////////////////////////////////////////////////////////////////////////////////
// base.js
////////////////////////////////////////////////////////////////////////////////

// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

if(typeof(WScript) === "undefined")
{
    var WScript = {
        Echo: print
    }
}

// Performance.now is used in latency benchmarks, the fallback is Date.now.
var performance = performance || {};
performance.now = (function() {
  return performance.now       ||
         performance.mozNow    ||
         performance.msNow     ||
         performance.oNow      ||
         performance.webkitNow ||
         Date.now;
})();

// Simple framework for running the benchmark suites and
// computing a score based on the timing measurements.


// A benchmark has a name (string) and a function that will be run to
// do the performance measurement. The optional setup and tearDown
// arguments are functions that will be invoked before and after
// running the benchmark, but the running time of these functions will
// not be accounted for in the benchmark score.
function Benchmark(name, doWarmup, doDeterministic, deterministicIterations, 
                   run, setup, tearDown, rmsResult, minIterations) {
  this.name = name;
  this.doWarmup = doWarmup;
  this.doDeterministic = doDeterministic;
  this.deterministicIterations = deterministicIterations;
  this.run = run;
  this.Setup = setup ? setup : function() { };
  this.TearDown = tearDown ? tearDown : function() { };
  this.rmsResult = rmsResult ? rmsResult : null; 
  this.minIterations = minIterations ? minIterations : 32;
}


// Benchmark results hold the benchmark and the measured time used to
// run the benchmark. The benchmark score is computed later once a
// full benchmark suite has run to completion. If latency is set to 0
// then there is no latency score for this benchmark.
function BenchmarkResult(benchmark, time, latency) {
  this.benchmark = benchmark;
  this.time = time;
  this.latency = latency;
}


// Automatically convert results to numbers. Used by the geometric
// mean computation.
BenchmarkResult.prototype.valueOf = function() {
  return this.time;
}


// Suites of benchmarks consist of a name and the set of benchmarks in
// addition to the reference timing that the final score will be based
// on. This way, all scores are relative to a reference run and higher
// scores implies better performance.
function BenchmarkSuite(name, reference, benchmarks) {
  this.name = name;
  this.reference = reference;
  this.benchmarks = benchmarks;
  BenchmarkSuite.suites.push(this);
}


// Keep track of all declared benchmark suites.
BenchmarkSuite.suites = [];

// Scores are not comparable across versions. Bump the version if
// you're making changes that will affect that scores, e.g. if you add
// a new benchmark or change an existing one.
BenchmarkSuite.version = '9';


// Defines global benchsuite running mode that overrides benchmark suite 
// behavior. Intended to be set by the benchmark driver. Undefined 
// values here allow a benchmark to define behaviour itself.
BenchmarkSuite.config = {
  doWarmup: undefined,
  doDeterministic: undefined
};


// Override the alert function to throw an exception instead.
alert = function(s) {
  throw "Alert called with argument: " + s;
};


// To make the benchmark results predictable, we replace Math.random
// with a 100% deterministic alternative.
BenchmarkSuite.ResetRNG = function() {
  Math.random = (function() {
    var seed = 49734321;
    return function() {
      // Robert Jenkins' 32 bit integer hash function.
      seed = ((seed + 0x7ed55d16) + (seed << 12))  & 0xffffffff;
      seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
      seed = ((seed + 0x165667b1) + (seed << 5))   & 0xffffffff;
      seed = ((seed + 0xd3a2646c) ^ (seed << 9))   & 0xffffffff;
      seed = ((seed + 0xfd7046c5) + (seed << 3))   & 0xffffffff;
      seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
      return (seed & 0xfffffff) / 0x10000000;
    };
  })();
}


// Runs all registered benchmark suites and optionally yields between
// each individual benchmark to avoid running for too long in the
// context of browsers. Once done, the final score is reported to the
// runner.
BenchmarkSuite.RunSuites = function(runner, skipBenchmarks) {
  skipBenchmarks = typeof skipBenchmarks === 'undefined' ? [] : skipBenchmarks;
  var continuation = null;
  var suites = BenchmarkSuite.suites;
  var length = suites.length;
  BenchmarkSuite.scores = [];
  var index = 0;
  function RunStep() {
    while (continuation || index < length) {
      if (continuation) {
        continuation = continuation();
      } else {
        var suite = suites[index++];
        if (runner.NotifyStart) runner.NotifyStart(suite.name);
        if (skipBenchmarks.indexOf(suite.name) > -1) {
          suite.NotifySkipped(runner);
        } else {
          continuation = suite.RunStep(runner);
        }
      }
      if (continuation && typeof window != 'undefined' && window.setTimeout) {
        window.setTimeout(RunStep, 25);
        return;
      }
    }

    // show final result
    if (runner.NotifyScore) {
      var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores);
      var formatted = BenchmarkSuite.FormatScore(100 * score);
      runner.NotifyScore(formatted);
    }
  }
  RunStep();
}


// Counts the total number of registered benchmarks. Useful for
// showing progress as a percentage.
BenchmarkSuite.CountBenchmarks = function() {
  var result = 0;
  var suites = BenchmarkSuite.suites;
  for (var i = 0; i < suites.length; i++) {
    result += suites[i].benchmarks.length;
  }
  return result;
}


// Computes the geometric mean of a set of numbers.
BenchmarkSuite.GeometricMean = function(numbers) {
  var log = 0;
  for (var i = 0; i < numbers.length; i++) {
    log += Math.log(numbers[i]);
  }
  return Math.pow(Math.E, log / numbers.length);
}


// Computes the geometric mean of a set of throughput time measurements.
BenchmarkSuite.GeometricMeanTime = function(measurements) {
  var log = 0;
  for (var i = 0; i < measurements.length; i++) {
    log += Math.log(measurements[i].time);
  }
  return Math.pow(Math.E, log / measurements.length);
}


// Computes the geometric mean of a set of rms measurements.
BenchmarkSuite.GeometricMeanLatency = function(measurements) {
  var log = 0;
  var hasLatencyResult = false;
  for (var i = 0; i < measurements.length; i++) {
    if (measurements[i].latency != 0) {
      log += Math.log(measurements[i].latency);
      hasLatencyResult = true;
    }
  }
  if (hasLatencyResult) {
    return Math.pow(Math.E, log / measurements.length);
  } else {
    return 0;
  }
}


// Converts a score value to a string with at least three significant
// digits.
BenchmarkSuite.FormatScore = function(value) {
  if (value > 100) {
    return value.toFixed(0);
  } else {
    return value.toPrecision(3);
  }
}

// Notifies the runner that we're done running a single benchmark in
// the benchmark suite. This can be useful to report progress.
BenchmarkSuite.prototype.NotifyStep = function(result) {
  this.results.push(result);
  if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name);
}


// Notifies the runner that we're done with running a suite and that
// we have a result which can be reported to the user if needed.
BenchmarkSuite.prototype.NotifyResult = function() {
  var mean = BenchmarkSuite.GeometricMeanTime(this.results);
  var score = this.reference[0] / mean;
  BenchmarkSuite.scores.push(score);
  if (this.runner.NotifyResult) {
    var formatted = BenchmarkSuite.FormatScore(100 * score);
    this.runner.NotifyResult(this.name, formatted);
  }
  if (this.reference.length == 2) {
    var meanLatency = BenchmarkSuite.GeometricMeanLatency(this.results);
    if (meanLatency != 0) {
      var scoreLatency = this.reference[1] / meanLatency;
      BenchmarkSuite.scores.push(scoreLatency);
      if (this.runner.NotifyResult) {
        var formattedLatency = BenchmarkSuite.FormatScore(100 * scoreLatency)
        this.runner.NotifyResult(this.name + "Latency", formattedLatency);
      }
    }
  }
}


BenchmarkSuite.prototype.NotifySkipped = function(runner) {
  BenchmarkSuite.scores.push(1);  // push default reference score.
  if (runner.NotifyResult) {
    runner.NotifyResult(this.name, "Skipped");
  }
}


// Notifies the runner that running a benchmark resulted in an error.
BenchmarkSuite.prototype.NotifyError = function(error) {
  if (this.runner.NotifyError) {
    this.runner.NotifyError(this.name, error);
  }
  if (this.runner.NotifyStep) {
    this.runner.NotifyStep(this.name);
  }
}


// Runs a single benchmark for at least a second and computes the
// average time it takes to run a single iteration.
BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) {
  var config = BenchmarkSuite.config;
  var doWarmup = config.doWarmup !== undefined 
                 ? config.doWarmup 
                 : benchmark.doWarmup;
  var doDeterministic = config.doDeterministic !== undefined 
                        ? config.doDeterministic 
                        : benchmark.doDeterministic;

  function Measure(data) {
    var elapsed = 0;
    var start = new Date();
  
  // Run either for 1 second or for the number of iterations specified
  // by minIterations, depending on the config flag doDeterministic.
    for (var i = 0; (doDeterministic ? 
      i<benchmark.deterministicIterations : elapsed < 1000); i++) {
      benchmark.run();
      elapsed = new Date() - start;
    }
    if (data != null) {
      data.runs += i;
      data.elapsed += elapsed;
    }
  }

  // Sets up data in order to skip or not the warmup phase.
  if (!doWarmup && data == null) {
    data = { runs: 0, elapsed: 0 };
  }

  if (data == null) {
    Measure(null);
    return { runs: 0, elapsed: 0 };
  } else {
    Measure(data);
    // If we've run too few iterations, we continue for another second.
    if (data.runs < benchmark.minIterations) return data;
    var usec = (data.elapsed * 1000) / data.runs;
    var rms = (benchmark.rmsResult != null) ? benchmark.rmsResult() : 0;
    this.NotifyStep(new BenchmarkResult(benchmark, usec, rms));
    return null;
  }
}


// This function starts running a suite, but stops between each
// individual benchmark in the suite and returns a continuation
// function which can be invoked to run the next benchmark. Once the
// last benchmark has been executed, null is returned.
BenchmarkSuite.prototype.RunStep = function(runner) {
  BenchmarkSuite.ResetRNG();
  this.results = [];
  this.runner = runner;
  var length = this.benchmarks.length;
  var index = 0;
  var suite = this;
  var data;

  // Run the setup, the actual benchmark, and the tear down in three
  // separate steps to allow the framework to yield between any of the
  // steps.

  function RunNextSetup() {
    if (index < length) {
      try {
        suite.benchmarks[index].Setup();
      } catch (e) {
        suite.NotifyError(e);
        return null;
      }
      return RunNextBenchmark;
    }
    suite.NotifyResult();
    return null;
  }

  function RunNextBenchmark() {
    try {
      data = suite.RunSingleBenchmark(suite.benchmarks[index], data);
    } catch (e) {
      suite.NotifyError(e);
      return null;
    }
    // If data is null, we're done with this benchmark.
    return (data == null) ? RunNextTearDown : RunNextBenchmark();
  }

  function RunNextTearDown() {
    try {
      suite.benchmarks[index++].TearDown();
    } catch (e) {
      suite.NotifyError(e);
      return null;
    }
    return RunNextSetup;
  }

  // Start out running the setup.
  return RunNextSetup();
}

/////////////////////////////////////////////////////////////////////////
// typescript.js
/////////////////////////////////////////////////////////////////////////

// Copyright 2013 the Octane Benchmark project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

var typescript = new BenchmarkSuite('Typescript', [255011322], [
  new Benchmark("Typescript",
                false,
                true,
                5,
                runTypescript,
                setupTypescript,
                tearDownTypescript,
                null,
                1)
]);


function setupTypescript() {
}


function tearDownTypescript() {
  compiler_input = null;
}


var parseErrors = [];


function runTypescript() {
  var compiler = createCompiler();
  compiler.addUnit(compiler_input, "compiler_input.ts");
  parseErrors = [];
  compiler.reTypeCheck();
  compiler.emit({
           createFile: function (fileName) { return outfile; },
           fileExists: function (path) { return false; },
           directoryExists: function (path) { return false; },
           resolvePath: function (path) { return path; }
  });
  
  if (parseErrors.length != 192 && parseErrors.length != 193) {
    throw new Error("Parse errors.");
  }
  compiler = null;
}

var outfile = {
  checksum: -412589664, 
  cumulative_checksum: 0,
  Write: function (s) { this.Verify(s); },
  WriteLine: function (s) { this.Verify(s + "\n"); },
  Close: function () {
    if (this.checksum != this.cumulative_checksum) {
      throw new Error("Wrong checksum.");
    }
    this.cumulative_checksum = 0;
  },
  Verify: function (s) {
    for(var i = 0; i < s.length; i++) {
      var c = s.charCodeAt(i);
      this.cumulative_checksum = (this.cumulative_checksum << 1) ^ c;
    }
  }
};


var outerr = {
  checksum: 0,
  cumulative_checksum: 0,
  Write: function (s) { this.Verify(s); },
  WriteLine: function (s) { this.Verify(s + "\n"); },
  Close: function () {
    if (this.checksum != this.cumulative_checksum) {
      throw new Error("Wrong checksum.");
    }
    this.cumulative_checksum = 0;
  },
  Verify: function (s) {
    for(var i = 0; i < s.length; i++) {
      var c = s.charCodeAt(i);
      this.cumulative_checksum = (this.cumulative_checksum << 1) ^ c;
    }
  }
};


function createCompiler() {
  var settings = new TypeScript.CompilationSettings();
  settings.codeGenTarget = TypeScript.CodeGenTarget.ES5;
  var compiler = new TypeScript.TypeScriptCompiler(
      outerr, new TypeScript.NullLogger, settings);
  compiler.setErrorCallback(function (start, len, message) { 
    parseErrors.push({ start: start, len: len, message: message }); 
  });
  compiler.parser.errorRecovery = true;
  compiler.typeCheck();
  return compiler
}


// The two files accompanying this benchmark contain a modified version of the
// Typescript compiler. They can be generated using the following instructions
// with the code available at:
//    http://typescript.codeplex.com/SourceControl/changeset/view/258e00903a9e
//
// 1) Copy the compiler from $TYPESCRIPT/bin/tsc.js to typescript-compiler.js
// 2) Remove the call to the batch compiler from the last line of tsc.js
// 3) Add this code after line 7963 (fix for Mozilla Firefox):
//    if (this.currentToken === undefined)
//      this.currentToken = this.scanner.scan();
// 4) Add this code after line 9142 (fix for Mozilla Firefox):
//    if (this.currentToken === undefined) {
//      this.currentToken = this.scanner.scan();
//      continue;
//    }
// 5) Generate the Typescript compiler input using the following command:
//    $ cat $TYPESCRIPT/src/compiler/*.ts | iconv -c -f utf8 -t ascii \
//      | dos2unix > /tmp/compiler_input
// 6) Run the following Python script to generate the reformatted input:
//    $ python script.py > typescript-input.js
//
// #!/usr/bin/env python
// import re;
// def escape_and_format(data, varname):
//   data = data.replace("\\", "\\\\").replace("\"", "\\\"")
//          .replace("\n", "\\n");
//   data = "var " + varname + " = \"" + data + "\""
//   print data; 
// result = open("/tmp/compiler_input", 'r');
// escape_and_format(result.read(), "compiler_input")
//
// The following is the original copyright notice present in the Typescript
// compiler source at the time this benchmark was generated:
//
/* *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved. 
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0  
 
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
MERCHANTABLITY OR NON-INFRINGEMENT. 
 
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */

////////////////////////////////////////////////////////////////////////
//	typescript-compiler.js
////////////////////////////////////////////////////////////////////////

var TypeScript;
(function (TypeScript) {
    function hasFlag(val, flag) {
        return (val & flag) != 0;
    }
    TypeScript.hasFlag = hasFlag;
    (function (ErrorRecoverySet) {
        ErrorRecoverySet._map = [];
        ErrorRecoverySet.None = 0;
        ErrorRecoverySet.Comma = 1;
        ErrorRecoverySet.SColon = 1 << 1;
        ErrorRecoverySet.Asg = 1 << 2;
        ErrorRecoverySet.BinOp = 1 << 3;
        ErrorRecoverySet.RBrack = 1 << 4;
        ErrorRecoverySet.RCurly = 1 << 5;
        ErrorRecoverySet.RParen = 1 << 6;
        ErrorRecoverySet.Dot = 1 << 7;
        ErrorRecoverySet.Colon = 1 << 8;
        ErrorRecoverySet.PrimType = 1 << 9;
        ErrorRecoverySet.AddOp = 1 << 10;
        ErrorRecoverySet.LCurly = 1 << 11;
        ErrorRecoverySet.PreOp = 1 << 12;
        ErrorRecoverySet.RegExp = 1 << 13;
        ErrorRecoverySet.LParen = 1 << 14;
        ErrorRecoverySet.LBrack = 1 << 15;
        ErrorRecoverySet.Scope = 1 << 16;
        ErrorRecoverySet.In = 1 << 17;
        ErrorRecoverySet.SCase = 1 << 18;
        ErrorRecoverySet.Else = 1 << 19;
        ErrorRecoverySet.Catch = 1 << 20;
        ErrorRecoverySet.Var = 1 << 21;
        ErrorRecoverySet.Stmt = 1 << 22;
        ErrorRecoverySet.While = 1 << 23;
        ErrorRecoverySet.ID = 1 << 24;
        ErrorRecoverySet.Prefix = 1 << 25;
        ErrorRecoverySet.Literal = 1 << 26;
        ErrorRecoverySet.RLit = 1 << 27;
        ErrorRecoverySet.Func = 1 << 28;
        ErrorRecoverySet.EOF = 1 << 29;
        ErrorRecoverySet.TypeScriptS = 1 << 30;
        ErrorRecoverySet.ExprStart = ErrorRecoverySet.SColon | ErrorRecoverySet.AddOp | ErrorRecoverySet.LCurly | ErrorRecoverySet.PreOp | ErrorRecoverySet.RegExp | ErrorRecoverySet.LParen | ErrorRecoverySet.LBrack | ErrorRecoverySet.ID | ErrorRecoverySet.Prefix | ErrorRecoverySet.RLit | ErrorRecoverySet.Func | ErrorRecoverySet.Literal;
        ErrorRecoverySet.StmtStart = ErrorRecoverySet.ExprStart | ErrorRecoverySet.SColon | ErrorRecoverySet.Var | ErrorRecoverySet.Stmt | ErrorRecoverySet.While | ErrorRecoverySet.TypeScriptS;
        ErrorRecoverySet.Postfix = ErrorRecoverySet.Dot | ErrorRecoverySet.LParen | ErrorRecoverySet.LBrack;
    })(TypeScript.ErrorRecoverySet || (TypeScript.ErrorRecoverySet = {}));
    var ErrorRecoverySet = TypeScript.ErrorRecoverySet;
    (function (AllowedElements) {
        AllowedElements._map = [];
        AllowedElements.None = 0;
        AllowedElements.ModuleDeclarations = 1 << 2;
        AllowedElements.ClassDeclarations = 1 << 3;
        AllowedElements.InterfaceDeclarations = 1 << 4;
        AllowedElements.AmbientDeclarations = 1 << 10;
        AllowedElements.Properties = 1 << 11;
        AllowedElements.Global = AllowedElements.ModuleDeclarations | AllowedElements.ClassDeclarations | AllowedElements.InterfaceDeclarations | AllowedElements.AmbientDeclarations;
        AllowedElements.QuickParse = AllowedElements.Global | AllowedElements.Properties;
    })(TypeScript.AllowedElements || (TypeScript.AllowedElements = {}));
    var AllowedElements = TypeScript.AllowedElements;
    (function (Modifiers) {
        Modifiers._map = [];
        Modifiers.None = 0;
        Modifiers.Private = 1;
        Modifiers.Public = 1 << 1;
        Modifiers.Readonly = 1 << 2;
        Modifiers.Ambient = 1 << 3;
        Modifiers.Exported = 1 << 4;
        Modifiers.Getter = 1 << 5;
        Modifiers.Setter = 1 << 6;
        Modifiers.Static = 1 << 7;
    })(TypeScript.Modifiers || (TypeScript.Modifiers = {}));
    var Modifiers = TypeScript.Modifiers;
    (function (ASTFlags) {
        ASTFlags._map = [];
        ASTFlags.None = 0;
        ASTFlags.ExplicitSemicolon = 1;
        ASTFlags.AutomaticSemicolon = 1 << 1;
        ASTFlags.Writeable = 1 << 2;
        ASTFlags.Error = 1 << 3;
        ASTFlags.DotLHSPartial = 1 << 4;
        ASTFlags.DotLHS = 1 << 5;
        ASTFlags.IsStatement = 1 << 6;
        ASTFlags.StrictMode = 1 << 7;
        ASTFlags.PossibleOptionalParameter = 1 << 8;
        ASTFlags.ClassBaseConstructorCall = 1 << 9;
        ASTFlags.OptionalName = 1 << 10;
        ASTFlags.SkipNextRParen = 1 << 11;
    })(TypeScript.ASTFlags || (TypeScript.ASTFlags = {}));
    var ASTFlags = TypeScript.ASTFlags;
    (function (DeclFlags) {
        DeclFlags._map = [];
        DeclFlags.None = 0;
        DeclFlags.Exported = 1;
        DeclFlags.Private = 1 << 1;
        DeclFlags.Public = 1 << 2;
        DeclFlags.Ambient = 1 << 3;
        DeclFlags.Static = 1 << 4;
        DeclFlags.LocalStatic = 1 << 5;
        DeclFlags.GetAccessor = 1 << 6;
        DeclFlags.SetAccessor = 1 << 7;
    })(TypeScript.DeclFlags || (TypeScript.DeclFlags = {}));
    var DeclFlags = TypeScript.DeclFlags;
    (function (ModuleFlags) {
        ModuleFlags._map = [];
        ModuleFlags.None = 0;
        ModuleFlags.Exported = 1;
        ModuleFlags.Private = 1 << 1;
        ModuleFlags.Public = 1 << 2;
        ModuleFlags.Ambient = 1 << 3;
        ModuleFlags.Static = 1 << 4;
        ModuleFlags.LocalStatic = 1 << 5;
        ModuleFlags.GetAccessor = 1 << 6;
        ModuleFlags.SetAccessor = 1 << 7;
        ModuleFlags.IsEnum = 1 << 8;
        ModuleFlags.ShouldEmitModuleDecl = 1 << 9;
        ModuleFlags.IsWholeFile = 1 << 10;
        ModuleFlags.IsDynamic = 1 << 11;
        ModuleFlags.MustCaptureThis = 1 << 12;
    })(TypeScript.ModuleFlags || (TypeScript.ModuleFlags = {}));
    var ModuleFlags = TypeScript.ModuleFlags;
    (function (SymbolFlags) {
        SymbolFlags._map = [];
        SymbolFlags.None = 0;
        SymbolFlags.Exported = 1;
        SymbolFlags.Private = 1 << 1;
        SymbolFlags.Public = 1 << 2;
        SymbolFlags.Ambient = 1 << 3;
        SymbolFlags.Static = 1 << 4;
        SymbolFlags.LocalStatic = 1 << 5;
        SymbolFlags.GetAccessor = 1 << 6;
        SymbolFlags.SetAccessor = 1 << 7;
        SymbolFlags.Property = 1 << 8;
        SymbolFlags.Readonly = 1 << 9;
        SymbolFlags.ModuleMember = 1 << 10;
        SymbolFlags.InterfaceMember = 1 << 11;
        SymbolFlags.ClassMember = 1 << 12;
        SymbolFlags.BuiltIn = 1 << 13;
        SymbolFlags.TypeSetDuringScopeAssignment = 1 << 14;
        SymbolFlags.Constant = 1 << 15;
        SymbolFlags.Optional = 1 << 16;
        SymbolFlags.RecursivelyReferenced = 1 << 17;
        SymbolFlags.Bound = 1 << 18;
        SymbolFlags.CompilerGenerated = 1 << 19;
    })(TypeScript.SymbolFlags || (TypeScript.SymbolFlags = {}));
    var SymbolFlags = TypeScript.SymbolFlags;
    (function (VarFlags) {
        VarFlags._map = [];
        VarFlags.None = 0;
        VarFlags.Exported = 1;
        VarFlags.Private = 1 << 1;
        VarFlags.Public = 1 << 2;
        VarFlags.Ambient = 1 << 3;
        VarFlags.Static = 1 << 4;
        VarFlags.LocalStatic = 1 << 5;
        VarFlags.GetAccessor = 1 << 6;
        VarFlags.SetAccessor = 1 << 7;
        VarFlags.AutoInit = 1 << 8;
        VarFlags.Property = 1 << 9;
        VarFlags.Readonly = 1 << 10;
        VarFlags.Class = 1 << 11;
        VarFlags.ClassProperty = 1 << 12;
        VarFlags.ClassBodyProperty = 1 << 13;
        VarFlags.ClassConstructorProperty = 1 << 14;
        VarFlags.ClassSuperMustBeFirstCallInConstructor = 1 << 15;
        VarFlags.Constant = 1 << 16;
        VarFlags.MustCaptureThis = 1 << 17;
    })(TypeScript.VarFlags || (TypeScript.VarFlags = {}));
    var VarFlags = TypeScript.VarFlags;
    (function (FncFlags) {
        FncFlags._map = [];
        FncFlags.None = 0;
        FncFlags.Exported = 1;
        FncFlags.Private = 1 << 1;
        FncFlags.Public = 1 << 2;
        FncFlags.Ambient = 1 << 3;
        FncFlags.Static = 1 << 4;
        FncFlags.LocalStatic = 1 << 5;
        FncFlags.GetAccessor = 1 << 6;
        FncFlags.SetAccessor = 1 << 7;
        FncFlags.Definition = 1 << 8;
        FncFlags.Signature = 1 << 9;
        FncFlags.Method = 1 << 10;
        FncFlags.HasReturnExpression = 1 << 11;
        FncFlags.CallMember = 1 << 12;
        FncFlags.ConstructMember = 1 << 13;
        FncFlags.HasSelfReference = 1 << 14;
        FncFlags.IsFatArrowFunction = 1 << 15;
        FncFlags.IndexerMember = 1 << 16;
        FncFlags.IsFunctionExpression = 1 << 17;
        FncFlags.ClassMethod = 1 << 18;
        FncFlags.ClassPropertyMethodExported = 1 << 19;
        FncFlags.HasSuperReferenceInFatArrowFunction = 1 << 20;
        FncFlags.IsPropertyBound = 1 << 21;
    })(TypeScript.FncFlags || (TypeScript.FncFlags = {}));
    var FncFlags = TypeScript.FncFlags;
    (function (SignatureFlags) {
        SignatureFlags._map = [];
        SignatureFlags.None = 0;
        SignatureFlags.IsIndexer = 1;
        SignatureFlags.IsStringIndexer = 1 << 1;
        SignatureFlags.IsNumberIndexer = 1 << 2;
    })(TypeScript.SignatureFlags || (TypeScript.SignatureFlags = {}));
    var SignatureFlags = TypeScript.SignatureFlags;
                    function ToDeclFlags(fncOrVarOrSymbolOrModuleFlags) {
        return fncOrVarOrSymbolOrModuleFlags;
    }
    TypeScript.ToDeclFlags = ToDeclFlags;
    (function (TypeFlags) {
        TypeFlags._map = [];
        TypeFlags.None = 0;
        TypeFlags.HasImplementation = 1;
        TypeFlags.HasSelfReference = 1 << 1;
        TypeFlags.MergeResult = 1 << 2;
        TypeFlags.IsEnum = 1 << 3;
        TypeFlags.BuildingName = 1 << 4;
        TypeFlags.HasBaseType = 1 << 5;
        TypeFlags.HasBaseTypeOfObject = 1 << 6;
        TypeFlags.IsClass = 1 << 7;
    })(TypeScript.TypeFlags || (TypeScript.TypeFlags = {}));
    var TypeFlags = TypeScript.TypeFlags;
    (function (TypeRelationshipFlags) {
        TypeRelationshipFlags._map = [];
        TypeRelationshipFlags.SuccessfulComparison = 0;
        TypeRelationshipFlags.SourceIsNullTargetIsVoidOrUndefined = 1;
        TypeRelationshipFlags.RequiredPropertyIsMissing = 1 << 1;
        TypeRelationshipFlags.IncompatibleSignatures = 1 << 2;
        TypeRelationshipFlags.SourceSignatureHasTooManyParameters = 3;
        TypeRelationshipFlags.IncompatibleReturnTypes = 1 << 4;
        TypeRelationshipFlags.IncompatiblePropertyTypes = 1 << 5;
        TypeRelationshipFlags.IncompatibleParameterTypes = 1 << 6;
    })(TypeScript.TypeRelationshipFlags || (TypeScript.TypeRelationshipFlags = {}));
    var TypeRelationshipFlags = TypeScript.TypeRelationshipFlags;
    (function (CodeGenTarget) {
        CodeGenTarget._map = [];
        CodeGenTarget.ES3 = 0;
        CodeGenTarget.ES5 = 1;
    })(TypeScript.CodeGenTarget || (TypeScript.CodeGenTarget = {}));
    var CodeGenTarget = TypeScript.CodeGenTarget;
    (function (ModuleGenTarget) {
        ModuleGenTarget._map = [];
        ModuleGenTarget.Synchronous = 0;
        ModuleGenTarget.Asynchronous = 1;
        ModuleGenTarget.Local = 1 << 1;
    })(TypeScript.ModuleGenTarget || (TypeScript.ModuleGenTarget = {}));
    var ModuleGenTarget = TypeScript.ModuleGenTarget;
    TypeScript.codeGenTarget = CodeGenTarget.ES3;
    TypeScript.moduleGenTarget = ModuleGenTarget.Synchronous;
    TypeScript.optimizeModuleCodeGen = true;
    function flagsToString(e, flags) {
        var builder = "";
        for(var i = 1; i < (1 << 31); i = i << 1) {
            if((flags & i) != 0) {
                for(var k in e) {
                    if(e[k] == i) {
                        if(builder.length > 0) {
                            builder += "|";
                        }
                        builder += k;
                        break;
                    }
                }
            }
        }
        return builder;
    }
    TypeScript.flagsToString = flagsToString;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (NodeType) {
        NodeType._map = [];
        NodeType._map[0] = "None";
        NodeType.None = 0;
        NodeType._map[1] = "Empty";
        NodeType.Empty = 1;
        NodeType._map[2] = "EmptyExpr";
        NodeType.EmptyExpr = 2;
        NodeType._map[3] = "True";
        NodeType.True = 3;
        NodeType._map[4] = "False";
        NodeType.False = 4;
        NodeType._map[5] = "This";
        NodeType.This = 5;
        NodeType._map[6] = "Super";
        NodeType.Super = 6;
        NodeType._map[7] = "QString";
        NodeType.QString = 7;
        NodeType._map[8] = "Regex";
        NodeType.Regex = 8;
        NodeType._map[9] = "Null";
        NodeType.Null = 9;
        NodeType._map[10] = "ArrayLit";
        NodeType.ArrayLit = 10;
        NodeType._map[11] = "ObjectLit";
        NodeType.ObjectLit = 11;
        NodeType._map[12] = "Void";
        NodeType.Void = 12;
        NodeType._map[13] = "Comma";
        NodeType.Comma = 13;
        NodeType._map[14] = "Pos";
        NodeType.Pos = 14;
        NodeType._map[15] = "Neg";
        NodeType.Neg = 15;
        NodeType._map[16] = "Delete";
        NodeType.Delete = 16;
        NodeType._map[17] = "Await";
        NodeType.Await = 17;
        NodeType._map[18] = "In";
        NodeType.In = 18;
        NodeType._map[19] = "Dot";
        NodeType.Dot = 19;
        NodeType._map[20] = "From";
        NodeType.From = 20;
        NodeType._map[21] = "Is";
        NodeType.Is = 21;
        NodeType._map[22] = "InstOf";
        NodeType.InstOf = 22;
        NodeType._map[23] = "Typeof";
        NodeType.Typeof = 23;
        NodeType._map[24] = "NumberLit";
        NodeType.NumberLit = 24;
        NodeType._map[25] = "Name";
        NodeType.Name = 25;
        NodeType._map[26] = "TypeRef";
        NodeType.TypeRef = 26;
        NodeType._map[27] = "Index";
        NodeType.Index = 27;
        NodeType._map[28] = "Call";
        NodeType.Call = 28;
        NodeType._map[29] = "New";
        NodeType.New = 29;
        NodeType._map[30] = "Asg";
        NodeType.Asg = 30;
        NodeType._map[31] = "AsgAdd";
        NodeType.AsgAdd = 31;
        NodeType._map[32] = "AsgSub";
        NodeType.AsgSub = 32;
        NodeType._map[33] = "AsgDiv";
        NodeType.AsgDiv = 33;
        NodeType._map[34] = "AsgMul";
        NodeType.AsgMul = 34;
        NodeType._map[35] = "AsgMod";
        NodeType.AsgMod = 35;
        NodeType._map[36] = "AsgAnd";
        NodeType.AsgAnd = 36;
        NodeType._map[37] = "AsgXor";
        NodeType.AsgXor = 37;
        NodeType._map[38] = "AsgOr";
        NodeType.AsgOr = 38;
        NodeType._map[39] = "AsgLsh";
        NodeType.AsgLsh = 39;
        NodeType._map[40] = "AsgRsh";
        NodeType.AsgRsh = 40;
        NodeType._map[41] = "AsgRs2";
        NodeType.AsgRs2 = 41;
        NodeType._map[42] = "ConditionalExpression";
        NodeType.ConditionalExpression = 42;
        NodeType._map[43] = "LogOr";
        NodeType.LogOr = 43;
        NodeType._map[44] = "LogAnd";
        NodeType.LogAnd = 44;
        NodeType._map[45] = "Or";
        NodeType.Or = 45;
        NodeType._map[46] = "Xor";
        NodeType.Xor = 46;
        NodeType._map[47] = "And";
        NodeType.And = 47;
        NodeType._map[48] = "Eq";
        NodeType.Eq = 48;
        NodeType._map[49] = "Ne";
        NodeType.Ne = 49;
        NodeType._map[50] = "Eqv";
        NodeType.Eqv = 50;
        NodeType._map[51] = "NEqv";
        NodeType.NEqv = 51;
        NodeType._map[52] = "Lt";
        NodeType.Lt = 52;
        NodeType._map[53] = "Le";
        NodeType.Le = 53;
        NodeType._map[54] = "Gt";
        NodeType.Gt = 54;
        NodeType._map[55] = "Ge";
        NodeType.Ge = 55;
        NodeType._map[56] = "Add";
        NodeType.Add = 56;
        NodeType._map[57] = "Sub";
        NodeType.Sub = 57;
        NodeType._map[58] = "Mul";
        NodeType.Mul = 58;
        NodeType._map[59] = "Div";
        NodeType.Div = 59;
        NodeType._map[60] = "Mod";
        NodeType.Mod = 60;
        NodeType._map[61] = "Lsh";
        NodeType.Lsh = 61;
        NodeType._map[62] = "Rsh";
        NodeType.Rsh = 62;
        NodeType._map[63] = "Rs2";
        NodeType.Rs2 = 63;
        NodeType._map[64] = "Not";
        NodeType.Not = 64;
        NodeType._map[65] = "LogNot";
        NodeType.LogNot = 65;
        NodeType._map[66] = "IncPre";
        NodeType.IncPre = 66;
        NodeType._map[67] = "DecPre";
        NodeType.DecPre = 67;
        NodeType._map[68] = "IncPost";
        NodeType.IncPost = 68;
        NodeType._map[69] = "DecPost";
        NodeType.DecPost = 69;
        NodeType._map[70] = "TypeAssertion";
        NodeType.TypeAssertion = 70;
        NodeType._map[71] = "FuncDecl";
        NodeType.FuncDecl = 71;
        NodeType._map[72] = "Member";
        NodeType.Member = 72;
        NodeType._map[73] = "VarDecl";
        NodeType.VarDecl = 73;
        NodeType._map[74] = "ArgDecl";
        NodeType.ArgDecl = 74;
        NodeType._map[75] = "Return";
        NodeType.Return = 75;
        NodeType._map[76] = "Break";
        NodeType.Break = 76;
        NodeType._map[77] = "Continue";
        NodeType.Continue = 77;
        NodeType._map[78] = "Throw";
        NodeType.Throw = 78;
        NodeType._map[79] = "For";
        NodeType.For = 79;
        NodeType._map[80] = "ForIn";
        NodeType.ForIn = 80;
        NodeType._map[81] = "If";
        NodeType.If = 81;
        NodeType._map[82] = "While";
        NodeType.While = 82;
        NodeType._map[83] = "DoWhile";
        NodeType.DoWhile = 83;
        NodeType._map[84] = "Block";
        NodeType.Block = 84;
        NodeType._map[85] = "Case";
        NodeType.Case = 85;
        NodeType._map[86] = "Switch";
        NodeType.Switch = 86;
        NodeType._map[87] = "Try";
        NodeType.Try = 87;
        NodeType._map[88] = "TryCatch";
        NodeType.TryCatch = 88;
        NodeType._map[89] = "TryFinally";
        NodeType.TryFinally = 89;
        NodeType._map[90] = "Finally";
        NodeType.Finally = 90;
        NodeType._map[91] = "Catch";
        NodeType.Catch = 91;
        NodeType._map[92] = "List";
        NodeType.List = 92;
        NodeType._map[93] = "Script";
        NodeType.Script = 93;
        NodeType._map[94] = "ClassDeclaration";
        NodeType.ClassDeclaration = 94;
        NodeType._map[95] = "InterfaceDeclaration";
        NodeType.InterfaceDeclaration = 95;
        NodeType._map[96] = "ModuleDeclaration";
        NodeType.ModuleDeclaration = 96;
        NodeType._map[97] = "ImportDeclaration";
        NodeType.ImportDeclaration = 97;
        NodeType._map[98] = "With";
        NodeType.With = 98;
        NodeType._map[99] = "Label";
        NodeType.Label = 99;
        NodeType._map[100] = "LabeledStatement";
        NodeType.LabeledStatement = 100;
        NodeType._map[101] = "EBStart";
        NodeType.EBStart = 101;
        NodeType._map[102] = "GotoEB";
        NodeType.GotoEB = 102;
        NodeType._map[103] = "EndCode";
        NodeType.EndCode = 103;
        NodeType._map[104] = "Error";
        NodeType.Error = 104;
        NodeType._map[105] = "Comment";
        NodeType.Comment = 105;
        NodeType._map[106] = "Debugger";
        NodeType.Debugger = 106;
        NodeType.GeneralNode = NodeType.FuncDecl;
        NodeType.LastAsg = NodeType.AsgRs2;
    })(TypeScript.NodeType || (TypeScript.NodeType = {}));
    var NodeType = TypeScript.NodeType;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var BlockIntrinsics = (function () {
        function BlockIntrinsics() {
            this.prototype = undefined;
            this.toString = undefined;
            this.toLocaleString = undefined;
            this.valueOf = undefined;
            this.hasOwnProperty = undefined;
            this.propertyIsEnumerable = undefined;
            this.isPrototypeOf = undefined;
            this["constructor"] = undefined;
        }
        return BlockIntrinsics;
    })();
    TypeScript.BlockIntrinsics = BlockIntrinsics;    
    var StringHashTable = (function () {
        function StringHashTable() {
            this.itemCount = 0;
            this.table = (new BlockIntrinsics());
        }
        StringHashTable.prototype.getAllKeys = function () {
            var result = [];
            for(var k in this.table) {
                if(this.table[k] != undefined) {
                    result[result.length] = k;
                }
            }
            return result;
        };
        StringHashTable.prototype.add = function (key, data) {
            if(this.table[key] != undefined) {
                return false;
            }
            this.table[key] = data;
            this.itemCount++;
            return true;
        };
        StringHashTable.prototype.addOrUpdate = function (key, data) {
            if(this.table[key] != undefined) {
                this.table[key] = data;
                return false;
            }
            this.table[key] = data;
            this.itemCount++;
            return true;
        };
        StringHashTable.prototype.map = function (fn, context) {
            for(var k in this.table) {
                var data = this.table[k];
                if(data != undefined) {
                    fn(k, this.table[k], context);
                }
            }
        };
        StringHashTable.prototype.every = function (fn, context) {
            for(var k in this.table) {
                var data = this.table[k];
                if(data != undefined) {
                    if(!fn(k, this.table[k], context)) {
                        return false;
                    }
                }
            }
            return true;
        };
        StringHashTable.prototype.some = function (fn, context) {
            for(var k in this.table) {
                var data = this.table[k];
                if(data != undefined) {
                    if(fn(k, this.table[k], context)) {
                        return true;
                    }
                }
            }
            return false;
        };
        StringHashTable.prototype.count = function () {
            return this.itemCount;
        };
        StringHashTable.prototype.lookup = function (key) {
            var data = this.table[key];
            if(data != undefined) {
                return data;
            } else {
                return (null);
            }
        };
        return StringHashTable;
    })();
    TypeScript.StringHashTable = StringHashTable;    
    var DualStringHashTable = (function () {
        function DualStringHashTable(primaryTable, secondaryTable) {
            this.primaryTable = primaryTable;
            this.secondaryTable = secondaryTable;
            this.insertPrimary = true;
        }
        DualStringHashTable.prototype.getAllKeys = function () {
            return this.primaryTable.getAllKeys().concat(this.secondaryTable.getAllKeys());
        };
        DualStringHashTable.prototype.add = function (key, data) {
            if(this.insertPrimary) {
                return this.primaryTable.add(key, data);
            } else {
                return this.secondaryTable.add(key, data);
            }
        };
        DualStringHashTable.prototype.addOrUpdate = function (key, data) {
            if(this.insertPrimary) {
                return this.primaryTable.addOrUpdate(key, data);
            } else {
                return this.secondaryTable.addOrUpdate(key, data);
            }
        };
        DualStringHashTable.prototype.map = function (fn, context) {
            this.primaryTable.map(fn, context);
            this.secondaryTable.map(fn, context);
        };
        DualStringHashTable.prototype.every = function (fn, context) {
            return this.primaryTable.every(fn, context) && this.secondaryTable.every(fn, context);
        };
        DualStringHashTable.prototype.some = function (fn, context) {
            return this.primaryTable.some(fn, context) || this.secondaryTable.some(fn, context);
        };
        DualStringHashTable.prototype.count = function () {
            return this.primaryTable.count() + this.secondaryTable.count();
        };
        DualStringHashTable.prototype.lookup = function (key) {
            var data = this.primaryTable.lookup(key);
            if(data != undefined) {
                return data;
            } else {
                return this.secondaryTable.lookup(key);
            }
        };
        return DualStringHashTable;
    })();
    TypeScript.DualStringHashTable = DualStringHashTable;    
    function numberHashFn(key) {
        var c2 = 668265261;
        key = (key ^ 61) ^ (key >>> 16);
        key = key + (key << 3);
        key = key ^ (key >>> 4);
        key = key * c2;
        key = key ^ (key >>> 15);
        return key;
    }
    TypeScript.numberHashFn = numberHashFn;
    function combineHashes(key1, key2) {
        return key2 ^ ((key1 >> 5) + key1);
    }
    TypeScript.combineHashes = combineHashes;
    var HashEntry = (function () {
        function HashEntry(key, data) {
            this.key = key;
            this.data = data;
        }
        return HashEntry;
    })();
    TypeScript.HashEntry = HashEntry;    
    var HashTable = (function () {
        function HashTable(size, hashFn, equalsFn) {
            this.size = size;
            this.hashFn = hashFn;
            this.equalsFn = equalsFn;
            this.itemCount = 0;
            this.table = new Array();
            for(var i = 0; i < this.size; i++) {
                this.table[i] = null;
            }
        }
        HashTable.prototype.add = function (key, data) {
            var current;
            var entry = new HashEntry(key, data);
            var val = this.hashFn(key);
            val = val % this.size;
            for(current = this.table[val]; current != null; current = current.next) {
                if(this.equalsFn(key, current.key)) {
                    return false;
                }
            }
            entry.next = this.table[val];
            this.table[val] = entry;
            this.itemCount++;
            return true;
        };
        HashTable.prototype.remove = function (key) {
            var current;
            var val = this.hashFn(key);
            val = val % this.size;
            var result = null;
            var prevEntry = null;
            for(current = this.table[val]; current != null; current = current.next) {
                if(this.equalsFn(key, current.key)) {
                    result = current.data;
                    this.itemCount--;
                    if(prevEntry) {
                        prevEntry.next = current.next;
                    } else {
                        this.table[val] = current.next;
                    }
                    break;
                }
                prevEntry = current;
            }
            return result;
        };
        HashTable.prototype.count = function () {
            return this.itemCount;
        };
        HashTable.prototype.lookup = function (key) {
            var current;
            var val = this.hashFn(key);
            val = val % this.size;
            for(current = this.table[val]; current != null; current = current.next) {
                if(this.equalsFn(key, current.key)) {
                    return (current.data);
                }
            }
            return (null);
        };
        return HashTable;
    })();
    TypeScript.HashTable = HashTable;    
    var SimpleHashTable = (function () {
        function SimpleHashTable() {
            this.keys = [];
            this.values = [];
        }
        SimpleHashTable.prototype.lookup = function (key, findValue) {
            var searchArray = this.keys;
            if(findValue) {
                searchArray = this.values;
            }
            for(var i = 0; i < searchArray.length; i++) {
                if(searchArray[i] == key) {
                    return {
                        key: this.keys[i],
                        data: this.values[i]
                    };
                }
            }
            return null;
        };
        SimpleHashTable.prototype.add = function (key, data) {
            var lookupData = this.lookup(key);
            if(lookupData) {
                return false;
            }
            this.keys[this.keys.length] = key;
            this.values[this.values.length] = data;
            return true;
        };
        return SimpleHashTable;
    })();
    TypeScript.SimpleHashTable = SimpleHashTable;    
})(TypeScript || (TypeScript = {}));
var __extends = this.__extends || function (d, b) {
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var TypeScript;
(function (TypeScript) {
    var ASTSpan = (function () {
        function ASTSpan() {
            this.minChar = -1;
            this.limChar = -1;
        }
        return ASTSpan;
    })();
    TypeScript.ASTSpan = ASTSpan;    
    var AST = (function (_super) {
        __extends(AST, _super);
        function AST(nodeType) {
                _super.call(this);
            this.nodeType = nodeType;
            this.type = null;
            this.flags = TypeScript.ASTFlags.Writeable;
            this.passCreated = TypeScript.CompilerDiagnostics.analysisPass;
            this.preComments = null;
            this.postComments = null;
            this.docComments = null;
            this.isParenthesized = false;
        }
        AST.prototype.isExpression = function () {
            return false;
        };
        AST.prototype.isStatementOrExpression = function () {
            return false;
        };
        AST.prototype.isCompoundStatement = function () {
            return false;
        };
        AST.prototype.isLeaf = function () {
            return this.isStatementOrExpression() && (!this.isCompoundStatement());
        };
        AST.prototype.isDeclaration = function () {
            return false;
        };
        AST.prototype.typeCheck = function (typeFlow) {
            switch(this.nodeType) {
                case TypeScript.NodeType.Error:
                case TypeScript.NodeType.EmptyExpr: {
                    this.type = typeFlow.anyType;
                    break;

                }
                case TypeScript.NodeType.This: {
                    return typeFlow.typeCheckThis(this);

                }
                case TypeScript.NodeType.Null: {
                    this.type = typeFlow.nullType;
                    break;

                }
                case TypeScript.NodeType.False:
                case TypeScript.NodeType.True: {
                    this.type = typeFlow.booleanType;
                    break;

                }
                case TypeScript.NodeType.Super: {
                    return typeFlow.typeCheckSuper(this);

                }
                case TypeScript.NodeType.EndCode:
                case TypeScript.NodeType.Empty:
                case TypeScript.NodeType.Void: {
                    this.type = typeFlow.voidType;
                    break;

                }
                default: {
                    throw new Error("please implement in derived class");

                }
            }
            return this;
        };
        AST.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            switch(this.nodeType) {
                case TypeScript.NodeType.This: {
                    emitter.recordSourceMappingStart(this);
                    if(emitter.thisFnc && (TypeScript.hasFlag(emitter.thisFnc.fncFlags, TypeScript.FncFlags.IsFatArrowFunction))) {
                        emitter.writeToOutput("_this");
                    } else {
                        emitter.writeToOutput("this");
                    }
                    emitter.recordSourceMappingEnd(this);
                    break;

                }
                case TypeScript.NodeType.Null: {
                    emitter.recordSourceMappingStart(this);
                    emitter.writeToOutput("null");
                    emitter.recordSourceMappingEnd(this);
                    break;

                }
                case TypeScript.NodeType.False: {
                    emitter.recordSourceMappingStart(this);
                    emitter.writeToOutput("false");
                    emitter.recordSourceMappingEnd(this);
                    break;

                }
                case TypeScript.NodeType.True: {
                    emitter.recordSourceMappingStart(this);
                    emitter.writeToOutput("true");
                    emitter.recordSourceMappingEnd(this);
                    break;

                }
                case TypeScript.NodeType.Super: {
                    emitter.recordSourceMappingStart(this);
                    emitter.emitSuperReference();
                    emitter.recordSourceMappingEnd(this);
                    break;

                }
                case TypeScript.NodeType.EndCode:
                case TypeScript.NodeType.Error:
                case TypeScript.NodeType.EmptyExpr: {
                    break;

                }
                case TypeScript.NodeType.Empty: {
                    emitter.recordSourceMappingStart(this);
                    emitter.recordSourceMappingEnd(this);
                    break;

                }
                case TypeScript.NodeType.Void: {
                    emitter.recordSourceMappingStart(this);
                    emitter.writeToOutput("void ");
                    emitter.recordSourceMappingEnd(this);
                    break;

                }
                default: {
                    throw new Error("please implement in derived class");

                }
            }
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        AST.prototype.print = function (context) {
            context.startLine();
            var lineCol = {
                line: -1,
                col: -1
            };
            var limLineCol = {
                line: -1,
                col: -1
            };
            if(context.parser !== null) {
                context.parser.getSourceLineCol(lineCol, this.minChar);
                context.parser.getSourceLineCol(limLineCol, this.limChar);
                context.write("(" + lineCol.line + "," + lineCol.col + ")--" + "(" + limLineCol.line + "," + limLineCol.col + "): ");
            }
            var lab = this.printLabel();
            if(TypeScript.hasFlag(this.flags, TypeScript.ASTFlags.Error)) {
                lab += " (Error)";
            }
            context.writeLine(lab);
        };
        AST.prototype.printLabel = function () {
            if(TypeScript.nodeTypeTable[this.nodeType] !== undefined) {
                return TypeScript.nodeTypeTable[this.nodeType];
            } else {
                return (TypeScript.NodeType)._map[this.nodeType];
            }
        };
        AST.prototype.addToControlFlow = function (context) {
            context.walker.options.goChildren = false;
            context.addContent(this);
        };
        AST.prototype.netFreeUses = function (container, freeUses) {
        };
        AST.prototype.treeViewLabel = function () {
            return (TypeScript.NodeType)._map[this.nodeType];
        };
        AST.getResolvedIdentifierName = function getResolvedIdentifierName(name) {
            if(!name) {
                return "";
            }
            var resolved = "";
            var start = 0;
            var i = 0;
            while(i <= name.length - 6) {
                if(name.charAt(i) == '\\' && name.charAt(i + 1) == 'u') {
                    var charCode = parseInt(name.substr(i + 2, 4), 16);
                    resolved += name.substr(start, i - start);
                    resolved += String.fromCharCode(charCode);
                    i += 6;
                    start = i;
                    continue;
                }
                i++;
            }
            resolved += name.substring(start);
            return resolved;
        }
        AST.prototype.getDocComments = function () {
            if(!this.isDeclaration() || !this.preComments || this.preComments.length == 0) {
                return [];
            }
            if(!this.docComments) {
                var preCommentsLength = this.preComments.length;
                var docComments = [];
                for(var i = preCommentsLength - 1; i >= 0; i--) {
                    if(this.preComments[i].isDocComment()) {
                        var prevDocComment = docComments.length > 0 ? docComments[docComments.length - 1] : null;
                        if(prevDocComment == null || (this.preComments[i].limLine == prevDocComment.minLine || this.preComments[i].limLine + 1 == prevDocComment.minLine)) {
                            docComments.push(this.preComments[i]);
                            continue;
                        }
                    }
                    break;
                }
                this.docComments = docComments.reverse();
            }
            return this.docComments;
        };
        return AST;
    })(ASTSpan);
    TypeScript.AST = AST;    
    var IncompleteAST = (function (_super) {
        __extends(IncompleteAST, _super);
        function IncompleteAST(min, lim) {
                _super.call(this, TypeScript.NodeType.Error);
            this.minChar = min;
            this.limChar = lim;
        }
        return IncompleteAST;
    })(AST);
    TypeScript.IncompleteAST = IncompleteAST;    
    var ASTList = (function (_super) {
        __extends(ASTList, _super);
        function ASTList() {
                _super.call(this, TypeScript.NodeType.List);
            this.enclosingScope = null;
            this.members = new Array();
        }
        ASTList.prototype.addToControlFlow = function (context) {
            var len = this.members.length;
            for(var i = 0; i < len; i++) {
                if(context.noContinuation) {
                    context.addUnreachable(this.members[i]);
                    break;
                } else {
                    this.members[i] = context.walk(this.members[i], this);
                }
            }
            context.walker.options.goChildren = false;
        };
        ASTList.prototype.append = function (ast) {
            this.members[this.members.length] = ast;
            return this;
        };
        ASTList.prototype.appendAll = function (ast) {
            if(ast.nodeType == TypeScript.NodeType.List) {
                var list = ast;
                for(var i = 0, len = list.members.length; i < len; i++) {
                    this.append(list.members[i]);
                }
            } else {
                this.append(ast);
            }
            return this;
        };
        ASTList.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.recordSourceMappingStart(this);
            emitter.emitJavascriptList(this, null, TypeScript.TokenID.Semicolon, startLine, false, false);
            emitter.recordSourceMappingEnd(this);
        };
        ASTList.prototype.typeCheck = function (typeFlow) {
            var len = this.members.length;
            typeFlow.nestingLevel++;
            for(var i = 0; i < len; i++) {
                if(this.members[i]) {
                    this.members[i] = this.members[i].typeCheck(typeFlow);
                }
            }
            typeFlow.nestingLevel--;
            return this;
        };
        return ASTList;
    })(AST);
    TypeScript.ASTList = ASTList;    
    var Identifier = (function (_super) {
        __extends(Identifier, _super);
        function Identifier(actualText, hasEscapeSequence) {
                _super.call(this, TypeScript.NodeType.Name);
            this.actualText = actualText;
            this.hasEscapeSequence = hasEscapeSequence;
            this.sym = null;
            this.cloId = -1;
            this.setText(actualText, hasEscapeSequence);
        }
        Identifier.prototype.setText = function (actualText, hasEscapeSequence) {
            this.actualText = actualText;
            if(hasEscapeSequence) {
                this.text = AST.getResolvedIdentifierName(actualText);
            } else {
                this.text = actualText;
            }
        };
        Identifier.prototype.isMissing = function () {
            return false;
        };
        Identifier.prototype.isLeaf = function () {
            return true;
        };
        Identifier.prototype.treeViewLabel = function () {
            return "id: " + this.actualText;
        };
        Identifier.prototype.printLabel = function () {
            if(this.actualText) {
                return "id: " + this.actualText;
            } else {
                return "name node";
            }
        };
        Identifier.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckName(this);
        };
        Identifier.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitJavascriptName(this, true);
        };
        Identifier.fromToken = function fromToken(token) {
            return new Identifier(token.getText(), (token).hasEscapeSequence);
        }
        return Identifier;
    })(AST);
    TypeScript.Identifier = Identifier;    
    var MissingIdentifier = (function (_super) {
        __extends(MissingIdentifier, _super);
        function MissingIdentifier() {
                _super.call(this, "__missing");
        }
        MissingIdentifier.prototype.isMissing = function () {
            return true;
        };
        MissingIdentifier.prototype.emit = function (emitter, tokenId, startLine) {
        };
        return MissingIdentifier;
    })(Identifier);
    TypeScript.MissingIdentifier = MissingIdentifier;    
    var Label = (function (_super) {
        __extends(Label, _super);
        function Label(id) {
                _super.call(this, TypeScript.NodeType.Label);
            this.id = id;
        }
        Label.prototype.printLabel = function () {
            return this.id.actualText + ":";
        };
        Label.prototype.typeCheck = function (typeFlow) {
            this.type = typeFlow.voidType;
            return this;
        };
        Label.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.recordSourceMappingStart(this.id);
            emitter.writeToOutput(this.id.actualText);
            emitter.recordSourceMappingEnd(this.id);
            emitter.writeLineToOutput(":");
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return Label;
    })(AST);
    TypeScript.Label = Label;    
    var Expression = (function (_super) {
        __extends(Expression, _super);
        function Expression(nodeType) {
                _super.call(this, nodeType);
        }
        Expression.prototype.isExpression = function () {
            return true;
        };
        Expression.prototype.isStatementOrExpression = function () {
            return true;
        };
        return Expression;
    })(AST);
    TypeScript.Expression = Expression;    
    var UnaryExpression = (function (_super) {
        __extends(UnaryExpression, _super);
        function UnaryExpression(nodeType, operand) {
                _super.call(this, nodeType);
            this.operand = operand;
            this.targetType = null;
            this.castTerm = null;
        }
        UnaryExpression.prototype.addToControlFlow = function (context) {
            _super.prototype.addToControlFlow.call(this, context);
            if(this.nodeType == TypeScript.NodeType.Throw) {
                context.returnStmt();
            }
        };
        UnaryExpression.prototype.typeCheck = function (typeFlow) {
            switch(this.nodeType) {
                case TypeScript.NodeType.Not: {
                    return typeFlow.typeCheckBitNot(this);

                }
                case TypeScript.NodeType.LogNot: {
                    return typeFlow.typeCheckLogNot(this);

                }
                case TypeScript.NodeType.Pos:
                case TypeScript.NodeType.Neg: {
                    return typeFlow.typeCheckUnaryNumberOperator(this);

                }
                case TypeScript.NodeType.IncPost:
                case TypeScript.NodeType.IncPre:
                case TypeScript.NodeType.DecPost:
                case TypeScript.NodeType.DecPre: {
                    return typeFlow.typeCheckIncOrDec(this);

                }
                case TypeScript.NodeType.ArrayLit: {
                    typeFlow.typeCheckArrayLit(this);
                    return this;

                }
                case TypeScript.NodeType.ObjectLit: {
                    typeFlow.typeCheckObjectLit(this);
                    return this;

                }
                case TypeScript.NodeType.Throw: {
                    this.operand = typeFlow.typeCheck(this.operand);
                    this.type = typeFlow.voidType;
                    return this;

                }
                case TypeScript.NodeType.Typeof: {
                    this.operand = typeFlow.typeCheck(this.operand);
                    this.type = typeFlow.stringType;
                    return this;

                }
                case TypeScript.NodeType.Delete: {
                    this.operand = typeFlow.typeCheck(this.operand);
                    this.type = typeFlow.booleanType;
                    break;

                }
                case TypeScript.NodeType.TypeAssertion: {
                    this.castTerm = typeFlow.typeCheck(this.castTerm);
                    var applyTargetType = !this.operand.isParenthesized;
                    var targetType = applyTargetType ? this.castTerm.type : null;
                    typeFlow.checker.typeCheckWithContextualType(targetType, typeFlow.checker.inProvisionalTypecheckMode(), true, this.operand);
                    typeFlow.castWithCoercion(this.operand, this.castTerm.type, false, true);
                    this.type = this.castTerm.type;
                    return this;

                }
                case TypeScript.NodeType.Void: {
                    this.operand = typeFlow.typeCheck(this.operand);
                    this.type = typeFlow.checker.undefinedType;
                    break;

                }
                default: {
                    throw new Error("please implement in derived class");

                }
            }
            return this;
        };
        UnaryExpression.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            switch(this.nodeType) {
                case TypeScript.NodeType.IncPost: {
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.PlusPlus, false);
                    emitter.writeToOutput("++");
                    break;

                }
                case TypeScript.NodeType.LogNot: {
                    emitter.writeToOutput("!");
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Exclamation, false);
                    break;

                }
                case TypeScript.NodeType.DecPost: {
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.MinusMinus, false);
                    emitter.writeToOutput("--");
                    break;

                }
                case TypeScript.NodeType.ObjectLit: {
                    emitter.emitObjectLiteral(this.operand);
                    break;

                }
                case TypeScript.NodeType.ArrayLit: {
                    emitter.emitArrayLiteral(this.operand);
                    break;

                }
                case TypeScript.NodeType.Not: {
                    emitter.writeToOutput("~");
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Tilde, false);
                    break;

                }
                case TypeScript.NodeType.Neg: {
                    emitter.writeToOutput("-");
                    if(this.operand.nodeType == TypeScript.NodeType.Neg) {
                        this.operand.isParenthesized = true;
                    }
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Minus, false);
                    break;

                }
                case TypeScript.NodeType.Pos: {
                    emitter.writeToOutput("+");
                    if(this.operand.nodeType == TypeScript.NodeType.Pos) {
                        this.operand.isParenthesized = true;
                    }
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Plus, false);
                    break;

                }
                case TypeScript.NodeType.IncPre: {
                    emitter.writeToOutput("++");
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.PlusPlus, false);
                    break;

                }
                case TypeScript.NodeType.DecPre: {
                    emitter.writeToOutput("--");
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.MinusMinus, false);
                    break;

                }
                case TypeScript.NodeType.Throw: {
                    emitter.writeToOutput("throw ");
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Tilde, false);
                    emitter.writeToOutput(";");
                    break;

                }
                case TypeScript.NodeType.Typeof: {
                    emitter.writeToOutput("typeof ");
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Tilde, false);
                    break;

                }
                case TypeScript.NodeType.Delete: {
                    emitter.writeToOutput("delete ");
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Tilde, false);
                    break;

                }
                case TypeScript.NodeType.Void: {
                    emitter.writeToOutput("void ");
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Tilde, false);
                    break;

                }
                case TypeScript.NodeType.TypeAssertion: {
                    emitter.emitJavascript(this.operand, TypeScript.TokenID.Tilde, false);
                    break;

                }
                default: {
                    throw new Error("please implement in derived class");

                }
            }
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return UnaryExpression;
    })(Expression);
    TypeScript.UnaryExpression = UnaryExpression;    
    var CallExpression = (function (_super) {
        __extends(CallExpression, _super);
        function CallExpression(nodeType, target, arguments) {
                _super.call(this, nodeType);
            this.target = target;
            this.arguments = arguments;
            this.signature = null;
            this.minChar = this.target.minChar;
        }
        CallExpression.prototype.typeCheck = function (typeFlow) {
            if(this.nodeType == TypeScript.NodeType.New) {
                return typeFlow.typeCheckNew(this);
            } else {
                return typeFlow.typeCheckCall(this);
            }
        };
        CallExpression.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            if(this.nodeType == TypeScript.NodeType.New) {
                emitter.emitNew(this.target, this.arguments);
            } else {
                emitter.emitCall(this, this.target, this.arguments);
            }
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return CallExpression;
    })(Expression);
    TypeScript.CallExpression = CallExpression;    
    var BinaryExpression = (function (_super) {
        __extends(BinaryExpression, _super);
        function BinaryExpression(nodeType, operand1, operand2) {
                _super.call(this, nodeType);
            this.operand1 = operand1;
            this.operand2 = operand2;
        }
        BinaryExpression.prototype.typeCheck = function (typeFlow) {
            switch(this.nodeType) {
                case TypeScript.NodeType.Dot: {
                    return typeFlow.typeCheckDotOperator(this);

                }
                case TypeScript.NodeType.Asg: {
                    return typeFlow.typeCheckAsgOperator(this);

                }
                case TypeScript.NodeType.Add:
                case TypeScript.NodeType.Sub:
                case TypeScript.NodeType.Mul:
                case TypeScript.NodeType.Div:
                case TypeScript.NodeType.Mod:
                case TypeScript.NodeType.Or:
                case TypeScript.NodeType.And: {
                    return typeFlow.typeCheckArithmeticOperator(this, false);

                }
                case TypeScript.NodeType.Xor: {
                    return typeFlow.typeCheckBitwiseOperator(this, false);

                }
                case TypeScript.NodeType.Ne:
                case TypeScript.NodeType.Eq: {
                    var text;
                    if(typeFlow.checker.styleSettings.eqeqeq) {
                        text = TypeScript.nodeTypeTable[this.nodeType];
                        typeFlow.checker.errorReporter.styleError(this, "use of " + text);
                    } else {
                        if(typeFlow.checker.styleSettings.eqnull) {
                            text = TypeScript.nodeTypeTable[this.nodeType];
                            if((this.operand2 !== null) && (this.operand2.nodeType == TypeScript.NodeType.Null)) {
                                typeFlow.checker.errorReporter.styleError(this, "use of " + text + " to compare with null");
                            }
                        }
                    }

                }
                case TypeScript.NodeType.Eqv:
                case TypeScript.NodeType.NEqv:
                case TypeScript.NodeType.Lt:
                case TypeScript.NodeType.Le:
                case TypeScript.NodeType.Ge:
                case TypeScript.NodeType.Gt: {
                    return typeFlow.typeCheckBooleanOperator(this);

                }
                case TypeScript.NodeType.Index: {
                    return typeFlow.typeCheckIndex(this);

                }
                case TypeScript.NodeType.Member: {
                    this.type = typeFlow.voidType;
                    return this;

                }
                case TypeScript.NodeType.LogOr: {
                    return typeFlow.typeCheckLogOr(this);

                }
                case TypeScript.NodeType.LogAnd: {
                    return typeFlow.typeCheckLogAnd(this);

                }
                case TypeScript.NodeType.AsgAdd:
                case TypeScript.NodeType.AsgSub:
                case TypeScript.NodeType.AsgMul:
                case TypeScript.NodeType.AsgDiv:
                case TypeScript.NodeType.AsgMod:
                case TypeScript.NodeType.AsgOr:
                case TypeScript.NodeType.AsgAnd: {
                    return typeFlow.typeCheckArithmeticOperator(this, true);

                }
                case TypeScript.NodeType.AsgXor: {
                    return typeFlow.typeCheckBitwiseOperator(this, true);

                }
                case TypeScript.NodeType.Lsh:
                case TypeScript.NodeType.Rsh:
                case TypeScript.NodeType.Rs2: {
                    return typeFlow.typeCheckShift(this, false);

                }
                case TypeScript.NodeType.AsgLsh:
                case TypeScript.NodeType.AsgRsh:
                case TypeScript.NodeType.AsgRs2: {
                    return typeFlow.typeCheckShift(this, true);

                }
                case TypeScript.NodeType.Comma: {
                    return typeFlow.typeCheckCommaOperator(this);

                }
                case TypeScript.NodeType.InstOf: {
                    return typeFlow.typeCheckInstOf(this);

                }
                case TypeScript.NodeType.In: {
                    return typeFlow.typeCheckInOperator(this);

                }
                case TypeScript.NodeType.From: {
                    typeFlow.checker.errorReporter.simpleError(this, "Illegal use of 'from' keyword in binary expression");
                    break;

                }
                default: {
                    throw new Error("please implement in derived class");

                }
            }
            return this;
        };
        BinaryExpression.prototype.emit = function (emitter, tokenId, startLine) {
            var binTokenId = TypeScript.nodeTypeToTokTable[this.nodeType];
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            if(binTokenId != undefined) {
                emitter.emitJavascript(this.operand1, binTokenId, false);
                if(TypeScript.tokenTable[binTokenId].text == "instanceof") {
                    emitter.writeToOutput(" instanceof ");
                } else {
                    if(TypeScript.tokenTable[binTokenId].text == "in") {
                        emitter.writeToOutput(" in ");
                    } else {
                        emitter.writeToOutputTrimmable(" " + TypeScript.tokenTable[binTokenId].text + " ");
                    }
                }
                emitter.emitJavascript(this.operand2, binTokenId, false);
            } else {
                switch(this.nodeType) {
                    case TypeScript.NodeType.Dot: {
                        if(!emitter.tryEmitConstant(this)) {
                            emitter.emitJavascript(this.operand1, TypeScript.TokenID.Dot, false);
                            emitter.writeToOutput(".");
                            emitter.emitJavascriptName(this.operand2, false);
                        }
                        break;

                    }
                    case TypeScript.NodeType.Index: {
                        emitter.emitIndex(this.operand1, this.operand2);
                        break;

                    }
                    case TypeScript.NodeType.Member: {
                        if(this.operand2.nodeType == TypeScript.NodeType.FuncDecl && (this.operand2).isAccessor()) {
                            var funcDecl = this.operand2;
                            if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor)) {
                                emitter.writeToOutput("get ");
                            } else {
                                emitter.writeToOutput("set ");
                            }
                            emitter.emitJavascript(this.operand1, TypeScript.TokenID.Colon, false);
                        } else {
                            emitter.emitJavascript(this.operand1, TypeScript.TokenID.Colon, false);
                            emitter.writeToOutputTrimmable(": ");
                        }
                        emitter.emitJavascript(this.operand2, TypeScript.TokenID.Comma, false);
                        break;

                    }
                    case TypeScript.NodeType.Comma: {
                        emitter.emitJavascript(this.operand1, TypeScript.TokenID.Comma, false);
                        if(emitter.emitState.inObjectLiteral) {
                            emitter.writeLineToOutput(", ");
                        } else {
                            emitter.writeToOutput(",");
                        }
                        emitter.emitJavascript(this.operand2, TypeScript.TokenID.Comma, false);
                        break;

                    }
                    case TypeScript.NodeType.Is: {
                        throw new Error("should be de-sugared during type check");

                    }
                    default: {
                        throw new Error("please implement in derived class");

                    }
                }
            }
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return BinaryExpression;
    })(Expression);
    TypeScript.BinaryExpression = BinaryExpression;    
    var ConditionalExpression = (function (_super) {
        __extends(ConditionalExpression, _super);
        function ConditionalExpression(operand1, operand2, operand3) {
                _super.call(this, TypeScript.NodeType.ConditionalExpression);
            this.operand1 = operand1;
            this.operand2 = operand2;
            this.operand3 = operand3;
        }
        ConditionalExpression.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckQMark(this);
        };
        ConditionalExpression.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.emitJavascript(this.operand1, TypeScript.TokenID.Question, false);
            emitter.writeToOutput(" ? ");
            emitter.emitJavascript(this.operand2, TypeScript.TokenID.Question, false);
            emitter.writeToOutput(" : ");
            emitter.emitJavascript(this.operand3, TypeScript.TokenID.Question, false);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return ConditionalExpression;
    })(Expression);
    TypeScript.ConditionalExpression = ConditionalExpression;    
    var NumberLiteral = (function (_super) {
        __extends(NumberLiteral, _super);
        function NumberLiteral(value, hasEmptyFraction) {
                _super.call(this, TypeScript.NodeType.NumberLit);
            this.value = value;
            this.hasEmptyFraction = hasEmptyFraction;
            this.isNegativeZero = false;
        }
        NumberLiteral.prototype.typeCheck = function (typeFlow) {
            this.type = typeFlow.doubleType;
            return this;
        };
        NumberLiteral.prototype.treeViewLabel = function () {
            return "num: " + this.printLabel();
        };
        NumberLiteral.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            if(this.isNegativeZero) {
                emitter.writeToOutput("-");
            }
            emitter.writeToOutput(this.value.toString());
            if(this.hasEmptyFraction) {
                emitter.writeToOutput(".0");
            }
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        NumberLiteral.prototype.printLabel = function () {
            if(Math.floor(this.value) != this.value) {
                return this.value.toFixed(2).toString();
            } else {
                if(this.hasEmptyFraction) {
                    return this.value.toString() + ".0";
                } else {
                    return this.value.toString();
                }
            }
        };
        return NumberLiteral;
    })(Expression);
    TypeScript.NumberLiteral = NumberLiteral;    
    var RegexLiteral = (function (_super) {
        __extends(RegexLiteral, _super);
        function RegexLiteral(regex) {
                _super.call(this, TypeScript.NodeType.Regex);
            this.regex = regex;
        }
        RegexLiteral.prototype.typeCheck = function (typeFlow) {
            this.type = typeFlow.regexType;
            return this;
        };
        RegexLiteral.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.writeToOutput(this.regex.toString());
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return RegexLiteral;
    })(Expression);
    TypeScript.RegexLiteral = RegexLiteral;    
    var StringLiteral = (function (_super) {
        __extends(StringLiteral, _super);
        function StringLiteral(text) {
                _super.call(this, TypeScript.NodeType.QString);
            this.text = text;
        }
        StringLiteral.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.emitStringLiteral(this.text);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        StringLiteral.prototype.typeCheck = function (typeFlow) {
            this.type = typeFlow.stringType;
            return this;
        };
        StringLiteral.prototype.treeViewLabel = function () {
            return "st: " + this.text;
        };
        StringLiteral.prototype.printLabel = function () {
            return this.text;
        };
        return StringLiteral;
    })(Expression);
    TypeScript.StringLiteral = StringLiteral;    
    var ModuleElement = (function (_super) {
        __extends(ModuleElement, _super);
        function ModuleElement(nodeType) {
                _super.call(this, nodeType);
        }
        return ModuleElement;
    })(AST);
    TypeScript.ModuleElement = ModuleElement;    
    var ImportDeclaration = (function (_super) {
        __extends(ImportDeclaration, _super);
        function ImportDeclaration(id, alias) {
                _super.call(this, TypeScript.NodeType.ImportDeclaration);
            this.id = id;
            this.alias = alias;
            this.varFlags = TypeScript.VarFlags.None;
            this.isDynamicImport = false;
        }
        ImportDeclaration.prototype.isStatementOrExpression = function () {
            return true;
        };
        ImportDeclaration.prototype.isDeclaration = function () {
            return true;
        };
        ImportDeclaration.prototype.emit = function (emitter, tokenId, startLine) {
            var mod = this.alias.type;
            if(!this.isDynamicImport || (this.id.sym && !(this.id.sym).onlyReferencedAsTypeRef)) {
                var prevModAliasId = emitter.modAliasId;
                var prevFirstModAlias = emitter.firstModAlias;
                emitter.recordSourceMappingStart(this);
                emitter.emitParensAndCommentsInPlace(this, true);
                emitter.writeToOutput("var " + this.id.actualText + " = ");
                emitter.modAliasId = this.id.actualText;
                emitter.firstModAlias = this.firstAliasedModToString();
                emitter.emitJavascript(this.alias, TypeScript.TokenID.Tilde, false);
                if(!this.isDynamicImport) {
                    emitter.writeToOutput(";");
                }
                emitter.emitParensAndCommentsInPlace(this, false);
                emitter.recordSourceMappingEnd(this);
                emitter.modAliasId = prevModAliasId;
                emitter.firstModAlias = prevFirstModAlias;
            }
        };
        ImportDeclaration.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckImportDecl(this);
        };
        ImportDeclaration.prototype.getAliasName = function (aliasAST) {
            if (typeof aliasAST === "undefined") { aliasAST = this.alias; }
            if(aliasAST.nodeType == TypeScript.NodeType.Name) {
                return (aliasAST).actualText;
            } else {
                var dotExpr = aliasAST;
                return this.getAliasName(dotExpr.operand1) + "." + this.getAliasName(dotExpr.operand2);
            }
        };
        ImportDeclaration.prototype.firstAliasedModToString = function () {
            if(this.alias.nodeType == TypeScript.NodeType.Name) {
                return (this.alias).actualText;
            } else {
                var dotExpr = this.alias;
                var firstMod = dotExpr.operand1;
                return firstMod.actualText;
            }
        };
        return ImportDeclaration;
    })(ModuleElement);
    TypeScript.ImportDeclaration = ImportDeclaration;    
    var BoundDecl = (function (_super) {
        __extends(BoundDecl, _super);
        function BoundDecl(id, nodeType, nestingLevel) {
                _super.call(this, nodeType);
            this.id = id;
            this.nestingLevel = nestingLevel;
            this.init = null;
            this.typeExpr = null;
            this.varFlags = TypeScript.VarFlags.None;
            this.sym = null;
        }
        BoundDecl.prototype.isDeclaration = function () {
            return true;
        };
        BoundDecl.prototype.isStatementOrExpression = function () {
            return true;
        };
        BoundDecl.prototype.isPrivate = function () {
            return TypeScript.hasFlag(this.varFlags, TypeScript.VarFlags.Private);
        };
        BoundDecl.prototype.isPublic = function () {
            return TypeScript.hasFlag(this.varFlags, TypeScript.VarFlags.Public);
        };
        BoundDecl.prototype.isProperty = function () {
            return TypeScript.hasFlag(this.varFlags, TypeScript.VarFlags.Property);
        };
        BoundDecl.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckBoundDecl(this);
        };
        BoundDecl.prototype.printLabel = function () {
            return this.treeViewLabel();
        };
        return BoundDecl;
    })(AST);
    TypeScript.BoundDecl = BoundDecl;    
    var VarDecl = (function (_super) {
        __extends(VarDecl, _super);
        function VarDecl(id, nest) {
                _super.call(this, id, TypeScript.NodeType.VarDecl, nest);
        }
        VarDecl.prototype.isAmbient = function () {
            return TypeScript.hasFlag(this.varFlags, TypeScript.VarFlags.Ambient);
        };
        VarDecl.prototype.isExported = function () {
            return TypeScript.hasFlag(this.varFlags, TypeScript.VarFlags.Exported);
        };
        VarDecl.prototype.isStatic = function () {
            return TypeScript.hasFlag(this.varFlags, TypeScript.VarFlags.Static);
        };
        VarDecl.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitJavascriptVarDecl(this, tokenId);
        };
        VarDecl.prototype.treeViewLabel = function () {
            return "var " + this.id.actualText;
        };
        return VarDecl;
    })(BoundDecl);
    TypeScript.VarDecl = VarDecl;    
    var ArgDecl = (function (_super) {
        __extends(ArgDecl, _super);
        function ArgDecl(id) {
                _super.call(this, id, TypeScript.NodeType.ArgDecl, 0);
            this.isOptional = false;
            this.parameterPropertySym = null;
        }
        ArgDecl.prototype.isOptionalArg = function () {
            return this.isOptional || this.init;
        };
        ArgDecl.prototype.treeViewLabel = function () {
            return "arg: " + this.id.actualText;
        };
        ArgDecl.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.writeToOutput(this.id.actualText);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return ArgDecl;
    })(BoundDecl);
    TypeScript.ArgDecl = ArgDecl;    
    var internalId = 0;
    var FuncDecl = (function (_super) {
        __extends(FuncDecl, _super);
        function FuncDecl(name, bod, isConstructor, arguments, vars, scopes, statics, nodeType) {
                _super.call(this, nodeType);
            this.name = name;
            this.bod = bod;
            this.isConstructor = isConstructor;
            this.arguments = arguments;
            this.vars = vars;
            this.scopes = scopes;
            this.statics = statics;
            this.hint = null;
            this.fncFlags = TypeScript.FncFlags.None;
            this.returnTypeAnnotation = null;
            this.variableArgList = false;
            this.jumpRefs = null;
            this.internalNameCache = null;
            this.tmp1Declared = false;
            this.enclosingFnc = null;
            this.freeVariables = [];
            this.unitIndex = -1;
            this.classDecl = null;
            this.boundToProperty = null;
            this.isOverload = false;
            this.innerStaticFuncs = [];
            this.isTargetTypedAsMethod = false;
            this.isInlineCallLiteral = false;
            this.accessorSymbol = null;
            this.leftCurlyCount = 0;
            this.rightCurlyCount = 0;
            this.returnStatementsWithExpressions = [];
            this.scopeType = null;
            this.endingToken = null;
        }
        FuncDecl.prototype.isDeclaration = function () {
            return true;
        };
        FuncDecl.prototype.internalName = function () {
            if(this.internalNameCache == null) {
                var extName = this.getNameText();
                if(extName) {
                    this.internalNameCache = "_internal_" + extName;
                } else {
                    this.internalNameCache = "_internal_" + internalId++;
                }
            }
            return this.internalNameCache;
        };
        FuncDecl.prototype.hasSelfReference = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.HasSelfReference);
        };
        FuncDecl.prototype.setHasSelfReference = function () {
            this.fncFlags |= TypeScript.FncFlags.HasSelfReference;
        };
        FuncDecl.prototype.hasSuperReferenceInFatArrowFunction = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.HasSuperReferenceInFatArrowFunction);
        };
        FuncDecl.prototype.setHasSuperReferenceInFatArrowFunction = function () {
            this.fncFlags |= TypeScript.FncFlags.HasSuperReferenceInFatArrowFunction;
        };
        FuncDecl.prototype.addCloRef = function (id, sym) {
            if(this.envids == null) {
                this.envids = new Array();
            }
            this.envids[this.envids.length] = id;
            var outerFnc = this.enclosingFnc;
            if(sym) {
                while(outerFnc && (outerFnc.type.symbol != sym.container)) {
                    outerFnc.addJumpRef(sym);
                    outerFnc = outerFnc.enclosingFnc;
                }
            }
            return this.envids.length - 1;
        };
        FuncDecl.prototype.addJumpRef = function (sym) {
            if(this.jumpRefs == null) {
                this.jumpRefs = new Array();
            }
            var id = new Identifier(sym.name);
            this.jumpRefs[this.jumpRefs.length] = id;
            id.sym = sym;
            id.cloId = this.addCloRef(id, null);
        };
        FuncDecl.prototype.buildControlFlow = function () {
            var entry = new TypeScript.BasicBlock();
            var exit = new TypeScript.BasicBlock();
            var context = new TypeScript.ControlFlowContext(entry, exit);
            var controlFlowPrefix = function (ast, parent, walker) {
                ast.addToControlFlow(walker.state);
                return ast;
            };
            var walker = TypeScript.getAstWalkerFactory().getWalker(controlFlowPrefix, null, null, context);
            context.walker = walker;
            walker.walk(this.bod, this);
            return context;
        };
        FuncDecl.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckFunction(this);
        };
        FuncDecl.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitJavascriptFunction(this);
        };
        FuncDecl.prototype.getNameText = function () {
            if(this.name) {
                return this.name.actualText;
            } else {
                return this.hint;
            }
        };
        FuncDecl.prototype.isMethod = function () {
            return (this.fncFlags & TypeScript.FncFlags.Method) != TypeScript.FncFlags.None;
        };
        FuncDecl.prototype.isCallMember = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.CallMember);
        };
        FuncDecl.prototype.isConstructMember = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.ConstructMember);
        };
        FuncDecl.prototype.isIndexerMember = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.IndexerMember);
        };
        FuncDecl.prototype.isSpecialFn = function () {
            return this.isCallMember() || this.isIndexerMember() || this.isConstructMember();
        };
        FuncDecl.prototype.isAnonymousFn = function () {
            return this.name === null;
        };
        FuncDecl.prototype.isAccessor = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.GetAccessor) || TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.SetAccessor);
        };
        FuncDecl.prototype.isGetAccessor = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.GetAccessor);
        };
        FuncDecl.prototype.isSetAccessor = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.SetAccessor);
        };
        FuncDecl.prototype.isAmbient = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.Ambient);
        };
        FuncDecl.prototype.isExported = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.Exported);
        };
        FuncDecl.prototype.isPrivate = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.Private);
        };
        FuncDecl.prototype.isPublic = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.Public);
        };
        FuncDecl.prototype.isStatic = function () {
            return TypeScript.hasFlag(this.fncFlags, TypeScript.FncFlags.Static);
        };
        FuncDecl.prototype.treeViewLabel = function () {
            if(this.name == null) {
                return "funcExpr";
            } else {
                return "func: " + this.name.actualText;
            }
        };
        FuncDecl.prototype.ClearFlags = function () {
            this.fncFlags = TypeScript.FncFlags.None;
        };
        FuncDecl.prototype.isSignature = function () {
            return (this.fncFlags & TypeScript.FncFlags.Signature) != TypeScript.FncFlags.None;
        };
        return FuncDecl;
    })(AST);
    TypeScript.FuncDecl = FuncDecl;    
    var LocationInfo = (function () {
        function LocationInfo(filename, lineMap, unitIndex) {
            this.filename = filename;
            this.lineMap = lineMap;
            this.unitIndex = unitIndex;
        }
        return LocationInfo;
    })();
    TypeScript.LocationInfo = LocationInfo;    
    TypeScript.unknownLocationInfo = new LocationInfo("unknown", null, -1);
    var Script = (function (_super) {
        __extends(Script, _super);
        function Script(vars, scopes) {
                _super.call(this, new Identifier("script"), null, false, null, vars, scopes, null, TypeScript.NodeType.Script);
            this.locationInfo = null;
            this.referencedFiles = [];
            this.requiresGlobal = false;
            this.requiresExtendsBlock = false;
            this.isResident = false;
            this.isDeclareFile = false;
            this.hasBeenTypeChecked = false;
            this.topLevelMod = null;
            this.leftCurlyCount = 0;
            this.rightCurlyCount = 0;
            this.containsUnicodeChar = false;
            this.containsUnicodeCharInComment = false;
            this.externallyVisibleImportedSymbols = [];
            this.vars = vars;
            this.scopes = scopes;
        }
        Script.prototype.setCachedEmitRequired = function (value) {
            this.cachedEmitRequired = value;
            return this.cachedEmitRequired;
        };
        Script.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckScript(this);
        };
        Script.prototype.treeViewLabel = function () {
            return "Script";
        };
        Script.prototype.emitRequired = function (emitOptions) {
            if(this.cachedEmitRequired != undefined) {
                return this.cachedEmitRequired;
            }
            if(!this.isDeclareFile && !this.isResident && this.bod) {
                for(var i = 0, len = this.bod.members.length; i < len; i++) {
                    var stmt = this.bod.members[i];
                    if(stmt.nodeType == TypeScript.NodeType.ModuleDeclaration) {
                        if(!TypeScript.hasFlag((stmt).modFlags, TypeScript.ModuleFlags.ShouldEmitModuleDecl | TypeScript.ModuleFlags.Ambient)) {
                            return this.setCachedEmitRequired(true);
                        }
                    } else {
                        if(stmt.nodeType == TypeScript.NodeType.ClassDeclaration) {
                            if(!TypeScript.hasFlag((stmt).varFlags, TypeScript.VarFlags.Ambient)) {
                                return this.setCachedEmitRequired(true);
                            }
                        } else {
                            if(stmt.nodeType == TypeScript.NodeType.VarDecl) {
                                if(!TypeScript.hasFlag((stmt).varFlags, TypeScript.VarFlags.Ambient)) {
                                    return this.setCachedEmitRequired(true);
                                }
                            } else {
                                if(stmt.nodeType == TypeScript.NodeType.FuncDecl) {
                                    if(!(stmt).isSignature()) {
                                        return this.setCachedEmitRequired(true);
                                    }
                                } else {
                                    if(stmt.nodeType != TypeScript.NodeType.InterfaceDeclaration && stmt.nodeType != TypeScript.NodeType.Empty) {
                                        return this.setCachedEmitRequired(true);
                                    }
                                }
                            }
                        }
                    }
                }
                if(emitOptions.emitComments && ((this.bod.preComments && this.bod.preComments.length > 0) || (this.bod.postComments && this.bod.postComments.length > 0))) {
                    return this.setCachedEmitRequired(true);
                }
            }
            return this.setCachedEmitRequired(false);
        };
        Script.prototype.emit = function (emitter, tokenId, startLine) {
            if(this.emitRequired(emitter.emitOptions)) {
                emitter.emitParensAndCommentsInPlace(this.bod, true);
                emitter.emitJavascriptList(this.bod, null, TypeScript.TokenID.Semicolon, true, false, false, true, this.requiresExtendsBlock);
                emitter.emitParensAndCommentsInPlace(this.bod, false);
            }
        };
        Script.prototype.AddExternallyVisibleImportedSymbol = function (symbol, checker) {
            if(this.isExternallyVisibleSymbol(symbol)) {
                return;
            }
            if(!symbol.getType().symbol.isExternallyVisible(checker)) {
                var quotes = "";
                var moduleName = symbol.getType().symbol.prettyName;
                if(!TypeScript.isQuoted(moduleName)) {
                    quotes = "'";
                }
                checker.errorReporter.simpleError(symbol.declAST, "Externally visible import statement uses non exported module " + quotes + moduleName + quotes);
            }
            this.externallyVisibleImportedSymbols.push(symbol);
        };
        Script.prototype.isExternallyVisibleSymbol = function (symbol) {
            for(var i = 0; i < this.externallyVisibleImportedSymbols.length; i++) {
                if(this.externallyVisibleImportedSymbols[i] == symbol) {
                    return true;
                }
            }
            return false;
        };
        return Script;
    })(FuncDecl);
    TypeScript.Script = Script;    
    var NamedDeclaration = (function (_super) {
        __extends(NamedDeclaration, _super);
        function NamedDeclaration(nodeType, name, members) {
                _super.call(this, nodeType);
            this.name = name;
            this.members = members;
            this.leftCurlyCount = 0;
            this.rightCurlyCount = 0;
        }
        NamedDeclaration.prototype.isDeclaration = function () {
            return true;
        };
        return NamedDeclaration;
    })(ModuleElement);
    TypeScript.NamedDeclaration = NamedDeclaration;    
    var ModuleDeclaration = (function (_super) {
        __extends(ModuleDeclaration, _super);
        function ModuleDeclaration(name, members, vars, scopes, endingToken) {
                _super.call(this, TypeScript.NodeType.ModuleDeclaration, name, members);
            this.endingToken = endingToken;
            this.modFlags = TypeScript.ModuleFlags.ShouldEmitModuleDecl;
            this.amdDependencies = [];
            this.containsUnicodeChar = false;
            this.containsUnicodeCharInComment = false;
            this.vars = vars;
            this.scopes = scopes;
            this.prettyName = this.name.actualText;
        }
        ModuleDeclaration.prototype.isExported = function () {
            return TypeScript.hasFlag(this.modFlags, TypeScript.ModuleFlags.Exported);
        };
        ModuleDeclaration.prototype.isAmbient = function () {
            return TypeScript.hasFlag(this.modFlags, TypeScript.ModuleFlags.Ambient);
        };
        ModuleDeclaration.prototype.isEnum = function () {
            return TypeScript.hasFlag(this.modFlags, TypeScript.ModuleFlags.IsEnum);
        };
        ModuleDeclaration.prototype.recordNonInterface = function () {
            this.modFlags &= ~TypeScript.ModuleFlags.ShouldEmitModuleDecl;
        };
        ModuleDeclaration.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckModule(this);
        };
        ModuleDeclaration.prototype.emit = function (emitter, tokenId, startLine) {
            if(!TypeScript.hasFlag(this.modFlags, TypeScript.ModuleFlags.ShouldEmitModuleDecl)) {
                emitter.emitParensAndCommentsInPlace(this, true);
                emitter.recordSourceMappingStart(this);
                emitter.emitJavascriptModule(this);
                emitter.recordSourceMappingEnd(this);
                emitter.emitParensAndCommentsInPlace(this, false);
            }
        };
        return ModuleDeclaration;
    })(NamedDeclaration);
    TypeScript.ModuleDeclaration = ModuleDeclaration;    
    var TypeDeclaration = (function (_super) {
        __extends(TypeDeclaration, _super);
        function TypeDeclaration(nodeType, name, extendsList, implementsList, members) {
                _super.call(this, nodeType, name, members);
            this.extendsList = extendsList;
            this.implementsList = implementsList;
            this.varFlags = TypeScript.VarFlags.None;
        }
        TypeDeclaration.prototype.isExported = function () {
            return TypeScript.hasFlag(this.varFlags, TypeScript.VarFlags.Exported);
        };
        TypeDeclaration.prototype.isAmbient = function () {
            return TypeScript.hasFlag(this.varFlags, TypeScript.VarFlags.Ambient);
        };
        return TypeDeclaration;
    })(NamedDeclaration);
    TypeScript.TypeDeclaration = TypeDeclaration;    
    var ClassDeclaration = (function (_super) {
        __extends(ClassDeclaration, _super);
        function ClassDeclaration(name, members, extendsList, implementsList) {
                _super.call(this, TypeScript.NodeType.ClassDeclaration, name, extendsList, implementsList, members);
            this.knownMemberNames = {
            };
            this.constructorDecl = null;
            this.constructorNestingLevel = 0;
            this.endingToken = null;
        }
        ClassDeclaration.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckClass(this);
        };
        ClassDeclaration.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitJavascriptClass(this);
        };
        return ClassDeclaration;
    })(TypeDeclaration);
    TypeScript.ClassDeclaration = ClassDeclaration;    
    var InterfaceDeclaration = (function (_super) {
        __extends(InterfaceDeclaration, _super);
        function InterfaceDeclaration(name, members, extendsList, implementsList) {
                _super.call(this, TypeScript.NodeType.InterfaceDeclaration, name, extendsList, implementsList, members);
        }
        InterfaceDeclaration.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckInterface(this);
        };
        InterfaceDeclaration.prototype.emit = function (emitter, tokenId, startLine) {
        };
        return InterfaceDeclaration;
    })(TypeDeclaration);
    TypeScript.InterfaceDeclaration = InterfaceDeclaration;    
    var Statement = (function (_super) {
        __extends(Statement, _super);
        function Statement(nodeType) {
                _super.call(this, nodeType);
            this.flags |= TypeScript.ASTFlags.IsStatement;
        }
        Statement.prototype.isLoop = function () {
            return false;
        };
        Statement.prototype.isStatementOrExpression = function () {
            return true;
        };
        Statement.prototype.isCompoundStatement = function () {
            return this.isLoop();
        };
        Statement.prototype.typeCheck = function (typeFlow) {
            this.type = typeFlow.voidType;
            return this;
        };
        return Statement;
    })(ModuleElement);
    TypeScript.Statement = Statement;    
    var LabeledStatement = (function (_super) {
        __extends(LabeledStatement, _super);
        function LabeledStatement(labels, stmt) {
                _super.call(this, TypeScript.NodeType.LabeledStatement);
            this.labels = labels;
            this.stmt = stmt;
        }
        LabeledStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            if(this.labels) {
                var labelsLen = this.labels.members.length;
                for(var i = 0; i < labelsLen; i++) {
                    this.labels.members[i].emit(emitter, tokenId, startLine);
                }
            }
            this.stmt.emit(emitter, tokenId, true);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        LabeledStatement.prototype.typeCheck = function (typeFlow) {
            typeFlow.typeCheck(this.labels);
            this.stmt = this.stmt.typeCheck(typeFlow);
            return this;
        };
        LabeledStatement.prototype.addToControlFlow = function (context) {
            var beforeBB = context.current;
            var bb = new TypeScript.BasicBlock();
            context.current = bb;
            beforeBB.addSuccessor(bb);
        };
        return LabeledStatement;
    })(Statement);
    TypeScript.LabeledStatement = LabeledStatement;    
    var Block = (function (_super) {
        __extends(Block, _super);
        function Block(statements, isStatementBlock) {
                _super.call(this, TypeScript.NodeType.Block);
            this.statements = statements;
            this.isStatementBlock = isStatementBlock;
        }
        Block.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            if(this.isStatementBlock) {
                emitter.writeLineToOutput(" {");
                emitter.indenter.increaseIndent();
            } else {
                emitter.setInVarBlock(this.statements.members.length);
            }
            var temp = emitter.setInObjectLiteral(false);
            if(this.statements) {
                emitter.emitJavascriptList(this.statements, null, TypeScript.TokenID.Semicolon, true, false, false);
            }
            if(this.isStatementBlock) {
                emitter.indenter.decreaseIndent();
                emitter.emitIndent();
                emitter.writeToOutput("}");
            }
            emitter.setInObjectLiteral(temp);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        Block.prototype.addToControlFlow = function (context) {
            var afterIfNeeded = new TypeScript.BasicBlock();
            context.pushStatement(this, context.current, afterIfNeeded);
            if(this.statements) {
                context.walk(this.statements, this);
            }
            context.walker.options.goChildren = false;
            context.popStatement();
            if(afterIfNeeded.predecessors.length > 0) {
                context.current.addSuccessor(afterIfNeeded);
                context.current = afterIfNeeded;
            }
        };
        Block.prototype.typeCheck = function (typeFlow) {
            if(!typeFlow.checker.styleSettings.emptyBlocks) {
                if((this.statements === null) || (this.statements.members.length == 0)) {
                    typeFlow.checker.errorReporter.styleError(this, "empty block");
                }
            }
            typeFlow.typeCheck(this.statements);
            return this;
        };
        return Block;
    })(Statement);
    TypeScript.Block = Block;    
    var Jump = (function (_super) {
        __extends(Jump, _super);
        function Jump(nodeType) {
                _super.call(this, nodeType);
            this.target = null;
            this.resolvedTarget = null;
        }
        Jump.prototype.hasExplicitTarget = function () {
            return (this.target);
        };
        Jump.prototype.setResolvedTarget = function (parser, stmt) {
            if(stmt.isLoop()) {
                this.resolvedTarget = stmt;
                return true;
            }
            if(this.nodeType === TypeScript.NodeType.Continue) {
                parser.reportParseError("continue statement applies only to loops");
                return false;
            } else {
                if((stmt.nodeType == TypeScript.NodeType.Switch) || this.hasExplicitTarget()) {
                    this.resolvedTarget = stmt;
                    return true;
                } else {
                    parser.reportParseError("break statement with no label can apply only to a loop or switch statement");
                    return false;
                }
            }
        };
        Jump.prototype.addToControlFlow = function (context) {
            _super.prototype.addToControlFlow.call(this, context);
            context.unconditionalBranch(this.resolvedTarget, (this.nodeType == TypeScript.NodeType.Continue));
        };
        Jump.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            if(this.nodeType == TypeScript.NodeType.Break) {
                emitter.writeToOutput("break");
            } else {
                emitter.writeToOutput("continue");
            }
            if(this.hasExplicitTarget()) {
                emitter.writeToOutput(" " + this.target);
            }
            emitter.recordSourceMappingEnd(this);
            emitter.writeToOutput(";");
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return Jump;
    })(Statement);
    TypeScript.Jump = Jump;    
    var WhileStatement = (function (_super) {
        __extends(WhileStatement, _super);
        function WhileStatement(cond) {
                _super.call(this, TypeScript.NodeType.While);
            this.cond = cond;
            this.body = null;
        }
        WhileStatement.prototype.isLoop = function () {
            return true;
        };
        WhileStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            var temp = emitter.setInObjectLiteral(false);
            emitter.writeToOutput("while(");
            emitter.emitJavascript(this.cond, TypeScript.TokenID.While, false);
            emitter.writeToOutput(")");
            emitter.emitJavascriptStatements(this.body, false);
            emitter.setInObjectLiteral(temp);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        WhileStatement.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckWhile(this);
        };
        WhileStatement.prototype.addToControlFlow = function (context) {
            var loopHeader = context.current;
            var loopStart = new TypeScript.BasicBlock();
            var afterLoop = new TypeScript.BasicBlock();
            loopHeader.addSuccessor(loopStart);
            context.current = loopStart;
            context.addContent(this.cond);
            var condBlock = context.current;
            var targetInfo = null;
            if(this.body) {
                context.current = new TypeScript.BasicBlock();
                condBlock.addSuccessor(context.current);
                context.pushStatement(this, loopStart, afterLoop);
                context.walk(this.body, this);
                targetInfo = context.popStatement();
            }
            if(!(context.noContinuation)) {
                var loopEnd = context.current;
                loopEnd.addSuccessor(loopStart);
            }
            context.current = afterLoop;
            condBlock.addSuccessor(afterLoop);
            context.noContinuation = false;
            context.walker.options.goChildren = false;
        };
        return WhileStatement;
    })(Statement);
    TypeScript.WhileStatement = WhileStatement;    
    var DoWhileStatement = (function (_super) {
        __extends(DoWhileStatement, _super);
        function DoWhileStatement() {
                _super.call(this, TypeScript.NodeType.DoWhile);
            this.body = null;
            this.whileAST = null;
            this.cond = null;
        }
        DoWhileStatement.prototype.isLoop = function () {
            return true;
        };
        DoWhileStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            var temp = emitter.setInObjectLiteral(false);
            emitter.writeToOutput("do");
            emitter.emitJavascriptStatements(this.body, true);
            emitter.recordSourceMappingStart(this.whileAST);
            emitter.writeToOutput("while");
            emitter.recordSourceMappingEnd(this.whileAST);
            emitter.writeToOutput('(');
            emitter.emitJavascript(this.cond, TypeScript.TokenID.CloseParen, false);
            emitter.writeToOutput(")");
            emitter.setInObjectLiteral(temp);
            emitter.recordSourceMappingEnd(this);
            emitter.writeToOutput(";");
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        DoWhileStatement.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckDoWhile(this);
        };
        DoWhileStatement.prototype.addToControlFlow = function (context) {
            var loopHeader = context.current;
            var loopStart = new TypeScript.BasicBlock();
            var afterLoop = new TypeScript.BasicBlock();
            loopHeader.addSuccessor(loopStart);
            context.current = loopStart;
            var targetInfo = null;
            if(this.body) {
                context.pushStatement(this, loopStart, afterLoop);
                context.walk(this.body, this);
                targetInfo = context.popStatement();
            }
            if(!(context.noContinuation)) {
                var loopEnd = context.current;
                loopEnd.addSuccessor(loopStart);
                context.addContent(this.cond);
                context.current = afterLoop;
                loopEnd.addSuccessor(afterLoop);
            } else {
                context.addUnreachable(this.cond);
            }
            context.walker.options.goChildren = false;
        };
        return DoWhileStatement;
    })(Statement);
    TypeScript.DoWhileStatement = DoWhileStatement;    
    var IfStatement = (function (_super) {
        __extends(IfStatement, _super);
        function IfStatement(cond) {
                _super.call(this, TypeScript.NodeType.If);
            this.cond = cond;
            this.elseBod = null;
            this.statement = new ASTSpan();
        }
        IfStatement.prototype.isCompoundStatement = function () {
            return true;
        };
        IfStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            var temp = emitter.setInObjectLiteral(false);
            emitter.recordSourceMappingStart(this.statement);
            emitter.writeToOutput("if(");
            emitter.emitJavascript(this.cond, TypeScript.TokenID.If, false);
            emitter.writeToOutput(")");
            emitter.recordSourceMappingEnd(this.statement);
            emitter.emitJavascriptStatements(this.thenBod, true);
            if(this.elseBod) {
                if(this.elseBod.nodeType === TypeScript.NodeType.If) {
                    emitter.writeToOutput(" else ");
                    this.elseBod.emit(emitter, tokenId, false);
                } else {
                    emitter.writeToOutput(" else");
                    emitter.emitJavascriptStatements(this.elseBod, true);
                }
            }
            emitter.setInObjectLiteral(temp);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        IfStatement.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckIf(this);
        };
        IfStatement.prototype.addToControlFlow = function (context) {
            this.cond.addToControlFlow(context);
            var afterIf = new TypeScript.BasicBlock();
            var beforeIf = context.current;
            context.pushStatement(this, beforeIf, afterIf);
            var hasContinuation = false;
            context.current = new TypeScript.BasicBlock();
            beforeIf.addSuccessor(context.current);
            context.walk(this.thenBod, this);
            if(!context.noContinuation) {
                hasContinuation = true;
                context.current.addSuccessor(afterIf);
            }
            if(this.elseBod) {
                context.current = new TypeScript.BasicBlock();
                context.noContinuation = false;
                beforeIf.addSuccessor(context.current);
                context.walk(this.elseBod, this);
                if(!context.noContinuation) {
                    hasContinuation = true;
                    context.current.addSuccessor(afterIf);
                } else {
                    if(hasContinuation) {
                        context.noContinuation = false;
                    }
                }
            } else {
                beforeIf.addSuccessor(afterIf);
                context.noContinuation = false;
                hasContinuation = true;
            }
            var targetInfo = context.popStatement();
            if(afterIf.predecessors.length > 0) {
                context.noContinuation = false;
                hasContinuation = true;
            }
            if(hasContinuation) {
                context.current = afterIf;
            }
            context.walker.options.goChildren = false;
        };
        return IfStatement;
    })(Statement);
    TypeScript.IfStatement = IfStatement;    
    var ReturnStatement = (function (_super) {
        __extends(ReturnStatement, _super);
        function ReturnStatement() {
                _super.call(this, TypeScript.NodeType.Return);
            this.returnExpression = null;
        }
        ReturnStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            var temp = emitter.setInObjectLiteral(false);
            if(this.returnExpression) {
                emitter.writeToOutput("return ");
                emitter.emitJavascript(this.returnExpression, TypeScript.TokenID.Semicolon, false);
                if(this.returnExpression.nodeType === TypeScript.NodeType.FuncDecl) {
                    emitter.writeToOutput(";");
                }
            } else {
                emitter.writeToOutput("return;");
            }
            emitter.setInObjectLiteral(temp);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        ReturnStatement.prototype.addToControlFlow = function (context) {
            _super.prototype.addToControlFlow.call(this, context);
            context.returnStmt();
        };
        ReturnStatement.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckReturn(this);
        };
        return ReturnStatement;
    })(Statement);
    TypeScript.ReturnStatement = ReturnStatement;    
    var EndCode = (function (_super) {
        __extends(EndCode, _super);
        function EndCode() {
                _super.call(this, TypeScript.NodeType.EndCode);
        }
        return EndCode;
    })(AST);
    TypeScript.EndCode = EndCode;    
    var ForInStatement = (function (_super) {
        __extends(ForInStatement, _super);
        function ForInStatement(lval, obj) {
                _super.call(this, TypeScript.NodeType.ForIn);
            this.lval = lval;
            this.obj = obj;
            this.statement = new ASTSpan();
            if(this.lval && (this.lval.nodeType == TypeScript.NodeType.VarDecl)) {
                (this.lval).varFlags |= TypeScript.VarFlags.AutoInit;
            }
        }
        ForInStatement.prototype.isLoop = function () {
            return true;
        };
        ForInStatement.prototype.isFiltered = function () {
            if(this.body) {
                var singleItem = null;
                if(this.body.nodeType == TypeScript.NodeType.List) {
                    var stmts = this.body;
                    if(stmts.members.length == 1) {
                        singleItem = stmts.members[0];
                    }
                } else {
                    singleItem = this.body;
                }
                if(singleItem !== null) {
                    if(singleItem.nodeType == TypeScript.NodeType.Block) {
                        var block = singleItem;
                        if((block.statements !== null) && (block.statements.members.length == 1)) {
                            singleItem = block.statements.members[0];
                        }
                    }
                    if(singleItem.nodeType == TypeScript.NodeType.If) {
                        var cond = (singleItem).cond;
                        if(cond.nodeType == TypeScript.NodeType.Call) {
                            var target = (cond).target;
                            if(target.nodeType == TypeScript.NodeType.Dot) {
                                var binex = target;
                                if((binex.operand1.nodeType == TypeScript.NodeType.Name) && (this.obj.nodeType == TypeScript.NodeType.Name) && ((binex.operand1).actualText == (this.obj).actualText)) {
                                    var prop = binex.operand2;
                                    if(prop.actualText == "hasOwnProperty") {
                                        var args = (cond).arguments;
                                        if((args !== null) && (args.members.length == 1)) {
                                            var arg = args.members[0];
                                            if((arg.nodeType == TypeScript.NodeType.Name) && (this.lval.nodeType == TypeScript.NodeType.Name)) {
                                                if(((this.lval).actualText) == (arg).actualText) {
                                                    return true;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return false;
        };
        ForInStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            var temp = emitter.setInObjectLiteral(false);
            emitter.recordSourceMappingStart(this.statement);
            emitter.writeToOutput("for(");
            emitter.emitJavascript(this.lval, TypeScript.TokenID.For, false);
            emitter.writeToOutput(" in ");
            emitter.emitJavascript(this.obj, TypeScript.TokenID.For, false);
            emitter.writeToOutput(")");
            emitter.recordSourceMappingEnd(this.statement);
            emitter.emitJavascriptStatements(this.body, true);
            emitter.setInObjectLiteral(temp);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        ForInStatement.prototype.typeCheck = function (typeFlow) {
            if(typeFlow.checker.styleSettings.forin) {
                if(!this.isFiltered()) {
                    typeFlow.checker.errorReporter.styleError(this, "no hasOwnProperty filter");
                }
            }
            return typeFlow.typeCheckForIn(this);
        };
        ForInStatement.prototype.addToControlFlow = function (context) {
            if(this.lval) {
                context.addContent(this.lval);
            }
            if(this.obj) {
                context.addContent(this.obj);
            }
            var loopHeader = context.current;
            var loopStart = new TypeScript.BasicBlock();
            var afterLoop = new TypeScript.BasicBlock();
            loopHeader.addSuccessor(loopStart);
            context.current = loopStart;
            if(this.body) {
                context.pushStatement(this, loopStart, afterLoop);
                context.walk(this.body, this);
                context.popStatement();
            }
            if(!(context.noContinuation)) {
                var loopEnd = context.current;
                loopEnd.addSuccessor(loopStart);
            }
            context.current = afterLoop;
            context.noContinuation = false;
            loopHeader.addSuccessor(afterLoop);
            context.walker.options.goChildren = false;
        };
        return ForInStatement;
    })(Statement);
    TypeScript.ForInStatement = ForInStatement;    
    var ForStatement = (function (_super) {
        __extends(ForStatement, _super);
        function ForStatement(init) {
                _super.call(this, TypeScript.NodeType.For);
            this.init = init;
        }
        ForStatement.prototype.isLoop = function () {
            return true;
        };
        ForStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            var temp = emitter.setInObjectLiteral(false);
            emitter.writeToOutput("for(");
            if(this.init) {
                if(this.init.nodeType != TypeScript.NodeType.List) {
                    emitter.emitJavascript(this.init, TypeScript.TokenID.For, false);
                } else {
                    emitter.setInVarBlock((this.init).members.length);
                    emitter.emitJavascriptList(this.init, null, TypeScript.TokenID.For, false, false, false);
                }
            }
            emitter.writeToOutput("; ");
            emitter.emitJavascript(this.cond, TypeScript.TokenID.For, false);
            emitter.writeToOutput("; ");
            emitter.emitJavascript(this.incr, TypeScript.TokenID.For, false);
            emitter.writeToOutput(")");
            emitter.emitJavascriptStatements(this.body, true);
            emitter.setInObjectLiteral(temp);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        ForStatement.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckFor(this);
        };
        ForStatement.prototype.addToControlFlow = function (context) {
            if(this.init) {
                context.addContent(this.init);
            }
            var loopHeader = context.current;
            var loopStart = new TypeScript.BasicBlock();
            var afterLoop = new TypeScript.BasicBlock();
            loopHeader.addSuccessor(loopStart);
            context.current = loopStart;
            var condBlock = null;
            var continueTarget = loopStart;
            var incrBB = null;
            if(this.incr) {
                incrBB = new TypeScript.BasicBlock();
                continueTarget = incrBB;
            }
            if(this.cond) {
                condBlock = context.current;
                context.addContent(this.cond);
                context.current = new TypeScript.BasicBlock();
                condBlock.addSuccessor(context.current);
            }
            var targetInfo = null;
            if(this.body) {
                context.pushStatement(this, continueTarget, afterLoop);
                context.walk(this.body, this);
                targetInfo = context.popStatement();
            }
            if(this.incr) {
                if(context.noContinuation) {
                    if(incrBB.predecessors.length == 0) {
                        context.addUnreachable(this.incr);
                    }
                } else {
                    context.current.addSuccessor(incrBB);
                    context.current = incrBB;
                    context.addContent(this.incr);
                }
            }
            var loopEnd = context.current;
            if(!(context.noContinuation)) {
                loopEnd.addSuccessor(loopStart);
            }
            if(condBlock) {
                condBlock.addSuccessor(afterLoop);
                context.noContinuation = false;
            }
            if(afterLoop.predecessors.length > 0) {
                context.noContinuation = false;
                context.current = afterLoop;
            }
            context.walker.options.goChildren = false;
        };
        return ForStatement;
    })(Statement);
    TypeScript.ForStatement = ForStatement;    
    var WithStatement = (function (_super) {
        __extends(WithStatement, _super);
        function WithStatement(expr) {
                _super.call(this, TypeScript.NodeType.With);
            this.expr = expr;
            this.withSym = null;
        }
        WithStatement.prototype.isCompoundStatement = function () {
            return true;
        };
        WithStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.writeToOutput("with (");
            if(this.expr) {
                emitter.emitJavascript(this.expr, TypeScript.TokenID.With, false);
            }
            emitter.writeToOutput(")");
            emitter.emitJavascriptStatements(this.body, true);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        WithStatement.prototype.typeCheck = function (typeFlow) {
            return typeFlow.typeCheckWith(this);
        };
        return WithStatement;
    })(Statement);
    TypeScript.WithStatement = WithStatement;    
    var SwitchStatement = (function (_super) {
        __extends(SwitchStatement, _super);
        function SwitchStatement(val) {
                _super.call(this, TypeScript.NodeType.Switch);
            this.val = val;
            this.defaultCase = null;
            this.statement = new ASTSpan();
        }
        SwitchStatement.prototype.isCompoundStatement = function () {
            return true;
        };
        SwitchStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            var temp = emitter.setInObjectLiteral(false);
            emitter.recordSourceMappingStart(this.statement);
            emitter.writeToOutput("switch(");
            emitter.emitJavascript(this.val, TypeScript.TokenID.Identifier, false);
            emitter.writeToOutput(")");
            emitter.recordSourceMappingEnd(this.statement);
            emitter.writeLineToOutput(" {");
            emitter.indenter.increaseIndent();
            var casesLen = this.caseList.members.length;
            for(var i = 0; i < casesLen; i++) {
                var caseExpr = this.caseList.members[i];
                emitter.emitJavascript(caseExpr, TypeScript.TokenID.Case, true);
            }
            emitter.indenter.decreaseIndent();
            emitter.emitIndent();
            emitter.writeToOutput("}");
            emitter.setInObjectLiteral(temp);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        SwitchStatement.prototype.typeCheck = function (typeFlow) {
            var len = this.caseList.members.length;
            this.val = typeFlow.typeCheck(this.val);
            for(var i = 0; i < len; i++) {
                this.caseList.members[i] = typeFlow.typeCheck(this.caseList.members[i]);
            }
            this.defaultCase = typeFlow.typeCheck(this.defaultCase);
            this.type = typeFlow.voidType;
            return this;
        };
        SwitchStatement.prototype.addToControlFlow = function (context) {
            var condBlock = context.current;
            context.addContent(this.val);
            var execBlock = new TypeScript.BasicBlock();
            var afterSwitch = new TypeScript.BasicBlock();
            condBlock.addSuccessor(execBlock);
            context.pushSwitch(execBlock);
            context.current = execBlock;
            context.pushStatement(this, execBlock, afterSwitch);
            context.walk(this.caseList, this);
            context.popSwitch();
            var targetInfo = context.popStatement();
            var hasCondContinuation = (this.defaultCase == null);
            if(this.defaultCase == null) {
                condBlock.addSuccessor(afterSwitch);
            }
            if(afterSwitch.predecessors.length > 0) {
                context.noContinuation = false;
                context.current = afterSwitch;
            } else {
                context.noContinuation = true;
            }
            context.walker.options.goChildren = false;
        };
        return SwitchStatement;
    })(Statement);
    TypeScript.SwitchStatement = SwitchStatement;    
    var CaseStatement = (function (_super) {
        __extends(CaseStatement, _super);
        function CaseStatement() {
                _super.call(this, TypeScript.NodeType.Case);
            this.expr = null;
        }
        CaseStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            if(this.expr) {
                emitter.writeToOutput("case ");
                emitter.emitJavascript(this.expr, TypeScript.TokenID.Identifier, false);
            } else {
                emitter.writeToOutput("default");
            }
            emitter.writeToOutput(":");
            if(this.body.members.length == 1 && this.body.members[0].nodeType == TypeScript.NodeType.Block) {
                emitter.emitJavascriptStatements(this.body, false);
            } else {
                emitter.writeLineToOutput("");
                emitter.indenter.increaseIndent();
                emitter.emitBareJavascriptStatements(this.body);
                emitter.indenter.decreaseIndent();
            }
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        CaseStatement.prototype.typeCheck = function (typeFlow) {
            this.expr = typeFlow.typeCheck(this.expr);
            typeFlow.typeCheck(this.body);
            this.type = typeFlow.voidType;
            return this;
        };
        CaseStatement.prototype.addToControlFlow = function (context) {
            var execBlock = new TypeScript.BasicBlock();
            var sw = context.currentSwitch[context.currentSwitch.length - 1];
            if(this.expr) {
                var exprBlock = new TypeScript.BasicBlock();
                context.current = exprBlock;
                sw.addSuccessor(exprBlock);
                context.addContent(this.expr);
                exprBlock.addSuccessor(execBlock);
            } else {
                sw.addSuccessor(execBlock);
            }
            context.current = execBlock;
            if(this.body) {
                context.walk(this.body, this);
            }
            context.noContinuation = false;
            context.walker.options.goChildren = false;
        };
        return CaseStatement;
    })(Statement);
    TypeScript.CaseStatement = CaseStatement;    
    var TypeReference = (function (_super) {
        __extends(TypeReference, _super);
        function TypeReference(term, arrayCount) {
                _super.call(this, TypeScript.NodeType.TypeRef);
            this.term = term;
            this.arrayCount = arrayCount;
        }
        TypeReference.prototype.emit = function (emitter, tokenId, startLine) {
            throw new Error("should not emit a type ref");
        };
        TypeReference.prototype.typeCheck = function (typeFlow) {
            var prevInTCTR = typeFlow.inTypeRefTypeCheck;
            typeFlow.inTypeRefTypeCheck = true;
            var typeLink = TypeScript.getTypeLink(this, typeFlow.checker, true);
            typeFlow.checker.resolveTypeLink(typeFlow.scope, typeLink, false);
            if(this.term) {
                typeFlow.typeCheck(this.term);
            }
            typeFlow.checkForVoidConstructor(typeLink.type, this);
            this.type = typeLink.type;
            if(this.term) {
                this.term.type = this.type;
            }
            typeFlow.inTypeRefTypeCheck = prevInTCTR;
            return this;
        };
        return TypeReference;
    })(AST);
    TypeScript.TypeReference = TypeReference;    
    var TryFinally = (function (_super) {
        __extends(TryFinally, _super);
        function TryFinally(tryNode, finallyNode) {
                _super.call(this, TypeScript.NodeType.TryFinally);
            this.tryNode = tryNode;
            this.finallyNode = finallyNode;
        }
        TryFinally.prototype.isCompoundStatement = function () {
            return true;
        };
        TryFinally.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.recordSourceMappingStart(this);
            emitter.emitJavascript(this.tryNode, TypeScript.TokenID.Try, false);
            emitter.emitJavascript(this.finallyNode, TypeScript.TokenID.Finally, false);
            emitter.recordSourceMappingEnd(this);
        };
        TryFinally.prototype.typeCheck = function (typeFlow) {
            this.tryNode = typeFlow.typeCheck(this.tryNode);
            this.finallyNode = typeFlow.typeCheck(this.finallyNode);
            this.type = typeFlow.voidType;
            return this;
        };
        TryFinally.prototype.addToControlFlow = function (context) {
            var afterFinally = new TypeScript.BasicBlock();
            context.walk(this.tryNode, this);
            var finBlock = new TypeScript.BasicBlock();
            if(context.current) {
                context.current.addSuccessor(finBlock);
            }
            context.current = finBlock;
            context.pushStatement(this, null, afterFinally);
            context.walk(this.finallyNode, this);
            if(!context.noContinuation && context.current) {
                context.current.addSuccessor(afterFinally);
            }
            if(afterFinally.predecessors.length > 0) {
                context.current = afterFinally;
            } else {
                context.noContinuation = true;
            }
            context.popStatement();
            context.walker.options.goChildren = false;
        };
        return TryFinally;
    })(Statement);
    TypeScript.TryFinally = TryFinally;    
    var TryCatch = (function (_super) {
        __extends(TryCatch, _super);
        function TryCatch(tryNode, catchNode) {
                _super.call(this, TypeScript.NodeType.TryCatch);
            this.tryNode = tryNode;
            this.catchNode = catchNode;
        }
        TryCatch.prototype.isCompoundStatement = function () {
            return true;
        };
        TryCatch.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.emitJavascript(this.tryNode, TypeScript.TokenID.Try, false);
            emitter.emitJavascript(this.catchNode, TypeScript.TokenID.Catch, false);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        TryCatch.prototype.addToControlFlow = function (context) {
            var beforeTry = context.current;
            var tryBlock = new TypeScript.BasicBlock();
            beforeTry.addSuccessor(tryBlock);
            context.current = tryBlock;
            var afterTryCatch = new TypeScript.BasicBlock();
            context.pushStatement(this, null, afterTryCatch);
            context.walk(this.tryNode, this);
            if(!context.noContinuation) {
                if(context.current) {
                    context.current.addSuccessor(afterTryCatch);
                }
            }
            context.current = new TypeScript.BasicBlock();
            beforeTry.addSuccessor(context.current);
            context.walk(this.catchNode, this);
            context.popStatement();
            if(!context.noContinuation) {
                if(context.current) {
                    context.current.addSuccessor(afterTryCatch);
                }
            }
            context.current = afterTryCatch;
            context.walker.options.goChildren = false;
        };
        TryCatch.prototype.typeCheck = function (typeFlow) {
            this.tryNode = typeFlow.typeCheck(this.tryNode);
            this.catchNode = typeFlow.typeCheck(this.catchNode);
            this.type = typeFlow.voidType;
            return this;
        };
        return TryCatch;
    })(Statement);
    TypeScript.TryCatch = TryCatch;    
    var Try = (function (_super) {
        __extends(Try, _super);
        function Try(body) {
                _super.call(this, TypeScript.NodeType.Try);
            this.body = body;
        }
        Try.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.writeToOutput("try ");
            emitter.emitJavascript(this.body, TypeScript.TokenID.Try, false);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        Try.prototype.typeCheck = function (typeFlow) {
            this.body = typeFlow.typeCheck(this.body);
            return this;
        };
        Try.prototype.addToControlFlow = function (context) {
            if(this.body) {
                context.walk(this.body, this);
            }
            context.walker.options.goChildren = false;
            context.noContinuation = false;
        };
        return Try;
    })(Statement);
    TypeScript.Try = Try;    
    var Catch = (function (_super) {
        __extends(Catch, _super);
        function Catch(param, body) {
                _super.call(this, TypeScript.NodeType.Catch);
            this.param = param;
            this.body = body;
            this.statement = new ASTSpan();
            this.containedScope = null;
            if(this.param) {
                this.param.varFlags |= TypeScript.VarFlags.AutoInit;
            }
        }
        Catch.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.writeToOutput(" ");
            emitter.recordSourceMappingStart(this.statement);
            emitter.writeToOutput("catch (");
            emitter.emitJavascript(this.param, TypeScript.TokenID.OpenParen, false);
            emitter.writeToOutput(")");
            emitter.recordSourceMappingEnd(this.statement);
            emitter.emitJavascript(this.body, TypeScript.TokenID.Catch, false);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        Catch.prototype.addToControlFlow = function (context) {
            if(this.param) {
                context.addContent(this.param);
                var bodBlock = new TypeScript.BasicBlock();
                context.current.addSuccessor(bodBlock);
                context.current = bodBlock;
            }
            if(this.body) {
                context.walk(this.body, this);
            }
            context.noContinuation = false;
            context.walker.options.goChildren = false;
        };
        Catch.prototype.typeCheck = function (typeFlow) {
            var prevScope = typeFlow.scope;
            typeFlow.scope = this.containedScope;
            this.param = typeFlow.typeCheck(this.param);
            var exceptVar = new TypeScript.ValueLocation();
            var varSym = new TypeScript.VariableSymbol((this.param).id.text, this.param.minChar, typeFlow.checker.locationInfo.unitIndex, exceptVar);
            exceptVar.symbol = varSym;
            exceptVar.typeLink = new TypeScript.TypeLink();
            exceptVar.typeLink.type = typeFlow.anyType;
            var thisFnc = typeFlow.thisFnc;
            if(thisFnc && thisFnc.type) {
                exceptVar.symbol.container = thisFnc.type.symbol;
            } else {
                exceptVar.symbol.container = null;
            }
            this.param.sym = exceptVar.symbol;
            typeFlow.scope.enter(exceptVar.symbol.container, this.param, exceptVar.symbol, typeFlow.checker.errorReporter, false, false, false);
            this.body = typeFlow.typeCheck(this.body);
            if(typeFlow.checker.inProvisionalTypecheckMode()) {
                var table = typeFlow.scope.getTable();
                (table).secondaryTable.table[exceptVar.symbol.name] = undefined;
            }
            this.type = typeFlow.voidType;
            typeFlow.scope = prevScope;
            return this;
        };
        return Catch;
    })(Statement);
    TypeScript.Catch = Catch;    
    var Finally = (function (_super) {
        __extends(Finally, _super);
        function Finally(body) {
                _super.call(this, TypeScript.NodeType.Finally);
            this.body = body;
        }
        Finally.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.writeToOutput("finally");
            emitter.emitJavascript(this.body, TypeScript.TokenID.Finally, false);
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        Finally.prototype.addToControlFlow = function (context) {
            if(this.body) {
                context.walk(this.body, this);
            }
            context.walker.options.goChildren = false;
            context.noContinuation = false;
        };
        Finally.prototype.typeCheck = function (typeFlow) {
            this.body = typeFlow.typeCheck(this.body);
            return this;
        };
        return Finally;
    })(Statement);
    TypeScript.Finally = Finally;    
    var Comment = (function (_super) {
        __extends(Comment, _super);
        function Comment(content, isBlockComment, endsLine) {
                _super.call(this, TypeScript.NodeType.Comment);
            this.content = content;
            this.isBlockComment = isBlockComment;
            this.endsLine = endsLine;
            this.text = null;
            this.docCommentText = null;
        }
        Comment.prototype.getText = function () {
            if(this.text == null) {
                if(this.isBlockComment) {
                    this.text = this.content.split("\n");
                    for(var i = 0; i < this.text.length; i++) {
                        this.text[i] = this.text[i].replace(/^\s+|\s+$/g, '');
                    }
                } else {
                    this.text = [
                        (this.content.replace(/^\s+|\s+$/g, ''))
                    ];
                }
            }
            return this.text;
        };
        Comment.prototype.isDocComment = function () {
            if(this.isBlockComment) {
                return this.content.charAt(2) == "*";
            }
            return false;
        };
        Comment.prototype.getDocCommentText = function () {
            if(this.docCommentText == null) {
                this.docCommentText = Comment.cleanJSDocComment(this.content);
            }
            return this.docCommentText;
        };
        Comment.consumeLeadingSpace = function consumeLeadingSpace(line, startIndex, maxSpacesToRemove) {
            var endIndex = line.length;
            if(maxSpacesToRemove != undefined) {
                endIndex = TypeScript.min(startIndex + maxSpacesToRemove, endIndex);
            }
            for(; startIndex < endIndex; startIndex++) {
                var charCode = line.charCodeAt(startIndex);
                if(charCode != TypeScript.LexCodeSpace && charCode != TypeScript.LexCodeTAB) {
                    return startIndex;
                }
            }
            if(endIndex != line.length) {
                return endIndex;
            }
            return -1;
        }
        Comment.isSpaceChar = function isSpaceChar(line, index) {
            var length = line.length;
            if(index < length) {
                var charCode = line.charCodeAt(index);
                return charCode == TypeScript.LexCodeSpace || charCode == TypeScript.LexCodeTAB;
            }
            return index == length;
        }
        Comment.cleanDocCommentLine = function cleanDocCommentLine(line, jsDocStyleComment, jsDocLineSpaceToRemove) {
            var nonSpaceIndex = Comment.consumeLeadingSpace(line, 0);
            if(nonSpaceIndex != -1) {
                var jsDocSpacesRemoved = nonSpaceIndex;
                if(jsDocStyleComment && line.charAt(nonSpaceIndex) == '*') {
                    var startIndex = nonSpaceIndex + 1;
                    nonSpaceIndex = Comment.consumeLeadingSpace(line, startIndex, jsDocLineSpaceToRemove);
                    if(nonSpaceIndex != -1) {
                        jsDocSpacesRemoved = nonSpaceIndex - startIndex;
                    } else {
                        return null;
                    }
                }
                return {
                    minChar: nonSpaceIndex,
                    limChar: line.charAt(line.length - 1) == "\r" ? line.length - 1 : line.length,
                    jsDocSpacesRemoved: jsDocSpacesRemoved
                };
            }
            return null;
        }
        Comment.cleanJSDocComment = function cleanJSDocComment(content, spacesToRemove) {
            var docCommentLines = [];
            content = content.replace("/**", "");
            if(content.length >= 2 && content.charAt(content.length - 1) == "/" && content.charAt(content.length - 2) == "*") {
                content = content.substring(0, content.length - 2);
            }
            var lines = content.split("\n");
            var inParamTag = false;
            for(var l = 0; l < lines.length; l++) {
                var line = lines[l];
                var cleanLinePos = Comment.cleanDocCommentLine(line, true, spacesToRemove);
                if(!cleanLinePos) {
                    continue;
                }
                var docCommentText = "";
                var prevPos = cleanLinePos.minChar;
                for(var i = line.indexOf("@", cleanLinePos.minChar); 0 <= i && i < cleanLinePos.limChar; i = line.indexOf("@", i + 1)) {
                    var wasInParamtag = inParamTag;
                    if(line.indexOf("param", i + 1) == i + 1 && Comment.isSpaceChar(line, i + 6)) {
                        if(!wasInParamtag) {
                            docCommentText += line.substring(prevPos, i);
                        }
                        prevPos = i;
                        inParamTag = true;
                    } else {
                        if(wasInParamtag) {
                            prevPos = i;
                            inParamTag = false;
                        }
                    }
                }
                if(!inParamTag) {
                    docCommentText += line.substring(prevPos, cleanLinePos.limChar);
                }
                var newCleanPos = Comment.cleanDocCommentLine(docCommentText, false);
                if(newCleanPos) {
                    if(spacesToRemove == undefined) {
                        spacesToRemove = cleanLinePos.jsDocSpacesRemoved;
                    }
                    docCommentLines.push(docCommentText);
                }
            }
            return docCommentLines.join("\n");
        }
        Comment.getDocCommentText = function getDocCommentText(comments) {
            var docCommentText = [];
            for(var c = 0; c < comments.length; c++) {
                var commentText = comments[c].getDocCommentText();
                if(commentText != "") {
                    docCommentText.push(commentText);
                }
            }
            return docCommentText.join("\n");
        }
        Comment.getParameterDocCommentText = function getParameterDocCommentText(param, fncDocComments) {
            if(fncDocComments.length == 0 || !fncDocComments[0].isBlockComment) {
                return "";
            }
            for(var i = 0; i < fncDocComments.length; i++) {
                var commentContents = fncDocComments[i].content;
                for(var j = commentContents.indexOf("@param", 0); 0 <= j; j = commentContents.indexOf("@param", j)) {
                    j += 6;
                    if(!Comment.isSpaceChar(commentContents, j)) {
                        continue;
                    }
                    j = Comment.consumeLeadingSpace(commentContents, j);
                    if(j == -1) {
                        break;
                    }
                    if(commentContents.charCodeAt(j) == TypeScript.LexCodeLC) {
                        j++;
                        var charCode = 0;
                        for(var curlies = 1; j < commentContents.length; j++) {
                            charCode = commentContents.charCodeAt(j);
                            if(charCode == TypeScript.LexCodeLC) {
                                curlies++;
                                continue;
                            }
                            if(charCode == TypeScript.LexCodeRC) {
                                curlies--;
                                if(curlies == 0) {
                                    break;
                                } else {
                                    continue;
                                }
                            }
                            if(charCode == TypeScript.LexCodeAtSign) {
                                break;
                            }
                        }
                        if(j == commentContents.length) {
                            break;
                        }
                        if(charCode == TypeScript.LexCodeAtSign) {
                            continue;
                        }
                        j = Comment.consumeLeadingSpace(commentContents, j + 1);
                        if(j == -1) {
                            break;
                        }
                    }
                    if(param != commentContents.substr(j, param.length) || !Comment.isSpaceChar(commentContents, j + param.length)) {
                        continue;
                    }
                    j = Comment.consumeLeadingSpace(commentContents, j + param.length);
                    if(j == -1) {
                        return "";
                    }
                    var endOfParam = commentContents.indexOf("@", j);
                    var paramHelpString = commentContents.substring(j, endOfParam < 0 ? commentContents.length : endOfParam);
                    var paramSpacesToRemove = undefined;
                    var paramLineIndex = commentContents.substring(0, j).lastIndexOf("\n") + 1;
                    if(paramLineIndex != 0) {
                        if(paramLineIndex < j && commentContents.charAt(paramLineIndex + 1) == "\r") {
                            paramLineIndex++;
                        }
                    }
                    var startSpaceRemovalIndex = Comment.consumeLeadingSpace(commentContents, paramLineIndex);
                    if(startSpaceRemovalIndex != j && commentContents.charAt(startSpaceRemovalIndex) == "*") {
                        paramSpacesToRemove = j - startSpaceRemovalIndex - 1;
                    }
                    return Comment.cleanJSDocComment(paramHelpString, paramSpacesToRemove);
                }
            }
            return "";
        }
        Comment.getDocCommentTextOfSignatures = function getDocCommentTextOfSignatures(signatures) {
            var comments = [];
            for(var i = 0; i < signatures.length; i++) {
                var signatureDocComment = TypeScript.Comment.getDocCommentText(signatures[i].declAST.getDocComments());
                if(signatureDocComment != "") {
                    comments.push(signatureDocComment);
                }
            }
            return comments.join("\n");
        }
        return Comment;
    })(AST);
    TypeScript.Comment = Comment;    
    var DebuggerStatement = (function (_super) {
        __extends(DebuggerStatement, _super);
        function DebuggerStatement() {
                _super.call(this, TypeScript.NodeType.Debugger);
        }
        DebuggerStatement.prototype.emit = function (emitter, tokenId, startLine) {
            emitter.emitParensAndCommentsInPlace(this, true);
            emitter.recordSourceMappingStart(this);
            emitter.writeLineToOutput("debugger;");
            emitter.recordSourceMappingEnd(this);
            emitter.emitParensAndCommentsInPlace(this, false);
        };
        return DebuggerStatement;
    })(Statement);
    TypeScript.DebuggerStatement = DebuggerStatement;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var AstWalkOptions = (function () {
        function AstWalkOptions() {
            this.goChildren = true;
            this.goNextSibling = true;
            this.reverseSiblings = false;
        }
        AstWalkOptions.prototype.stopWalk = function (stop) {
            if (typeof stop === "undefined") { stop = true; }
            this.goChildren = !stop;
            this.goNextSibling = !stop;
        };
        return AstWalkOptions;
    })();
    TypeScript.AstWalkOptions = AstWalkOptions;    
    var AstWalker = (function () {
        function AstWalker(childrenWalkers, pre, post, options, state) {
            this.childrenWalkers = childrenWalkers;
            this.pre = pre;
            this.post = post;
            this.options = options;
            this.state = state;
        }
        AstWalker.prototype.walk = function (ast, parent) {
            var preAst = this.pre(ast, parent, this);
            if(preAst === undefined) {
                preAst = ast;
            }
            if(this.options.goChildren) {
                var svGoSib = this.options.goNextSibling;
                this.options.goNextSibling = true;
                this.childrenWalkers[ast.nodeType](ast, parent, this);
                this.options.goNextSibling = svGoSib;
            } else {
                this.options.goChildren = true;
            }
            if(this.post) {
                var postAst = this.post(preAst, parent, this);
                if(postAst === undefined) {
                    postAst = preAst;
                }
                return postAst;
            } else {
                return preAst;
            }
        };
        return AstWalker;
    })();    
    var AstWalkerFactory = (function () {
        function AstWalkerFactory() {
            this.childrenWalkers = [];
            this.initChildrenWalkers();
        }
        AstWalkerFactory.prototype.walk = function (ast, pre, post, options, state) {
            return this.getWalker(pre, post, options, state).walk(ast, null);
        };
        AstWalkerFactory.prototype.getWalker = function (pre, post, options, state) {
            return this.getSlowWalker(pre, post, options, state);
        };
        AstWalkerFactory.prototype.getSlowWalker = function (pre, post, options, state) {
            if(!options) {
                options = new AstWalkOptions();
            }
            return new AstWalker(this.childrenWalkers, pre, post, options, state);
        };
        AstWalkerFactory.prototype.initChildrenWalkers = function () {
            this.childrenWalkers[TypeScript.NodeType.None] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Empty] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.EmptyExpr] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.True] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.False] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.This] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Super] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.QString] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Regex] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Null] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.ArrayLit] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.ObjectLit] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Void] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Comma] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Pos] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Neg] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Delete] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Await] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.In] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Dot] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.From] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Is] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.InstOf] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Typeof] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.NumberLit] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Name] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.TypeRef] = ChildrenWalkers.walkTypeReferenceChildren;
            this.childrenWalkers[TypeScript.NodeType.Index] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Call] = ChildrenWalkers.walkCallExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.New] = ChildrenWalkers.walkCallExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Asg] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgAdd] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgSub] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgDiv] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgMul] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgMod] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgAnd] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgXor] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgOr] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgLsh] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgRsh] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.AsgRs2] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.ConditionalExpression] = ChildrenWalkers.walkTrinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.LogOr] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.LogAnd] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Or] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Xor] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.And] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Eq] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Ne] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Eqv] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.NEqv] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Lt] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Le] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Gt] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Ge] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Add] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Sub] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Mul] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Div] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Mod] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Lsh] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Rsh] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Rs2] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.Not] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.LogNot] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.IncPre] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.DecPre] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.IncPost] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.DecPost] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.TypeAssertion] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.FuncDecl] = ChildrenWalkers.walkFuncDeclChildren;
            this.childrenWalkers[TypeScript.NodeType.Member] = ChildrenWalkers.walkBinaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.VarDecl] = ChildrenWalkers.walkBoundDeclChildren;
            this.childrenWalkers[TypeScript.NodeType.ArgDecl] = ChildrenWalkers.walkBoundDeclChildren;
            this.childrenWalkers[TypeScript.NodeType.Return] = ChildrenWalkers.walkReturnStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.Break] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Continue] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Throw] = ChildrenWalkers.walkUnaryExpressionChildren;
            this.childrenWalkers[TypeScript.NodeType.For] = ChildrenWalkers.walkForStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.ForIn] = ChildrenWalkers.walkForInStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.If] = ChildrenWalkers.walkIfStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.While] = ChildrenWalkers.walkWhileStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.DoWhile] = ChildrenWalkers.walkDoWhileStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.Block] = ChildrenWalkers.walkBlockChildren;
            this.childrenWalkers[TypeScript.NodeType.Case] = ChildrenWalkers.walkCaseStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.Switch] = ChildrenWalkers.walkSwitchStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.Try] = ChildrenWalkers.walkTryChildren;
            this.childrenWalkers[TypeScript.NodeType.TryCatch] = ChildrenWalkers.walkTryCatchChildren;
            this.childrenWalkers[TypeScript.NodeType.TryFinally] = ChildrenWalkers.walkTryFinallyChildren;
            this.childrenWalkers[TypeScript.NodeType.Finally] = ChildrenWalkers.walkFinallyChildren;
            this.childrenWalkers[TypeScript.NodeType.Catch] = ChildrenWalkers.walkCatchChildren;
            this.childrenWalkers[TypeScript.NodeType.List] = ChildrenWalkers.walkListChildren;
            this.childrenWalkers[TypeScript.NodeType.Script] = ChildrenWalkers.walkScriptChildren;
            this.childrenWalkers[TypeScript.NodeType.ClassDeclaration] = ChildrenWalkers.walkClassDeclChildren;
            this.childrenWalkers[TypeScript.NodeType.InterfaceDeclaration] = ChildrenWalkers.walkTypeDeclChildren;
            this.childrenWalkers[TypeScript.NodeType.ModuleDeclaration] = ChildrenWalkers.walkModuleDeclChildren;
            this.childrenWalkers[TypeScript.NodeType.ImportDeclaration] = ChildrenWalkers.walkImportDeclChildren;
            this.childrenWalkers[TypeScript.NodeType.With] = ChildrenWalkers.walkWithStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.Label] = ChildrenWalkers.walkLabelChildren;
            this.childrenWalkers[TypeScript.NodeType.LabeledStatement] = ChildrenWalkers.walkLabeledStatementChildren;
            this.childrenWalkers[TypeScript.NodeType.EBStart] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.GotoEB] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.EndCode] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Error] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Comment] = ChildrenWalkers.walkNone;
            this.childrenWalkers[TypeScript.NodeType.Debugger] = ChildrenWalkers.walkNone;
            for(var e in (TypeScript.NodeType)._map) {
                if((this.childrenWalkers)[e] === undefined) {
                    throw new Error("initWalkers function is not up to date with enum content!");
                }
            }
        };
        return AstWalkerFactory;
    })();
    TypeScript.AstWalkerFactory = AstWalkerFactory;    
    var globalAstWalkerFactory;
    function getAstWalkerFactory() {
        if(!globalAstWalkerFactory) {
            globalAstWalkerFactory = new AstWalkerFactory();
        }
        return globalAstWalkerFactory;
    }
    TypeScript.getAstWalkerFactory = getAstWalkerFactory;
    var ChildrenWalkers;
    (function (ChildrenWalkers) {
        function walkNone(preAst, parent, walker) {
        }
        ChildrenWalkers.walkNone = walkNone;
        function walkListChildren(preAst, parent, walker) {
            var len = preAst.members.length;
            if(walker.options.reverseSiblings) {
                for(var i = len - 1; i >= 0; i--) {
                    if(walker.options.goNextSibling) {
                        preAst.members[i] = walker.walk(preAst.members[i], preAst);
                    }
                }
            } else {
                for(var i = 0; i < len; i++) {
                    if(walker.options.goNextSibling) {
                        preAst.members[i] = walker.walk(preAst.members[i], preAst);
                    }
                }
            }
        }
        ChildrenWalkers.walkListChildren = walkListChildren;
        function walkUnaryExpressionChildren(preAst, parent, walker) {
            if(preAst.castTerm) {
                preAst.castTerm = walker.walk(preAst.castTerm, preAst);
            }
            if(preAst.operand) {
                preAst.operand = walker.walk(preAst.operand, preAst);
            }
        }
        ChildrenWalkers.walkUnaryExpressionChildren = walkUnaryExpressionChildren;
        function walkBinaryExpressionChildren(preAst, parent, walker) {
            if(walker.options.reverseSiblings) {
                if(preAst.operand2) {
                    preAst.operand2 = walker.walk(preAst.operand2, preAst);
                }
                if((preAst.operand1) && (walker.options.goNextSibling)) {
                    preAst.operand1 = walker.walk(preAst.operand1, preAst);
                }
            } else {
                if(preAst.operand1) {
                    preAst.operand1 = walker.walk(preAst.operand1, preAst);
                }
                if((preAst.operand2) && (walker.options.goNextSibling)) {
                    preAst.operand2 = walker.walk(preAst.operand2, preAst);
                }
            }
        }
        ChildrenWalkers.walkBinaryExpressionChildren = walkBinaryExpressionChildren;
        function walkTypeReferenceChildren(preAst, parent, walker) {
            if(preAst.term) {
                preAst.term = walker.walk(preAst.term, preAst);
            }
        }
        ChildrenWalkers.walkTypeReferenceChildren = walkTypeReferenceChildren;
        function walkCallExpressionChildren(preAst, parent, walker) {
            if(!walker.options.reverseSiblings) {
                preAst.target = walker.walk(preAst.target, preAst);
            }
            if(preAst.arguments && (walker.options.goNextSibling)) {
                preAst.arguments = walker.walk(preAst.arguments, preAst);
            }
            if((walker.options.reverseSiblings) && (walker.options.goNextSibling)) {
                preAst.target = walker.walk(preAst.target, preAst);
            }
        }
        ChildrenWalkers.walkCallExpressionChildren = walkCallExpressionChildren;
        function walkTrinaryExpressionChildren(preAst, parent, walker) {
            if(preAst.operand1) {
                preAst.operand1 = walker.walk(preAst.operand1, preAst);
            }
            if(preAst.operand2 && (walker.options.goNextSibling)) {
                preAst.operand2 = walker.walk(preAst.operand2, preAst);
            }
            if(preAst.operand3 && (walker.options.goNextSibling)) {
                preAst.operand3 = walker.walk(preAst.operand3, preAst);
            }
        }
        ChildrenWalkers.walkTrinaryExpressionChildren = walkTrinaryExpressionChildren;
        function walkFuncDeclChildren(preAst, parent, walker) {
            if(preAst.name) {
                preAst.name = walker.walk(preAst.name, preAst);
            }
            if(preAst.arguments && (preAst.arguments.members.length > 0) && (walker.options.goNextSibling)) {
                preAst.arguments = walker.walk(preAst.arguments, preAst);
            }
            if(preAst.returnTypeAnnotation && (walker.options.goNextSibling)) {
                preAst.returnTypeAnnotation = walker.walk(preAst.returnTypeAnnotation, preAst);
            }
            if(preAst.bod && (preAst.bod.members.length > 0) && (walker.options.goNextSibling)) {
                preAst.bod = walker.walk(preAst.bod, preAst);
            }
        }
        ChildrenWalkers.walkFuncDeclChildren = walkFuncDeclChildren;
        function walkBoundDeclChildren(preAst, parent, walker) {
            if(preAst.id) {
                preAst.id = walker.walk(preAst.id, preAst);
            }
            if(preAst.init) {
                preAst.init = walker.walk(preAst.init, preAst);
            }
            if((preAst.typeExpr) && (walker.options.goNextSibling)) {
                preAst.typeExpr = walker.walk(preAst.typeExpr, preAst);
            }
        }
        ChildrenWalkers.walkBoundDeclChildren = walkBoundDeclChildren;
        function walkReturnStatementChildren(preAst, parent, walker) {
            if(preAst.returnExpression) {
                preAst.returnExpression = walker.walk(preAst.returnExpression, preAst);
            }
        }
        ChildrenWalkers.walkReturnStatementChildren = walkReturnStatementChildren;
        function walkForStatementChildren(preAst, parent, walker) {
            if(preAst.init) {
                preAst.init = walker.walk(preAst.init, preAst);
            }
            if(preAst.cond && walker.options.goNextSibling) {
                preAst.cond = walker.walk(preAst.cond, preAst);
            }
            if(preAst.incr && walker.options.goNextSibling) {
                preAst.incr = walker.walk(preAst.incr, preAst);
            }
            if(preAst.body && walker.options.goNextSibling) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkForStatementChildren = walkForStatementChildren;
        function walkForInStatementChildren(preAst, parent, walker) {
            preAst.lval = walker.walk(preAst.lval, preAst);
            if(walker.options.goNextSibling) {
                preAst.obj = walker.walk(preAst.obj, preAst);
            }
            if(preAst.body && (walker.options.goNextSibling)) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkForInStatementChildren = walkForInStatementChildren;
        function walkIfStatementChildren(preAst, parent, walker) {
            preAst.cond = walker.walk(preAst.cond, preAst);
            if(preAst.thenBod && (walker.options.goNextSibling)) {
                preAst.thenBod = walker.walk(preAst.thenBod, preAst);
            }
            if(preAst.elseBod && (walker.options.goNextSibling)) {
                preAst.elseBod = walker.walk(preAst.elseBod, preAst);
            }
        }
        ChildrenWalkers.walkIfStatementChildren = walkIfStatementChildren;
        function walkWhileStatementChildren(preAst, parent, walker) {
            preAst.cond = walker.walk(preAst.cond, preAst);
            if(preAst.body && (walker.options.goNextSibling)) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkWhileStatementChildren = walkWhileStatementChildren;
        function walkDoWhileStatementChildren(preAst, parent, walker) {
            preAst.cond = walker.walk(preAst.cond, preAst);
            if(preAst.body && (walker.options.goNextSibling)) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkDoWhileStatementChildren = walkDoWhileStatementChildren;
        function walkBlockChildren(preAst, parent, walker) {
            if(preAst.statements) {
                preAst.statements = walker.walk(preAst.statements, preAst);
            }
        }
        ChildrenWalkers.walkBlockChildren = walkBlockChildren;
        function walkCaseStatementChildren(preAst, parent, walker) {
            if(preAst.expr) {
                preAst.expr = walker.walk(preAst.expr, preAst);
            }
            if(preAst.body && walker.options.goNextSibling) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkCaseStatementChildren = walkCaseStatementChildren;
        function walkSwitchStatementChildren(preAst, parent, walker) {
            if(preAst.val) {
                preAst.val = walker.walk(preAst.val, preAst);
            }
            if((preAst.caseList) && walker.options.goNextSibling) {
                preAst.caseList = walker.walk(preAst.caseList, preAst);
            }
        }
        ChildrenWalkers.walkSwitchStatementChildren = walkSwitchStatementChildren;
        function walkTryChildren(preAst, parent, walker) {
            if(preAst.body) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkTryChildren = walkTryChildren;
        function walkTryCatchChildren(preAst, parent, walker) {
            if(preAst.tryNode) {
                preAst.tryNode = walker.walk(preAst.tryNode, preAst);
            }
            if((preAst.catchNode) && walker.options.goNextSibling) {
                preAst.catchNode = walker.walk(preAst.catchNode, preAst);
            }
        }
        ChildrenWalkers.walkTryCatchChildren = walkTryCatchChildren;
        function walkTryFinallyChildren(preAst, parent, walker) {
            if(preAst.tryNode) {
                preAst.tryNode = walker.walk(preAst.tryNode, preAst);
            }
            if(preAst.finallyNode && walker.options.goNextSibling) {
                preAst.finallyNode = walker.walk(preAst.finallyNode, preAst);
            }
        }
        ChildrenWalkers.walkTryFinallyChildren = walkTryFinallyChildren;
        function walkFinallyChildren(preAst, parent, walker) {
            if(preAst.body) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkFinallyChildren = walkFinallyChildren;
        function walkCatchChildren(preAst, parent, walker) {
            if(preAst.param) {
                preAst.param = walker.walk(preAst.param, preAst);
            }
            if((preAst.body) && walker.options.goNextSibling) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkCatchChildren = walkCatchChildren;
        function walkRecordChildren(preAst, parent, walker) {
            preAst.name = walker.walk(preAst.name, preAst);
            if(walker.options.goNextSibling && preAst.members) {
                preAst.members = walker.walk(preAst.members, preAst);
            }
        }
        ChildrenWalkers.walkRecordChildren = walkRecordChildren;
        function walkNamedTypeChildren(preAst, parent, walker) {
            walkRecordChildren(preAst, parent, walker);
        }
        ChildrenWalkers.walkNamedTypeChildren = walkNamedTypeChildren;
        function walkClassDeclChildren(preAst, parent, walker) {
            walkNamedTypeChildren(preAst, parent, walker);
            if(walker.options.goNextSibling && preAst.extendsList) {
                preAst.extendsList = walker.walk(preAst.extendsList, preAst);
            }
            if(walker.options.goNextSibling && preAst.implementsList) {
                preAst.implementsList = walker.walk(preAst.implementsList, preAst);
            }
        }
        ChildrenWalkers.walkClassDeclChildren = walkClassDeclChildren;
        function walkScriptChildren(preAst, parent, walker) {
            if(preAst.bod) {
                preAst.bod = walker.walk(preAst.bod, preAst);
            }
        }
        ChildrenWalkers.walkScriptChildren = walkScriptChildren;
        function walkTypeDeclChildren(preAst, parent, walker) {
            walkNamedTypeChildren(preAst, parent, walker);
            if(walker.options.goNextSibling && preAst.extendsList) {
                preAst.extendsList = walker.walk(preAst.extendsList, preAst);
            }
            if(walker.options.goNextSibling && preAst.implementsList) {
                preAst.implementsList = walker.walk(preAst.implementsList, preAst);
            }
        }
        ChildrenWalkers.walkTypeDeclChildren = walkTypeDeclChildren;
        function walkModuleDeclChildren(preAst, parent, walker) {
            walkRecordChildren(preAst, parent, walker);
        }
        ChildrenWalkers.walkModuleDeclChildren = walkModuleDeclChildren;
        function walkImportDeclChildren(preAst, parent, walker) {
            if(preAst.id) {
                preAst.id = walker.walk(preAst.id, preAst);
            }
            if(preAst.alias) {
                preAst.alias = walker.walk(preAst.alias, preAst);
            }
        }
        ChildrenWalkers.walkImportDeclChildren = walkImportDeclChildren;
        function walkWithStatementChildren(preAst, parent, walker) {
            if(preAst.expr) {
                preAst.expr = walker.walk(preAst.expr, preAst);
            }
            if(preAst.body && walker.options.goNextSibling) {
                preAst.body = walker.walk(preAst.body, preAst);
            }
        }
        ChildrenWalkers.walkWithStatementChildren = walkWithStatementChildren;
        function walkLabelChildren(preAst, parent, walker) {
        }
        ChildrenWalkers.walkLabelChildren = walkLabelChildren;
        function walkLabeledStatementChildren(preAst, parent, walker) {
            preAst.labels = walker.walk(preAst.labels, preAst);
            if(walker.options.goNextSibling) {
                preAst.stmt = walker.walk(preAst.stmt, preAst);
            }
        }
        ChildrenWalkers.walkLabeledStatementChildren = walkLabeledStatementChildren;
    })(ChildrenWalkers || (ChildrenWalkers = {}));
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (AstWalkerWithDetailCallback) {
        function walk(script, callback) {
            var pre = function (cur, parent) {
                walker.options.goChildren = AstWalkerCallback(true, cur, callback);
                return cur;
            };
            var post = function (cur, parent) {
                AstWalkerCallback(false, cur, callback);
                return cur;
            };
            var walker = TypeScript.getAstWalkerFactory().getWalker(pre, post);
            walker.walk(script, null);
        }
        AstWalkerWithDetailCallback.walk = walk;
        function AstWalkerCallback(pre, ast, callback) {
            var nodeType = ast.nodeType;
            var callbackString = (TypeScript.NodeType)._map[nodeType] + "Callback";
            if(callback[callbackString]) {
                return callback[callbackString](pre, ast);
            }
            if(callback.DefaultCallback) {
                return callback.DefaultCallback(pre, ast);
            }
            return true;
        }
    })(TypeScript.AstWalkerWithDetailCallback || (TypeScript.AstWalkerWithDetailCallback = {}));
    var AstWalkerWithDetailCallback = TypeScript.AstWalkerWithDetailCallback;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    function lastOf(items) {
        return (items === null || items.length === 0) ? null : items[items.length - 1];
    }
    TypeScript.lastOf = lastOf;
    function max(a, b) {
        return a >= b ? a : b;
    }
    TypeScript.max = max;
    function min(a, b) {
        return a <= b ? a : b;
    }
    TypeScript.min = min;
    var AstPath = (function () {
        function AstPath() {
            this.asts = [];
            this.top = -1;
        }
        AstPath.reverseIndexOf = function reverseIndexOf(items, index) {
            return (items === null || items.length <= index) ? null : items[items.length - index - 1];
        }
        AstPath.prototype.clone = function () {
            var clone = new AstPath();
            clone.asts = this.asts.map(function (value) {
                return value;
            });
            clone.top = this.top;
            return clone;
        };
        AstPath.prototype.pop = function () {
            var head = this.ast();
            this.up();
            while(this.asts.length > this.count()) {
                this.asts.pop();
            }
            return head;
        };
        AstPath.prototype.push = function (ast) {
            while(this.asts.length > this.count()) {
                this.asts.pop();
            }
            this.top = this.asts.length;
            this.asts.push(ast);
        };
        AstPath.prototype.up = function () {
            if(this.top <= -1) {
                throw new Error("Invalid call to 'up'");
            }
            this.top--;
        };
        AstPath.prototype.down = function () {
            if(this.top == this.ast.length - 1) {
                throw new Error("Invalid call to 'down'");
            }
            this.top++;
        };
        AstPath.prototype.nodeType = function () {
            if(this.ast() == null) {
                return TypeScript.NodeType.None;
            }
            return this.ast().nodeType;
        };
        AstPath.prototype.ast = function () {
            return AstPath.reverseIndexOf(this.asts, this.asts.length - (this.top + 1));
        };
        AstPath.prototype.parent = function () {
            return AstPath.reverseIndexOf(this.asts, this.asts.length - this.top);
        };
        AstPath.prototype.count = function () {
            return this.top + 1;
        };
        AstPath.prototype.get = function (index) {
            return this.asts[index];
        };
        AstPath.prototype.isNameOfClass = function () {
            if(this.ast() === null || this.parent() === null) {
                return false;
            }
            return (this.ast().nodeType === TypeScript.NodeType.Name) && (this.parent().nodeType === TypeScript.NodeType.ClassDeclaration) && ((this.parent()).name === this.ast());
        };
        AstPath.prototype.isNameOfInterface = function () {
            if(this.ast() === null || this.parent() === null) {
                return false;
            }
            return (this.ast().nodeType === TypeScript.NodeType.Name) && (this.parent().nodeType === TypeScript.NodeType.InterfaceDeclaration) && ((this.parent()).name === this.ast());
        };
        AstPath.prototype.isNameOfArgument = function () {
            if(this.ast() === null || this.parent() === null) {
                return false;
            }
            return (this.ast().nodeType === TypeScript.NodeType.Name) && (this.parent().nodeType === TypeScript.NodeType.ArgDecl) && ((this.parent()).id === this.ast());
        };
        AstPath.prototype.isNameOfVariable = function () {
            if(this.ast() === null || this.parent() === null) {
                return false;
            }
            return (this.ast().nodeType === TypeScript.NodeType.Name) && (this.parent().nodeType === TypeScript.NodeType.VarDecl) && ((this.parent()).id === this.ast());
        };
        AstPath.prototype.isNameOfModule = function () {
            if(this.ast() === null || this.parent() === null) {
                return false;
            }
            return (this.ast().nodeType === TypeScript.NodeType.Name) && (this.parent().nodeType === TypeScript.NodeType.ModuleDeclaration) && ((this.parent()).name === this.ast());
        };
        AstPath.prototype.isNameOfFunction = function () {
            if(this.ast() === null || this.parent() === null) {
                return false;
            }
            return (this.ast().nodeType === TypeScript.NodeType.Name) && (this.parent().nodeType === TypeScript.NodeType.FuncDecl) && ((this.parent()).name === this.ast());
        };
        AstPath.prototype.isChildOfScript = function () {
            var ast = lastOf(this.asts);
            return this.count() >= 3 && this.asts[this.top] === ast && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && this.asts[this.top - 2].nodeType === TypeScript.NodeType.Script;
        };
        AstPath.prototype.isChildOfModule = function () {
            var ast = lastOf(this.asts);
            return this.count() >= 3 && this.asts[this.top] === ast && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && this.asts[this.top - 2].nodeType === TypeScript.NodeType.ModuleDeclaration;
        };
        AstPath.prototype.isChildOfClass = function () {
            var ast = lastOf(this.asts);
            return this.count() >= 3 && this.asts[this.top] === ast && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && this.asts[this.top - 2].nodeType === TypeScript.NodeType.ClassDeclaration;
        };
        AstPath.prototype.isArgumentOfClassConstructor = function () {
            var ast = lastOf(this.asts);
            return this.count() >= 5 && this.asts[this.top] === ast && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && this.asts[this.top - 2].nodeType === TypeScript.NodeType.FuncDecl && this.asts[this.top - 3].nodeType === TypeScript.NodeType.List && this.asts[this.top - 4].nodeType === TypeScript.NodeType.ClassDeclaration && ((this.asts[this.top - 2]).isConstructor) && ((this.asts[this.top - 2]).arguments === this.asts[this.top - 1]) && ((this.asts[this.top - 4]).constructorDecl === this.asts[this.top - 2]);
        };
        AstPath.prototype.isChildOfInterface = function () {
            var ast = lastOf(this.asts);
            return this.count() >= 3 && this.asts[this.top] === ast && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && this.asts[this.top - 2].nodeType === TypeScript.NodeType.InterfaceDeclaration;
        };
        AstPath.prototype.isTopLevelImplicitModule = function () {
            return this.count() >= 1 && this.asts[this.top].nodeType === TypeScript.NodeType.ModuleDeclaration && TypeScript.hasFlag((this.asts[this.top]).modFlags, TypeScript.ModuleFlags.IsWholeFile);
        };
        AstPath.prototype.isBodyOfTopLevelImplicitModule = function () {
            return this.count() >= 2 && this.asts[this.top - 0].nodeType === TypeScript.NodeType.List && this.asts[this.top - 1].nodeType === TypeScript.NodeType.ModuleDeclaration && (this.asts[this.top - 1]).members == this.asts[this.top - 0] && TypeScript.hasFlag((this.asts[this.top - 1]).modFlags, TypeScript.ModuleFlags.IsWholeFile);
        };
        AstPath.prototype.isBodyOfScript = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Script && (this.asts[this.top - 1]).bod == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfSwitch = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Switch && (this.asts[this.top - 1]).caseList == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfModule = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.ModuleDeclaration && (this.asts[this.top - 1]).members == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfClass = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.ClassDeclaration && (this.asts[this.top - 1]).members == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfFunction = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.FuncDecl && (this.asts[this.top - 1]).bod == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfInterface = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.InterfaceDeclaration && (this.asts[this.top - 1]).members == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfBlock = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Block && (this.asts[this.top - 1]).statements == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfFor = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.For && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfCase = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Case && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfTry = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Try && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfCatch = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Catch && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfDoWhile = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.DoWhile && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfWhile = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.While && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfForIn = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.ForIn && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfWith = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.With && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfFinally = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Finally && (this.asts[this.top - 1]).body == this.asts[this.top - 0];
        };
        AstPath.prototype.isCaseOfSwitch = function () {
            return this.count() >= 3 && this.asts[this.top - 2].nodeType === TypeScript.NodeType.Switch && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && (this.asts[this.top - 2]).caseList == this.asts[this.top - 1];
        };
        AstPath.prototype.isDefaultCaseOfSwitch = function () {
            return this.count() >= 3 && this.asts[this.top - 2].nodeType === TypeScript.NodeType.Switch && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && (this.asts[this.top - 2]).caseList == this.asts[this.top - 1] && (this.asts[this.top - 2]).defaultCase == this.asts[this.top - 0];
        };
        AstPath.prototype.isListOfObjectLit = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.ObjectLit && this.asts[this.top - 0].nodeType === TypeScript.NodeType.List && (this.asts[this.top - 1]).operand == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfObjectLit = function () {
            return this.isListOfObjectLit();
        };
        AstPath.prototype.isEmptyListOfObjectLit = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.ObjectLit && this.asts[this.top - 0].nodeType === TypeScript.NodeType.List && (this.asts[this.top - 1]).operand == this.asts[this.top - 0] && (this.asts[this.top - 0]).members.length == 0;
        };
        AstPath.prototype.isMemberOfObjectLit = function () {
            return this.count() >= 3 && this.asts[this.top - 2].nodeType === TypeScript.NodeType.ObjectLit && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && this.asts[this.top - 0].nodeType === TypeScript.NodeType.Member && (this.asts[this.top - 2]).operand == this.asts[this.top - 1];
        };
        AstPath.prototype.isNameOfMemberOfObjectLit = function () {
            return this.count() >= 4 && this.asts[this.top - 3].nodeType === TypeScript.NodeType.ObjectLit && this.asts[this.top - 2].nodeType === TypeScript.NodeType.List && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member && this.asts[this.top - 0].nodeType === TypeScript.NodeType.Name && (this.asts[this.top - 3]).operand == this.asts[this.top - 2];
        };
        AstPath.prototype.isListOfArrayLit = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.ArrayLit && this.asts[this.top - 0].nodeType === TypeScript.NodeType.List && (this.asts[this.top - 1]).operand == this.asts[this.top - 0];
        };
        AstPath.prototype.isTargetOfMember = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member && (this.asts[this.top - 1]).operand1 === this.asts[this.top - 0];
        };
        AstPath.prototype.isMemberOfMember = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member && (this.asts[this.top - 1]).operand2 === this.asts[this.top - 0];
        };
        AstPath.prototype.isItemOfList = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List;
        };
        AstPath.prototype.isThenOfIf = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.If && (this.asts[this.top - 1]).thenBod == this.asts[this.top - 0];
        };
        AstPath.prototype.isElseOfIf = function () {
            return this.count() >= 2 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.If && (this.asts[this.top - 1]).elseBod == this.asts[this.top - 0];
        };
        AstPath.prototype.isBodyOfDefaultCase = function () {
            return this.isBodyOfCase();
        };
        AstPath.prototype.isSingleStatementList = function () {
            return this.count() >= 1 && this.asts[this.top].nodeType === TypeScript.NodeType.List && (this.asts[this.top]).members.length === 1;
        };
        AstPath.prototype.isArgumentListOfFunction = function () {
            return this.count() >= 2 && this.asts[this.top - 0].nodeType === TypeScript.NodeType.List && this.asts[this.top - 1].nodeType === TypeScript.NodeType.FuncDecl && (this.asts[this.top - 1]).arguments === this.asts[this.top - 0];
        };
        AstPath.prototype.isArgumentOfFunction = function () {
            return this.count() >= 3 && this.asts[this.top - 1].nodeType === TypeScript.NodeType.List && this.asts[this.top - 2].nodeType === TypeScript.NodeType.FuncDecl && (this.asts[this.top - 2]).arguments === this.asts[this.top - 1];
        };
        AstPath.prototype.isArgumentListOfCall = function () {
            return this.count() >= 2 && this.asts[this.top - 0].nodeType === TypeScript.NodeType.List && this.asts[this.top - 1].nodeType === TypeScript.NodeType.Call && (this.asts[this.top - 1]).arguments === this.asts[this.top - 0];
        };
        AstPath.prototype.isArgumentListOfNew = function () {
            return this.count() >= 2 && this.asts[this.top - 0].nodeType === TypeScript.NodeType.List && this.asts[this.top - 1].nodeType === TypeScript.NodeType.New && (this.asts[this.top - 1]).arguments === this.asts[this.top - 0];
        };
        AstPath.prototype.isSynthesizedBlock = function () {
            return this.count() >= 1 && this.asts[this.top - 0].nodeType === TypeScript.NodeType.Block && (this.asts[this.top - 0]).isStatementBlock === false;
        };
        return AstPath;
    })();
    TypeScript.AstPath = AstPath;    
    function isValidAstNode(ast) {
        if(ast === null) {
            return false;
        }
        if(ast.minChar === -1 || ast.limChar === -1) {
            return false;
        }
        return true;
    }
    TypeScript.isValidAstNode = isValidAstNode;
    var AstPathContext = (function () {
        function AstPathContext() {
            this.path = new TypeScript.AstPath();
        }
        return AstPathContext;
    })();
    TypeScript.AstPathContext = AstPathContext;    
    (function (GetAstPathOptions) {
        GetAstPathOptions._map = [];
        GetAstPathOptions.Default = 0;
        GetAstPathOptions.EdgeInclusive = 1;
        GetAstPathOptions.DontPruneSearchBasedOnPosition = 1 << 1;
    })(TypeScript.GetAstPathOptions || (TypeScript.GetAstPathOptions = {}));
    var GetAstPathOptions = TypeScript.GetAstPathOptions;
    function getAstPathToPosition(script, pos, options) {
        if (typeof options === "undefined") { options = GetAstPathOptions.Default; }
        var lookInComments = function (comments) {
            if(comments && comments.length > 0) {
                for(var i = 0; i < comments.length; i++) {
                    var minChar = comments[i].minChar;
                    var limChar = comments[i].limChar;
                    if(!comments[i].isBlockComment) {
                        limChar++;
                    }
                    if(pos >= minChar && pos < limChar) {
                        ctx.path.push(comments[i]);
                    }
                }
            }
        };
        var pre = function (cur, parent, walker) {
            if(isValidAstNode(cur)) {
                var inclusive = TypeScript.hasFlag(options, GetAstPathOptions.EdgeInclusive) || cur.nodeType === TypeScript.NodeType.Name || pos === script.limChar;
                var minChar = cur.minChar;
                var limChar = cur.limChar + (inclusive ? 1 : 0);
                if(pos >= minChar && pos < limChar) {
                    var previous = ctx.path.ast();
                    if(previous == null || (cur.minChar >= previous.minChar && cur.limChar <= previous.limChar)) {
                        ctx.path.push(cur);
                    } else {
                    }
                }
                if(pos < limChar) {
                    lookInComments(cur.preComments);
                }
                if(pos >= minChar) {
                    lookInComments(cur.postComments);
                }
                if(!TypeScript.hasFlag(options, GetAstPathOptions.DontPruneSearchBasedOnPosition)) {
                    walker.options.goChildren = (minChar <= pos && pos <= limChar);
                }
            }
            return cur;
        };
        var ctx = new AstPathContext();
        TypeScript.getAstWalkerFactory().walk(script, pre, null, null, ctx);
        return ctx.path;
    }
    TypeScript.getAstPathToPosition = getAstPathToPosition;
    function getTokenizationOffset(script, position) {
        var bestOffset = 0;
        var pre = function (cur, parent, walker) {
            if(TypeScript.isValidAstNode(cur)) {
                if(cur.minChar <= position) {
                    bestOffset = max(bestOffset, cur.minChar);
                }
                if(cur.minChar > position || cur.limChar < bestOffset) {
                    walker.options.goChildren = false;
                }
            }
            return cur;
        };
        TypeScript.getAstWalkerFactory().walk(script, pre);
        return bestOffset;
    }
    TypeScript.getTokenizationOffset = getTokenizationOffset;
    function walkAST(ast, callback) {
        var pre = function (cur, parent, walker) {
            var path = walker.state;
            path.push(cur);
            callback(path, walker);
            return cur;
        };
        var post = function (cur, parent, walker) {
            var path = walker.state;
            path.pop();
            return cur;
        };
        var path = new AstPath();
        TypeScript.getAstWalkerFactory().walk(ast, pre, post, null, path);
    }
    TypeScript.walkAST = walkAST;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var AstLogger = (function () {
        function AstLogger(logger) {
            this.logger = logger;
        }
        AstLogger.prototype.logScript = function (script) {
            var _this = this;
            this.logLinemap(script.locationInfo.lineMap);
            var stack = [];
            var pre = function (cur, parent) {
                stack.push(cur);
                var indent = (stack.length - 1) * 2;
                _this.logComments(script, cur.preComments, indent);
                _this.logNode(script, cur, indent);
                _this.logComments(script, cur.postComments, indent);
                return cur;
            };
            var post = function (cur, parent) {
                stack.pop();
                return cur;
            };
            TypeScript.getAstWalkerFactory().walk(script, pre, post);
        };
        AstLogger.prototype.logNode = function (script, cur, indent) {
            var msg = this.addPadding("", indent, "| ", true);
            msg = msg.concat("+ " + cur.treeViewLabel());
            msg = this.addPadding(msg, 70, " ", false);
            msg = msg + this.addLineColumn(script, cur.minChar);
            msg = this.addPadding(msg, 80, " ", false);
            msg = msg + "=> ";
            msg = msg + this.addLineColumn(script, cur.limChar);
            msg = this.addPadding(msg, 102, " ", false);
            msg = msg.concat("[" + this.addPadding(cur.minChar.toString(), 1, " ", true) + ", " + this.addPadding(cur.limChar.toString(), 1, " ", true) + "]");
            msg = this.addPadding(msg, 115, " ", false);
            msg = msg.concat("sym=" + (cur).sym);
            msg = this.addPadding(msg, 135, " ", false);
            msg = msg.concat("type=" + (cur.type === null ? "null" : cur.type.getTypeName()));
            this.logger.log(msg);
        };
        AstLogger.prototype.logComments = function (script, comments, indent) {
            if(comments == null) {
                return;
            }
            for(var i = 0; i < comments.length; i++) {
                this.logNode(script, comments[i], indent);
            }
        };
        AstLogger.prototype.logLinemap = function (linemap) {
            var result = "[";
            for(var i = 0; i < linemap.length; i++) {
                if(i > 0) {
                    result += ",";
                }
                result += linemap[i];
            }
            result += "]";
            this.logger.log("linemap: " + result);
        };
        AstLogger.prototype.addPadding = function (s, targetLength, paddingString, leftPadding) {
            var result = (leftPadding ? "" : s);
            for(var i = s.length; i < targetLength; i++) {
                result = result + paddingString;
            }
            result = result + (leftPadding ? s : "");
            return result;
        };
        AstLogger.prototype.addLineColumn = function (script, position) {
            var lineInfo = {
                line: -1,
                col: -1
            };
            TypeScript.getSourceLineColFromMap(lineInfo, position, script.locationInfo.lineMap);
            if(lineInfo.col !== -1) {
                lineInfo.col++;
            }
            return "(" + lineInfo.line + ", " + lineInfo.col + ")";
        };
        return AstLogger;
    })();
    TypeScript.AstLogger = AstLogger;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var Binder = (function () {
        function Binder(checker) {
            this.checker = checker;
        }
        Binder.prototype.resolveBaseTypeLinks = function (typeLinks, scope) {
            var extendsList = null;
            if(typeLinks) {
                extendsList = new Array();
                for(var i = 0, len = typeLinks.length; i < len; i++) {
                    extendsList[i] = this.checker.resolveBaseTypeLink(typeLinks[i], scope);
                }
            }
            return extendsList;
        };
        Binder.prototype.resolveBases = function (scope, type) {
            type.extendsList = this.resolveBaseTypeLinks(type.extendsTypeLinks, scope);
            var i = 0, len = type.extendsList.length;
            var derivedIsClass = type.isClassInstance();
            for(; i < len; i++) {
                var baseIsClass = type.extendsList[i].isClassInstance();
                if(type.extendsList[i] != this.checker.anyType) {
                    var baseRef = type.extendsTypeLinks[i].ast;
                    if(derivedIsClass) {
                        if(!baseIsClass) {
                            this.checker.errorReporter.simpleError(baseRef, "A class may only extend other classes, " + type.extendsList[i].symbol.fullName() + " is not a class.");
                        }
                    } else {
                        if(baseIsClass) {
                            this.checker.errorReporter.simpleError(baseRef, "An interface may only extend other interfaces, " + type.extendsList[i].symbol.fullName() + " is a class.");
                        }
                    }
                }
            }
            type.implementsList = this.resolveBaseTypeLinks(type.implementsTypeLinks, scope);
            if(type.implementsList) {
                for(i = 0 , len = type.implementsList.length; i < len; i++) {
                    var iface = type.implementsList[i];
                    var baseRef = type.implementsTypeLinks[i].ast;
                    if(iface.isClassInstance()) {
                        if(derivedIsClass) {
                            this.checker.errorReporter.simpleError(baseRef, "A class may only implement an interface; " + iface.symbol.fullName() + " is a class.");
                        }
                    }
                }
            }
        };
        Binder.prototype.resolveSignatureGroup = function (signatureGroup, scope, instanceType) {
            var supplyVar = !(signatureGroup.hasImplementation);
            for(var i = 0, len = signatureGroup.signatures.length; i < len; i++) {
                var signature = signatureGroup.signatures[i];
                if(instanceType) {
                    signature.returnType.type = instanceType;
                } else {
                    this.checker.resolveTypeLink(scope, signature.returnType, supplyVar);
                }
                var paramLen = signature.parameters.length;
                for(var j = 0; j < paramLen; j++) {
                    this.bindSymbol(scope, signature.parameters[j]);
                }
                if(signature.hasVariableArgList) {
                    var lastParam = signature.parameters[paramLen - 1];
                    lastParam.argsOffset = paramLen - 1;
                    if(!lastParam.getType().isArray()) {
                        this.checker.errorReporter.simpleErrorFromSym(lastParam, "... parameter must have array type");
                        lastParam.parameter.typeLink.type = this.checker.makeArrayType(lastParam.parameter.typeLink.type);
                    }
                }
            }
        };
        Binder.prototype.bindType = function (scope, type, instanceType) {
            if(instanceType) {
                this.bindType(scope, instanceType, null);
            }
            if(type.hasMembers()) {
                var members = type.members;
                var ambientMembers = type.ambientMembers;
                var typeMembers = type.getAllEnclosedTypes();
                var ambientTypeMembers = type.getAllAmbientEnclosedTypes();
                var memberScope = new TypeScript.SymbolTableScope(members, ambientMembers, typeMembers, ambientTypeMembers, type.symbol);
                var agg = new TypeScript.SymbolAggregateScope(type.symbol);
                var prevCurrentModDecl = this.checker.currentModDecl;
                var prevBindStatus = this.checker.inBind;
                agg.addParentScope(memberScope);
                agg.addParentScope(scope);
                if(type.isModuleType()) {
                    this.checker.currentModDecl = type.symbol.declAST;
                    this.checker.inBind = true;
                }
                if(members) {
                    this.bind(agg, type.members.allMembers);
                }
                if(typeMembers) {
                    this.bind(agg, typeMembers.allMembers);
                }
                if(ambientMembers) {
                    this.bind(agg, ambientMembers.allMembers);
                }
                if(ambientTypeMembers) {
                    this.bind(agg, ambientTypeMembers.allMembers);
                }
                this.checker.currentModDecl = prevCurrentModDecl;
                this.checker.inBind = prevBindStatus;
            }
            if(type.extendsTypeLinks) {
                this.resolveBases(scope, type);
            }
            if(type.construct) {
                this.resolveSignatureGroup(type.construct, scope, instanceType);
            }
            if(type.call) {
                this.resolveSignatureGroup(type.call, scope, null);
            }
            if(type.index) {
                this.resolveSignatureGroup(type.index, scope, null);
            }
            if(type.elementType) {
                this.bindType(scope, type.elementType, null);
            }
        };
        Binder.prototype.bindSymbol = function (scope, symbol) {
            if(!symbol.bound) {
                var prevLocationInfo = this.checker.locationInfo;
                if((this.checker.units) && (symbol.unitIndex >= 0) && (symbol.unitIndex < this.checker.units.length)) {
                    this.checker.locationInfo = this.checker.units[symbol.unitIndex];
                }
                switch(symbol.kind()) {
                    case TypeScript.SymbolKind.Type: {
                        if(symbol.flags & TypeScript.SymbolFlags.Bound) {
                            break;
                        }
                        var typeSymbol = symbol;
                        typeSymbol.flags |= TypeScript.SymbolFlags.Bound;
                        if(typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == TypeScript.NodeType.Name) {
                            var modPath = (typeSymbol.aliasLink.alias).text;
                            var modSym = this.checker.findSymbolForDynamicModule(modPath, this.checker.locationInfo.filename, function (id) {
                                return scope.find(id, false, true);
                            });
                            if(modSym) {
                                typeSymbol.type = modSym.getType();
                            }
                        }
                        if(typeSymbol.type && typeSymbol.type != this.checker.gloModType) {
                            this.bindType(scope, typeSymbol.type, typeSymbol.instanceType);
                            if(typeSymbol.type.isModuleType()) {
                                for(var i = 0; i < typeSymbol.expansions.length; i++) {
                                    this.bindType(scope, typeSymbol.expansions[i], typeSymbol.instanceType);
                                }
                            }
                        }
                        break;

                    }
                    case TypeScript.SymbolKind.Field: {
                        this.checker.resolveTypeLink(scope, (symbol).field.typeLink, false);
                        break;

                    }
                    case TypeScript.SymbolKind.Parameter: {
                        this.checker.resolveTypeLink(scope, (symbol).parameter.typeLink, true);
                        break;

                    }
                }
                this.checker.locationInfo = prevLocationInfo;
            }
            symbol.bound = true;
        };
        Binder.prototype.bind = function (scope, table) {
            table.map(function (key, sym, binder) {
                binder.bindSymbol(scope, sym);
            }, this);
        };
        return Binder;
    })();
    TypeScript.Binder = Binder;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var Base64Format = (function () {
        function Base64Format() { }
        Base64Format.encodedValues = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        Base64Format.encode = function encode(inValue) {
            if(inValue < 64) {
                return Base64Format.encodedValues.charAt(inValue);
            }
            throw TypeError(inValue + ": not a 64 based value");
        }
        Base64Format.decodeChar = function decodeChar(inChar) {
            if(inChar.length === 1) {
                return Base64Format.encodedValues.indexOf(inChar);
            } else {
                throw TypeError('"' + inChar + '" must have length 1');
            }
        }
        return Base64Format;
    })();    
    var Base64VLQFormat = (function () {
        function Base64VLQFormat() { }
        Base64VLQFormat.encode = function encode(inValue) {
            if(inValue < 0) {
                inValue = ((-inValue) << 1) + 1;
            } else {
                inValue = inValue << 1;
            }
            var encodedStr = "";
            do {
                var currentDigit = inValue & 31;
                inValue = inValue >> 5;
                if(inValue > 0) {
                    currentDigit = currentDigit | 32;
                }
                encodedStr = encodedStr + Base64Format.encode(currentDigit);
            }while(inValue > 0)
            return encodedStr;
        }
        Base64VLQFormat.decode = function decode(inString) {
            var result = 0;
            var negative = false;
            var shift = 0;
            for(var i = 0; i < inString.length; i++) {
                var byte = Base64Format.decodeChar(inString[i]);
                if(i === 0) {
                    if((byte & 1) === 1) {
                        negative = true;
                    }
                    result = (byte >> 1) & 15;
                } else {
                    result = result | ((byte & 31) << shift);
                }
                shift += (i == 0) ? 4 : 5;
                if((byte & 32) === 32) {
                } else {
                    return {
                        value: negative ? -(result) : result,
                        rest: inString.substr(i + 1)
                    };
                }
            }
            throw new Error('Base64 value "' + inString + '" finished with a continuation bit');
        }
        return Base64VLQFormat;
    })();
    TypeScript.Base64VLQFormat = Base64VLQFormat;    
})(TypeScript || (TypeScript = {}));
var JSON2 = {
};
((function () {
    'use strict';
    function f(n) {
        return n < 10 ? '0' + n : n;
    }
    if(typeof Date.prototype.toJSON !== 'function') {
        Date.prototype.toJSON = function (key) {
            return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null;
        };
        var strProto = String.prototype;
        var numProto = Number.prototype;
        numProto.JSON = strProto.JSON = (Boolean).prototype.toJSON = function (key) {
            return this.valueOf();
        };
    }
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"': '\\"',
'\\': '\\\\'    }, rep;
    function quote(string) {
        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' : '"' + string + '"';
    }
    function str(key, holder) {
        var i, k = null, v, length, mind = gap, partial, value = holder[key];
        if(value && typeof value === 'object' && typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }
        if(typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }
        switch(typeof value) {
            case 'string': {
                return quote(value);

            }
            case 'number': {
                return isFinite(value) ? String(value) : 'null';

            }
            case 'boolean':
            case 'null': {
                return String(value);

            }
            case 'object': {
                if(!value) {
                    return 'null';
                }
                gap += indent;
                partial = [];
                if(Object.prototype.toString.apply(value, []) === '[object Array]') {
                    length = value.length;
                    for(i = 0; i < length; i += 1) {
                        partial[i] = str(i, value) || 'null';
                    }
                    v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
                    gap = mind;
                    return v;
                }
                if(rep && typeof rep === 'object') {
                    length = rep.length;
                    for(i = 0; i < length; i += 1) {
                        if(typeof rep[i] === 'string') {
                            k = rep[i];
                            v = str(k, value);
                            if(v) {
                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
                            }
                        }
                    }
                } else {
                    for(k in value) {
                        if(Object.prototype.hasOwnProperty.call(value, k)) {
                            v = str(k, value);
                            if(v) {
                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
                            }
                        }
                    }
                }
                v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}';
                gap = mind;
                return v;

            }
        }
    }
    if(typeof JSON2.stringify !== 'function') {
        JSON2.stringify = function (value, replacer, space) {
            var i;
            gap = '';
            indent = '';
            if(typeof space === 'number') {
                for(i = 0; i < space; i += 1) {
                    indent += ' ';
                }
            } else {
                if(typeof space === 'string') {
                    indent = space;
                }
            }
            rep = replacer;
            if(replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }
            return str('', {
                '': value
            });
        };
    }
    if(typeof JSON2.parse !== 'function') {
        JSON2.parse = function (text, reviver) {
            var j;
            function walk(holder, key) {
                var k = null, v, value = holder[key];
                if(value && typeof value === 'object') {
                    for(k in value) {
                        if(Object.prototype.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if(v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }
            text = String(text);
            cx.lastIndex = 0;
            if(cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }
            if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
                j = eval('(' + text + ')');
                return typeof reviver === 'function' ? walk({
                    '': j
                }, '') : j;
            }
            throw new SyntaxError('JSON.parse');
        };
    }
})());
var TypeScript;
(function (TypeScript) {
    var SourceMapPosition = (function () {
        function SourceMapPosition() { }
        return SourceMapPosition;
    })();
    TypeScript.SourceMapPosition = SourceMapPosition;    
    var SourceMapping = (function () {
        function SourceMapping() {
            this.start = new SourceMapPosition();
            this.end = new SourceMapPosition();
            this.nameIndex = -1;
            this.childMappings = [];
        }
        return SourceMapping;
    })();
    TypeScript.SourceMapping = SourceMapping;    
    var SourceMapper = (function () {
        function SourceMapper(tsFileName, jsFileName, jsFile, sourceMapOut, errorReporter) {
            this.jsFile = jsFile;
            this.sourceMapOut = sourceMapOut;
            this.errorReporter = errorReporter;
            this.sourceMappings = [];
            this.currentMappings = [];
            this.names = [];
            this.currentNameIndex = [];
            this.currentMappings.push(this.sourceMappings);
            jsFileName = TypeScript.switchToForwardSlashes(jsFileName);
            this.jsFileName = TypeScript.getPrettyName(jsFileName, false, true);
            var removalIndex = jsFileName.lastIndexOf(this.jsFileName);
            var fixedPath = jsFileName.substring(0, removalIndex);
            this.tsFileName = TypeScript.getRelativePathToFixedPath(fixedPath, tsFileName);
        }
        SourceMapper.MapFileExtension = ".map";
        SourceMapper.EmitSourceMapping = function EmitSourceMapping(allSourceMappers) {
            var sourceMapper = allSourceMappers[0];
            sourceMapper.jsFile.WriteLine("//@ sourceMappingURL=" + sourceMapper.jsFileName + SourceMapper.MapFileExtension);
            var sourceMapOut = sourceMapper.sourceMapOut;
            var mappingsString = "";
            var tsFiles = [];
            var prevEmittedColumn = 0;
            var prevEmittedLine = 0;
            var prevSourceColumn = 0;
            var prevSourceLine = 0;
            var prevSourceIndex = 0;
            var prevNameIndex = 0;
            var namesList = [];
            var namesCount = 0;
            var emitComma = false;
            var recordedPosition = null;
            for(var sourceMapperIndex = 0; sourceMapperIndex < allSourceMappers.length; sourceMapperIndex++) {
                sourceMapper = allSourceMappers[sourceMapperIndex];
                var currentSourceIndex = tsFiles.length;
                tsFiles.push(sourceMapper.tsFileName);
                if(sourceMapper.names.length > 0) {
                    namesList.push.apply(namesList, sourceMapper.names);
                }
                var recordSourceMapping = function (mappedPosition, nameIndex) {
                    if(recordedPosition != null && recordedPosition.emittedColumn == mappedPosition.emittedColumn && recordedPosition.emittedLine == mappedPosition.emittedLine) {
                        return;
                    }
                    if(prevEmittedLine !== mappedPosition.emittedLine) {
                        while(prevEmittedLine < mappedPosition.emittedLine) {
                            prevEmittedColumn = 0;
                            mappingsString = mappingsString + ";";
                            prevEmittedLine++;
                        }
                        emitComma = false;
                    } else {
                        if(emitComma) {
                            mappingsString = mappingsString + ",";
                        }
                    }
                    mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(mappedPosition.emittedColumn - prevEmittedColumn);
                    prevEmittedColumn = mappedPosition.emittedColumn;
                    mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(currentSourceIndex - prevSourceIndex);
                    prevSourceIndex = currentSourceIndex;
                    mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(mappedPosition.sourceLine - 1 - prevSourceLine);
                    prevSourceLine = mappedPosition.sourceLine - 1;
                    mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(mappedPosition.sourceColumn - prevSourceColumn);
                    prevSourceColumn = mappedPosition.sourceColumn;
                    if(nameIndex >= 0) {
                        mappingsString = mappingsString + TypeScript.Base64VLQFormat.encode(namesCount + nameIndex - prevNameIndex);
                        prevNameIndex = namesCount + nameIndex;
                    }
                    emitComma = true;
                    recordedPosition = mappedPosition;
                };
                var recordSourceMappingSiblings = function (sourceMappings) {
                    for(var i = 0; i < sourceMappings.length; i++) {
                        var sourceMapping = sourceMappings[i];
                        recordSourceMapping(sourceMapping.start, sourceMapping.nameIndex);
                        recordSourceMappingSiblings(sourceMapping.childMappings);
                        recordSourceMapping(sourceMapping.end, sourceMapping.nameIndex);
                    }
                };
                recordSourceMappingSiblings(sourceMapper.sourceMappings, -1);
                namesCount = namesCount + sourceMapper.names.length;
            }
            if(mappingsString != "") {
                sourceMapOut.Write(JSON2.stringify({
                    version: 3,
                    file: sourceMapper.jsFileName,
                    sources: tsFiles,
                    names: namesList,
                    mappings: mappingsString
                }));
            }
            try  {
                sourceMapOut.Close();
            } catch (ex) {
                sourceMapper.errorReporter.emitterError(null, ex.message);
            }
        }
        return SourceMapper;
    })();
    TypeScript.SourceMapper = SourceMapper;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (EmitContainer) {
        EmitContainer._map = [];
        EmitContainer._map[0] = "Prog";
        EmitContainer.Prog = 0;
        EmitContainer._map[1] = "Module";
        EmitContainer.Module = 1;
        EmitContainer._map[2] = "DynamicModule";
        EmitContainer.DynamicModule = 2;
        EmitContainer._map[3] = "Class";
        EmitContainer.Class = 3;
        EmitContainer._map[4] = "Constructor";
        EmitContainer.Constructor = 4;
        EmitContainer._map[5] = "Function";
        EmitContainer.Function = 5;
        EmitContainer._map[6] = "Args";
        EmitContainer.Args = 6;
        EmitContainer._map[7] = "Interface";
        EmitContainer.Interface = 7;
    })(TypeScript.EmitContainer || (TypeScript.EmitContainer = {}));
    var EmitContainer = TypeScript.EmitContainer;
    var EmitState = (function () {
        function EmitState() {
            this.column = 0;
            this.line = 0;
            this.pretty = false;
            this.inObjectLiteral = false;
            this.container = EmitContainer.Prog;
        }
        return EmitState;
    })();
    TypeScript.EmitState = EmitState;    
    var EmitOptions = (function () {
        function EmitOptions(settings) {
            this.ioHost = null;
            this.outputMany = true;
            this.commonDirectoryPath = "";
            this.minWhitespace = settings.minWhitespace;
            this.propagateConstants = settings.propagateConstants;
            this.emitComments = settings.emitComments;
            this.outputOption = settings.outputOption;
        }
        EmitOptions.prototype.mapOutputFileName = function (fileName, extensionChanger) {
            if(this.outputMany) {
                var updatedFileName = fileName;
                if(this.outputOption != "") {
                    updatedFileName = fileName.replace(this.commonDirectoryPath, "");
                    updatedFileName = this.outputOption + updatedFileName;
                }
                return extensionChanger(updatedFileName, false);
            } else {
                return extensionChanger(this.outputOption, true);
            }
        };
        return EmitOptions;
    })();
    TypeScript.EmitOptions = EmitOptions;    
    var Indenter = (function () {
        function Indenter() {
            this.indentAmt = 0;
        }
        Indenter.indentStep = 4;
        Indenter.indentStepString = "    ";
        Indenter.indentStrings = [];
        Indenter.prototype.increaseIndent = function () {
            this.indentAmt += Indenter.indentStep;
        };
        Indenter.prototype.decreaseIndent = function () {
            this.indentAmt -= Indenter.indentStep;
        };
        Indenter.prototype.getIndent = function () {
            var indentString = Indenter.indentStrings[this.indentAmt];
            if(indentString === undefined) {
                indentString = "";
                for(var i = 0; i < this.indentAmt; i = i + Indenter.indentStep) {
                    indentString += Indenter.indentStepString;
                }
                Indenter.indentStrings[this.indentAmt] = indentString;
            }
            return indentString;
        };
        return Indenter;
    })();
    TypeScript.Indenter = Indenter;    
    var Emitter = (function () {
        function Emitter(checker, emittingFileName, outfile, emitOptions, errorReporter) {
            this.checker = checker;
            this.emittingFileName = emittingFileName;
            this.outfile = outfile;
            this.emitOptions = emitOptions;
            this.errorReporter = errorReporter;
            this.prologueEmitted = false;
            this.thisClassNode = null;
            this.thisFnc = null;
            this.moduleDeclList = [];
            this.moduleName = "";
            this.emitState = new EmitState();
            this.indenter = new Indenter();
            this.ambientModule = false;
            this.modAliasId = null;
            this.firstModAlias = null;
            this.allSourceMappers = [];
            this.sourceMapper = null;
            this.captureThisStmtString = "var _this = this;";
            this.varListCountStack = [
                0
            ];
        }
        Emitter.prototype.setSourceMappings = function (mapper) {
            this.allSourceMappers.push(mapper);
            this.sourceMapper = mapper;
        };
        Emitter.prototype.writeToOutput = function (s) {
            this.outfile.Write(s);
            this.emitState.column += s.length;
        };
        Emitter.prototype.writeToOutputTrimmable = function (s) {
            if(this.emitOptions.minWhitespace) {
                s = s.replace(/[\s]*/g, '');
            }
            this.writeToOutput(s);
        };
        Emitter.prototype.writeLineToOutput = function (s) {
            if(this.emitOptions.minWhitespace) {
                this.writeToOutput(s);
                var c = s.charCodeAt(s.length - 1);
                if(!((c == TypeScript.LexCodeSpace) || (c == TypeScript.LexCodeSMC) || (c == TypeScript.LexCodeLBR))) {
                    this.writeToOutput(' ');
                }
            } else {
                this.outfile.WriteLine(s);
                this.emitState.column = 0;
                this.emitState.line++;
            }
        };
        Emitter.prototype.writeCaptureThisStatement = function (ast) {
            this.emitIndent();
            this.recordSourceMappingStart(ast);
            this.writeToOutput(this.captureThisStmtString);
            this.recordSourceMappingEnd(ast);
            this.writeLineToOutput("");
        };
        Emitter.prototype.setInVarBlock = function (count) {
            this.varListCountStack[this.varListCountStack.length - 1] = count;
        };
        Emitter.prototype.setInObjectLiteral = function (val) {
            var temp = this.emitState.inObjectLiteral;
            this.emitState.inObjectLiteral = val;
            return temp;
        };
        Emitter.prototype.setContainer = function (c) {
            var temp = this.emitState.container;
            this.emitState.container = c;
            return temp;
        };
        Emitter.prototype.getIndentString = function () {
            if(this.emitOptions.minWhitespace) {
                return "";
            } else {
                return this.indenter.getIndent();
            }
        };
        Emitter.prototype.emitIndent = function () {
            this.writeToOutput(this.getIndentString());
        };
        Emitter.prototype.emitCommentInPlace = function (comment) {
            this.recordSourceMappingStart(comment);
            var text = comment.getText();
            var hadNewLine = false;
            if(comment.isBlockComment) {
                if(this.emitState.column == 0) {
                    this.emitIndent();
                }
                this.writeToOutput(text[0]);
                if(text.length > 1 || comment.endsLine) {
                    this.writeLineToOutput("");
                    for(var i = 1; i < text.length; i++) {
                        this.emitIndent();
                        this.writeLineToOutput(text[i]);
                    }
                    hadNewLine = true;
                }
            } else {
                if(this.emitState.column == 0) {
                    this.emitIndent();
                }
                this.writeLineToOutput(text[0]);
                hadNewLine = true;
            }
            if(hadNewLine) {
                this.emitIndent();
            } else {
                this.writeToOutput(" ");
            }
            this.recordSourceMappingEnd(comment);
        };
        Emitter.prototype.emitParensAndCommentsInPlace = function (ast, pre) {
            var comments = pre ? ast.preComments : ast.postComments;
            if(ast.isParenthesized && !pre) {
                this.writeToOutput(")");
            }
            if(this.emitOptions.emitComments && comments && comments.length != 0) {
                for(var i = 0; i < comments.length; i++) {
                    this.emitCommentInPlace(comments[i]);
                }
            }
            if(ast.isParenthesized && pre) {
                this.writeToOutput("(");
            }
        };
        Emitter.prototype.emitObjectLiteral = function (content) {
            this.writeLineToOutput("{");
            this.indenter.increaseIndent();
            var inObjectLiteral = this.setInObjectLiteral(true);
            this.emitJavascriptList(content, ",", TypeScript.TokenID.Comma, true, false, false);
            this.setInObjectLiteral(inObjectLiteral);
            this.indenter.decreaseIndent();
            this.emitIndent();
            this.writeToOutput("}");
        };
        Emitter.prototype.emitArrayLiteral = function (content) {
            this.writeToOutput("[");
            if(content) {
                this.writeLineToOutput("");
                this.indenter.increaseIndent();
                this.emitJavascriptList(content, ", ", TypeScript.TokenID.Comma, true, false, false);
                this.indenter.decreaseIndent();
                this.emitIndent();
            }
            this.writeToOutput("]");
        };
        Emitter.prototype.emitNew = function (target, args) {
            this.writeToOutput("new ");
            if(target.nodeType == TypeScript.NodeType.TypeRef) {
                var typeRef = target;
                if(typeRef.arrayCount) {
                    this.writeToOutput("Array()");
                } else {
                    this.emitJavascript(typeRef.term, TypeScript.TokenID.Tilde, false);
                    this.writeToOutput("()");
                }
            } else {
                this.emitJavascript(target, TypeScript.TokenID.Tilde, false);
                this.recordSourceMappingStart(args);
                this.writeToOutput("(");
                this.emitJavascriptList(args, ", ", TypeScript.TokenID.Comma, false, false, false);
                this.writeToOutput(")");
                this.recordSourceMappingEnd(args);
            }
        };
        Emitter.prototype.tryEmitConstant = function (dotExpr) {
            if(!this.emitOptions.propagateConstants) {
                return false;
            }
            var propertyName = dotExpr.operand2;
            if(propertyName && propertyName.sym && propertyName.sym.isVariable()) {
                if(TypeScript.hasFlag(propertyName.sym.flags, TypeScript.SymbolFlags.Constant)) {
                    if(propertyName.sym.declAST) {
                        var boundDecl = propertyName.sym.declAST;
                        if(boundDecl.init && (boundDecl.init.nodeType == TypeScript.NodeType.NumberLit)) {
                            var numLit = boundDecl.init;
                            this.writeToOutput(numLit.value.toString());
                            var comment = " /* ";
                            comment += propertyName.actualText;
                            comment += " */ ";
                            this.writeToOutput(comment);
                            return true;
                        }
                    }
                }
            }
            return false;
        };
        Emitter.prototype.emitCall = function (callNode, target, args) {
            if(!this.emitSuperCall(callNode)) {
                if(!TypeScript.hasFlag(callNode.flags, TypeScript.ASTFlags.ClassBaseConstructorCall)) {
                    if(target.nodeType == TypeScript.NodeType.FuncDecl && !target.isParenthesized) {
                        this.writeToOutput("(");
                    }
                    if(callNode.target.nodeType == TypeScript.NodeType.Super && this.emitState.container == EmitContainer.Constructor) {
                        this.writeToOutput("_super.call");
                    } else {
                        this.emitJavascript(target, TypeScript.TokenID.OpenParen, false);
                    }
                    if(target.nodeType == TypeScript.NodeType.FuncDecl && !target.isParenthesized) {
                        this.writeToOutput(")");
                    }
                    this.recordSourceMappingStart(args);
                    this.writeToOutput("(");
                    if(callNode.target.nodeType == TypeScript.NodeType.Super && this.emitState.container == EmitContainer.Constructor) {
                        this.writeToOutput("this");
                        if(args && args.members.length) {
                            this.writeToOutput(", ");
                        }
                    }
                    this.emitJavascriptList(args, ", ", TypeScript.TokenID.Comma, false, false, false);
                    this.writeToOutput(")");
                    this.recordSourceMappingEnd(args);
                } else {
                    this.indenter.decreaseIndent();
                    this.indenter.decreaseIndent();
                    var constructorCall = new TypeScript.ASTList();
                    constructorCall.members[0] = callNode;
                    this.emitConstructorCalls(constructorCall, this.thisClassNode);
                    this.indenter.increaseIndent();
                    this.indenter.increaseIndent();
                }
            }
        };
        Emitter.prototype.emitConstructorCalls = function (bases, classDecl) {
            if(bases == null) {
                return;
            }
            var basesLen = bases.members.length;
            this.recordSourceMappingStart(classDecl);
            for(var i = 0; i < basesLen; i++) {
                var baseExpr = bases.members[i];
                var baseSymbol = null;
                if(baseExpr.nodeType == TypeScript.NodeType.Call) {
                    baseSymbol = (baseExpr).target.type.symbol;
                } else {
                    baseSymbol = baseExpr.type.symbol;
                }
                var baseName = baseSymbol.name;
                if(baseSymbol.declModule != classDecl.type.symbol.declModule) {
                    baseName = baseSymbol.fullName();
                }
                if(baseExpr.nodeType == TypeScript.NodeType.Call) {
                    this.emitIndent();
                    this.writeToOutput("_super.call(this");
                    var args = (baseExpr).arguments;
                    if(args && (args.members.length > 0)) {
                        this.writeToOutput(", ");
                        this.emitJavascriptList(args, ", ", TypeScript.TokenID.Comma, false, false, false);
                    }
                    this.writeToOutput(")");
                } else {
                    if(baseExpr.type && (baseExpr.type.isClassInstance())) {
                        this.emitIndent();
                        this.writeToOutput(classDecl.name.actualText + "._super.constructor");
                        this.writeToOutput(".call(this)");
                    }
                }
            }
            this.recordSourceMappingEnd(classDecl);
        };
        Emitter.prototype.emitInnerFunction = function (funcDecl, printName, isMember, bases, hasSelfRef, classDecl) {
            var isClassConstructor = funcDecl.isConstructor && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod);
            var hasNonObjectBaseType = isClassConstructor && TypeScript.hasFlag(this.thisClassNode.type.instanceType.typeFlags, TypeScript.TypeFlags.HasBaseType) && !TypeScript.hasFlag(this.thisClassNode.type.instanceType.typeFlags, TypeScript.TypeFlags.HasBaseTypeOfObject);
            var classPropertiesMustComeAfterSuperCall = hasNonObjectBaseType && TypeScript.hasFlag((this.thisClassNode).varFlags, TypeScript.VarFlags.ClassSuperMustBeFirstCallInConstructor);
            var shouldParenthesize = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.IsFunctionExpression) && !funcDecl.isParenthesized && !funcDecl.isAccessor() && (TypeScript.hasFlag(funcDecl.flags, TypeScript.ASTFlags.ExplicitSemicolon) || TypeScript.hasFlag(funcDecl.flags, TypeScript.ASTFlags.AutomaticSemicolon));
            this.emitParensAndCommentsInPlace(funcDecl, true);
            if(shouldParenthesize) {
                this.writeToOutput("(");
            }
            this.recordSourceMappingStart(funcDecl);
            if(!(funcDecl.isAccessor() && (funcDecl.accessorSymbol).isObjectLitField)) {
                this.writeToOutput("function ");
            }
            if(printName) {
                var id = funcDecl.getNameText();
                if(id && !funcDecl.isAccessor()) {
                    if(funcDecl.name) {
                        this.recordSourceMappingStart(funcDecl.name);
                    }
                    this.writeToOutput(id);
                    if(funcDecl.name) {
                        this.recordSourceMappingEnd(funcDecl.name);
                    }
                }
            }
            this.writeToOutput("(");
            var argsLen = 0;
            var i = 0;
            var arg;
            var defaultArgs = [];
            if(funcDecl.arguments) {
                var tempContainer = this.setContainer(EmitContainer.Args);
                argsLen = funcDecl.arguments.members.length;
                var printLen = argsLen;
                if(funcDecl.variableArgList) {
                    printLen--;
                }
                for(i = 0; i < printLen; i++) {
                    arg = funcDecl.arguments.members[i];
                    if(arg.init) {
                        defaultArgs.push(arg);
                    }
                    this.emitJavascript(arg, TypeScript.TokenID.OpenParen, false);
                    if(i < (printLen - 1)) {
                        this.writeToOutput(", ");
                    }
                }
                this.setContainer(tempContainer);
            }
            this.writeLineToOutput(") {");
            if(funcDecl.isConstructor) {
                this.recordSourceMappingNameStart("constructor");
            } else {
                if(funcDecl.isGetAccessor()) {
                    this.recordSourceMappingNameStart("get_" + funcDecl.getNameText());
                } else {
                    if(funcDecl.isSetAccessor()) {
                        this.recordSourceMappingNameStart("set_" + funcDecl.getNameText());
                    } else {
                        this.recordSourceMappingNameStart(funcDecl.getNameText());
                    }
                }
            }
            this.indenter.increaseIndent();
            for(i = 0; i < defaultArgs.length; i++) {
                var arg = defaultArgs[i];
                this.emitIndent();
                this.recordSourceMappingStart(arg);
                this.writeToOutput("if (typeof " + arg.id.actualText + " === \"undefined\") { ");
                this.recordSourceMappingStart(arg.id);
                this.writeToOutput(arg.id.actualText);
                this.recordSourceMappingEnd(arg.id);
                this.writeToOutput(" = ");
                this.emitJavascript(arg.init, TypeScript.TokenID.OpenParen, false);
                this.writeLineToOutput("; }");
                this.recordSourceMappingEnd(arg);
            }
            if(funcDecl.isConstructor && ((funcDecl.classDecl).varFlags & TypeScript.VarFlags.MustCaptureThis)) {
                this.writeCaptureThisStatement(funcDecl);
            }
            if(funcDecl.isConstructor && !classPropertiesMustComeAfterSuperCall) {
                if(funcDecl.arguments) {
                    argsLen = funcDecl.arguments.members.length;
                    for(i = 0; i < argsLen; i++) {
                        arg = funcDecl.arguments.members[i];
                        if((arg.varFlags & TypeScript.VarFlags.Property) != TypeScript.VarFlags.None) {
                            this.emitIndent();
                            this.recordSourceMappingStart(arg);
                            this.recordSourceMappingStart(arg.id);
                            this.writeToOutput("this." + arg.id.actualText);
                            this.recordSourceMappingEnd(arg.id);
                            this.writeToOutput(" = ");
                            this.recordSourceMappingStart(arg.id);
                            this.writeToOutput(arg.id.actualText);
                            this.recordSourceMappingEnd(arg.id);
                            this.writeLineToOutput(";");
                            this.recordSourceMappingEnd(arg);
                        }
                    }
                }
                if(!TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod)) {
                    this.emitConstructorCalls(bases, classDecl);
                }
            }
            if(hasSelfRef) {
                this.writeCaptureThisStatement(funcDecl);
            }
            if(funcDecl.variableArgList) {
                argsLen = funcDecl.arguments.members.length;
                var lastArg = funcDecl.arguments.members[argsLen - 1];
                this.emitIndent();
                this.recordSourceMappingStart(lastArg);
                this.writeToOutput("var ");
                this.recordSourceMappingStart(lastArg.id);
                this.writeToOutput(lastArg.id.actualText);
                this.recordSourceMappingEnd(lastArg.id);
                this.writeLineToOutput(" = [];");
                this.recordSourceMappingEnd(lastArg);
                this.emitIndent();
                this.writeToOutput("for (");
                this.recordSourceMappingStart(lastArg);
                this.writeToOutput("var _i = 0;");
                this.recordSourceMappingEnd(lastArg);
                this.writeToOutput(" ");
                this.recordSourceMappingStart(lastArg);
                this.writeToOutput("_i < (arguments.length - " + (argsLen - 1) + ")");
                this.recordSourceMappingEnd(lastArg);
                this.writeToOutput("; ");
                this.recordSourceMappingStart(lastArg);
                this.writeToOutput("_i++");
                this.recordSourceMappingEnd(lastArg);
                this.writeLineToOutput(") {");
                this.indenter.increaseIndent();
                this.emitIndent();
                this.recordSourceMappingStart(lastArg);
                this.writeToOutput(lastArg.id.actualText + "[_i] = arguments[_i + " + (argsLen - 1) + "];");
                this.recordSourceMappingEnd(lastArg);
                this.writeLineToOutput("");
                this.indenter.decreaseIndent();
                this.emitIndent();
                this.writeLineToOutput("}");
            }
            if(funcDecl.isConstructor && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod) && !classPropertiesMustComeAfterSuperCall) {
                var nProps = (this.thisClassNode.members).members.length;
                for(var i = 0; i < nProps; i++) {
                    if((this.thisClassNode.members).members[i].nodeType == TypeScript.NodeType.VarDecl) {
                        var varDecl = (this.thisClassNode.members).members[i];
                        if(!TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Static) && varDecl.init) {
                            this.emitIndent();
                            this.emitJavascriptVarDecl(varDecl, TypeScript.TokenID.Tilde);
                            this.writeLineToOutput("");
                        }
                    }
                }
            }
            this.emitBareJavascriptStatements(funcDecl.bod, classPropertiesMustComeAfterSuperCall);
            this.indenter.decreaseIndent();
            this.emitIndent();
            this.recordSourceMappingStart(funcDecl.endingToken);
            this.writeToOutput("}");
            this.recordSourceMappingNameEnd();
            this.recordSourceMappingEnd(funcDecl.endingToken);
            this.recordSourceMappingEnd(funcDecl);
            if(shouldParenthesize) {
                this.writeToOutput(")");
            }
            this.recordSourceMappingEnd(funcDecl);
            this.emitParensAndCommentsInPlace(funcDecl, false);
            if(!isMember && !TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.IsFunctionExpression) && (TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Definition) || funcDecl.isConstructor)) {
                this.writeLineToOutput("");
            } else {
                if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.IsFunctionExpression)) {
                    if(TypeScript.hasFlag(funcDecl.flags, TypeScript.ASTFlags.ExplicitSemicolon) || TypeScript.hasFlag(funcDecl.flags, TypeScript.ASTFlags.AutomaticSemicolon)) {
                        this.writeLineToOutput(";");
                    }
                }
            }
        };
        Emitter.prototype.emitJavascriptModule = function (moduleDecl) {
            var modName = moduleDecl.name.actualText;
            if(TypeScript.isTSFile(modName)) {
                moduleDecl.name.setText(modName.substring(0, modName.length - 3));
            } else {
                if(TypeScript.isSTRFile(modName)) {
                    moduleDecl.name.setText(modName.substring(0, modName.length - 4));
                }
            }
            if(!TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.Ambient)) {
                var isDynamicMod = TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.IsDynamic);
                var prevOutFile = this.outfile;
                var prevOutFileName = this.emittingFileName;
                var prevAllSourceMappers = this.allSourceMappers;
                var prevSourceMapper = this.sourceMapper;
                var prevColumn = this.emitState.column;
                var prevLine = this.emitState.line;
                var temp = this.setContainer(EmitContainer.Module);
                var svModuleName = this.moduleName;
                var isExported = TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.Exported);
                this.moduleDeclList[this.moduleDeclList.length] = moduleDecl;
                var isWholeFile = TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.IsWholeFile);
                this.moduleName = moduleDecl.name.actualText;
                if(isDynamicMod) {
                    var tsModFileName = TypeScript.stripQuotes(moduleDecl.name.actualText);
                    var modFilePath = TypeScript.trimModName(tsModFileName) + ".js";
                    modFilePath = this.emitOptions.mapOutputFileName(modFilePath, TypeScript.TypeScriptCompiler.mapToJSFileName);
                    if(this.emitOptions.ioHost) {
                        if(TypeScript.switchToForwardSlashes(modFilePath) != TypeScript.switchToForwardSlashes(this.emittingFileName)) {
                            this.emittingFileName = modFilePath;
                            var useUTF8InOutputfile = moduleDecl.containsUnicodeChar || (this.emitOptions.emitComments && moduleDecl.containsUnicodeCharInComment);
                            this.outfile = this.createFile(this.emittingFileName, useUTF8InOutputfile);
                            if(prevSourceMapper != null) {
                                this.allSourceMappers = [];
                                var sourceMappingFile = this.createFile(this.emittingFileName + TypeScript.SourceMapper.MapFileExtension, false);
                                this.setSourceMappings(new TypeScript.SourceMapper(tsModFileName, this.emittingFileName, this.outfile, sourceMappingFile, this.errorReporter));
                                this.emitState.column = 0;
                                this.emitState.line = 0;
                            }
                        } else {
                            TypeScript.CompilerDiagnostics.assert(this.emitOptions.outputMany, "Cannot have dynamic modules compiling into single file");
                        }
                    }
                    this.setContainer(EmitContainer.DynamicModule);
                    this.recordSourceMappingStart(moduleDecl);
                    if(TypeScript.moduleGenTarget == TypeScript.ModuleGenTarget.Asynchronous) {
                        var dependencyList = "[\"require\", \"exports\"";
                        var importList = "require, exports";
                        var importStatement = null;
                        for(var i = 0; i < (moduleDecl.mod).importedModules.length; i++) {
                            importStatement = (moduleDecl.mod).importedModules[i];
                            if(importStatement.id.sym && !(importStatement.id.sym).onlyReferencedAsTypeRef) {
                                if(i <= (moduleDecl.mod).importedModules.length - 1) {
                                    dependencyList += ", ";
                                    importList += ", ";
                                }
                                importList += "__" + importStatement.id.actualText + "__";
                                dependencyList += importStatement.firstAliasedModToString();
                            }
                        }
                        for(var i = 0; i < moduleDecl.amdDependencies.length; i++) {
                            dependencyList += ", \"" + moduleDecl.amdDependencies[i] + "\"";
                        }
                        dependencyList += "]";
                        this.writeLineToOutput("define(" + dependencyList + "," + " function(" + importList + ") {");
                    } else {
                    }
                } else {
                    if(!isExported) {
                        this.recordSourceMappingStart(moduleDecl);
                        this.writeToOutput("var ");
                        this.recordSourceMappingStart(moduleDecl.name);
                        this.writeToOutput(this.moduleName);
                        this.recordSourceMappingEnd(moduleDecl.name);
                        this.writeLineToOutput(";");
                        this.recordSourceMappingEnd(moduleDecl);
                        this.emitIndent();
                    }
                    this.writeToOutput("(");
                    this.recordSourceMappingStart(moduleDecl);
                    this.writeToOutput("function (");
                    this.recordSourceMappingStart(moduleDecl.name);
                    this.writeToOutput(this.moduleName);
                    this.recordSourceMappingEnd(moduleDecl.name);
                    this.writeLineToOutput(") {");
                }
                if(!isWholeFile) {
                    this.recordSourceMappingNameStart(this.moduleName);
                }
                if(!isDynamicMod || TypeScript.moduleGenTarget == TypeScript.ModuleGenTarget.Asynchronous) {
                    this.indenter.increaseIndent();
                }
                if(moduleDecl.modFlags & TypeScript.ModuleFlags.MustCaptureThis) {
                    this.writeCaptureThisStatement(moduleDecl);
                }
                this.emitJavascriptList(moduleDecl.members, null, TypeScript.TokenID.Semicolon, true, false, false);
                if(!isDynamicMod || TypeScript.moduleGenTarget == TypeScript.ModuleGenTarget.Asynchronous) {
                    this.indenter.decreaseIndent();
                }
                this.emitIndent();
                if(isDynamicMod) {
                    if(TypeScript.moduleGenTarget == TypeScript.ModuleGenTarget.Asynchronous) {
                        this.writeLineToOutput("})");
                    } else {
                    }
                    if(!isWholeFile) {
                        this.recordSourceMappingNameEnd();
                    }
                    this.recordSourceMappingEnd(moduleDecl);
                    if(this.outfile != prevOutFile) {
                        this.Close();
                        if(prevSourceMapper != null) {
                            this.allSourceMappers = prevAllSourceMappers;
                            this.sourceMapper = prevSourceMapper;
                            this.emitState.column = prevColumn;
                            this.emitState.line = prevLine;
                        }
                        this.outfile = prevOutFile;
                        this.emittingFileName = prevOutFileName;
                    }
                } else {
                    var containingMod = null;
                    if(moduleDecl.type && moduleDecl.type.symbol.container && moduleDecl.type.symbol.container.declAST) {
                        containingMod = moduleDecl.type.symbol.container.declAST;
                    }
                    var parentIsDynamic = containingMod && TypeScript.hasFlag(containingMod.modFlags, TypeScript.ModuleFlags.IsDynamic);
                    this.recordSourceMappingStart(moduleDecl.endingToken);
                    if(temp == EmitContainer.Prog && isExported) {
                        this.writeToOutput("}");
                        if(!isWholeFile) {
                            this.recordSourceMappingNameEnd();
                        }
                        this.recordSourceMappingEnd(moduleDecl.endingToken);
                        this.writeLineToOutput(")(this." + this.moduleName + " || (this." + this.moduleName + " = {}));");
                    } else {
                        if(isExported || temp == EmitContainer.Prog) {
                            var dotMod = svModuleName != "" ? (parentIsDynamic ? "exports" : svModuleName) + "." : svModuleName;
                            this.writeToOutput("}");
                            if(!isWholeFile) {
                                this.recordSourceMappingNameEnd();
                            }
                            this.recordSourceMappingEnd(moduleDecl.endingToken);
                            this.writeLineToOutput(")(" + dotMod + this.moduleName + " || (" + dotMod + this.moduleName + " = {}));");
                        } else {
                            if(!isExported && temp != EmitContainer.Prog) {
                                this.writeToOutput("}");
                                if(!isWholeFile) {
                                    this.recordSourceMappingNameEnd();
                                }
                                this.recordSourceMappingEnd(moduleDecl.endingToken);
                                this.writeLineToOutput(")(" + this.moduleName + " || (" + this.moduleName + " = {}));");
                            } else {
                                this.writeToOutput("}");
                                if(!isWholeFile) {
                                    this.recordSourceMappingNameEnd();
                                }
                                this.recordSourceMappingEnd(moduleDecl.endingToken);
                                this.writeLineToOutput(")();");
                            }
                        }
                    }
                    this.recordSourceMappingEnd(moduleDecl);
                    if(temp != EmitContainer.Prog && isExported) {
                        this.emitIndent();
                        this.recordSourceMappingStart(moduleDecl);
                        if(parentIsDynamic) {
                            this.writeLineToOutput("var " + this.moduleName + " = exports." + this.moduleName + ";");
                        } else {
                            this.writeLineToOutput("var " + this.moduleName + " = " + svModuleName + "." + this.moduleName + ";");
                        }
                        this.recordSourceMappingEnd(moduleDecl);
                    }
                }
                this.setContainer(temp);
                this.moduleName = svModuleName;
                this.moduleDeclList.length--;
            }
        };
        Emitter.prototype.emitIndex = function (operand1, operand2) {
            var temp = this.setInObjectLiteral(false);
            this.emitJavascript(operand1, TypeScript.TokenID.Tilde, false);
            this.writeToOutput("[");
            this.emitJavascriptList(operand2, ", ", TypeScript.TokenID.Comma, false, false, false);
            this.writeToOutput("]");
            this.setInObjectLiteral(temp);
        };
        Emitter.prototype.emitStringLiteral = function (text) {
            this.writeToOutput(text);
        };
        Emitter.prototype.emitJavascriptFunction = function (funcDecl) {
            if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Signature) || funcDecl.isOverload) {
                return;
            }
            var temp;
            var tempFnc = this.thisFnc;
            this.thisFnc = funcDecl;
            if(funcDecl.isConstructor) {
                temp = this.setContainer(EmitContainer.Constructor);
            } else {
                temp = this.setContainer(EmitContainer.Function);
            }
            var bases = null;
            var hasSelfRef = false;
            var funcName = funcDecl.getNameText();
            if((this.emitState.inObjectLiteral || !funcDecl.isAccessor()) && ((temp != EmitContainer.Constructor) || ((funcDecl.fncFlags & TypeScript.FncFlags.Method) == TypeScript.FncFlags.None))) {
                var tempLit = this.setInObjectLiteral(false);
                if(this.thisClassNode) {
                    bases = this.thisClassNode.extendsList;
                }
                hasSelfRef = Emitter.shouldCaptureThis(funcDecl);
                this.recordSourceMappingStart(funcDecl);
                if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Exported | TypeScript.FncFlags.ClassPropertyMethodExported) && funcDecl.type.symbol.container == this.checker.gloMod && !funcDecl.isConstructor) {
                    this.writeToOutput("this." + funcName + " = ");
                    this.emitInnerFunction(funcDecl, false, false, bases, hasSelfRef, this.thisClassNode);
                } else {
                    this.emitInnerFunction(funcDecl, (funcDecl.name && !funcDecl.name.isMissing()), false, bases, hasSelfRef, this.thisClassNode);
                }
                this.setInObjectLiteral(tempLit);
            }
            this.setContainer(temp);
            this.thisFnc = tempFnc;
            if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Definition)) {
                if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Static)) {
                    if(this.thisClassNode) {
                        if(funcDecl.isAccessor()) {
                            this.emitPropertyAccessor(funcDecl, this.thisClassNode.name.actualText, false);
                        } else {
                            this.emitIndent();
                            this.recordSourceMappingStart(funcDecl);
                            this.writeLineToOutput(this.thisClassNode.name.actualText + "." + funcName + " = " + funcName + ";");
                            this.recordSourceMappingEnd(funcDecl);
                        }
                    }
                } else {
                    if((this.emitState.container == EmitContainer.Module || this.emitState.container == EmitContainer.DynamicModule) && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Exported | TypeScript.FncFlags.ClassPropertyMethodExported)) {
                        this.emitIndent();
                        var modName = this.emitState.container == EmitContainer.Module ? this.moduleName : "exports";
                        this.recordSourceMappingStart(funcDecl);
                        this.writeLineToOutput(modName + "." + funcName + " = " + funcName + ";");
                        this.recordSourceMappingEnd(funcDecl);
                    }
                }
            }
        };
        Emitter.prototype.emitAmbientVarDecl = function (varDecl) {
            if(varDecl.init) {
                this.emitParensAndCommentsInPlace(varDecl, true);
                this.recordSourceMappingStart(varDecl);
                this.recordSourceMappingStart(varDecl.id);
                this.writeToOutput(varDecl.id.actualText);
                this.recordSourceMappingEnd(varDecl.id);
                this.writeToOutput(" = ");
                this.emitJavascript(varDecl.init, TypeScript.TokenID.Comma, false);
                this.recordSourceMappingEnd(varDecl);
                this.writeToOutput(";");
                this.emitParensAndCommentsInPlace(varDecl, false);
            }
        };
        Emitter.prototype.varListCount = function () {
            return this.varListCountStack[this.varListCountStack.length - 1];
        };
        Emitter.prototype.emitVarDeclVar = function () {
            if(this.varListCount() >= 0) {
                this.writeToOutput("var ");
                this.setInVarBlock(-this.varListCount());
            }
            return true;
        };
        Emitter.prototype.onEmitVar = function () {
            if(this.varListCount() > 0) {
                this.setInVarBlock(this.varListCount() - 1);
            } else {
                if(this.varListCount() < 0) {
                    this.setInVarBlock(this.varListCount() + 1);
                }
            }
        };
        Emitter.prototype.emitJavascriptVarDecl = function (varDecl, tokenId) {
            if((varDecl.varFlags & TypeScript.VarFlags.Ambient) == TypeScript.VarFlags.Ambient) {
                this.emitAmbientVarDecl(varDecl);
                this.onEmitVar();
            } else {
                var sym = varDecl.sym;
                var hasInitializer = (varDecl.init != null);
                this.emitParensAndCommentsInPlace(varDecl, true);
                this.recordSourceMappingStart(varDecl);
                if(sym && sym.isMember() && sym.container && (sym.container.kind() == TypeScript.SymbolKind.Type)) {
                    var type = (sym.container).type;
                    if(type.isClass() && (!TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.ModuleMember))) {
                        if(this.emitState.container != EmitContainer.Args) {
                            if(TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Static)) {
                                this.writeToOutput(sym.container.name + ".");
                            } else {
                                this.writeToOutput("this.");
                            }
                        }
                    } else {
                        if(type.hasImplementation()) {
                            if(!TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Exported) && (sym.container == this.checker.gloMod || !TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Property))) {
                                this.emitVarDeclVar();
                            } else {
                                if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.LocalStatic)) {
                                    this.writeToOutput(".");
                                } else {
                                    if(this.emitState.container == EmitContainer.DynamicModule) {
                                        this.writeToOutput("exports.");
                                    } else {
                                        this.writeToOutput(this.moduleName + ".");
                                    }
                                }
                            }
                        } else {
                            if(tokenId != TypeScript.TokenID.OpenParen) {
                                if(TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Exported) && sym.container == this.checker.gloMod) {
                                    this.writeToOutput("this.");
                                } else {
                                    this.emitVarDeclVar();
                                }
                            }
                        }
                    }
                } else {
                    if(tokenId != TypeScript.TokenID.OpenParen) {
                        this.emitVarDeclVar();
                    }
                }
                this.recordSourceMappingStart(varDecl.id);
                this.writeToOutput(varDecl.id.actualText);
                this.recordSourceMappingEnd(varDecl.id);
                if(hasInitializer) {
                    this.writeToOutputTrimmable(" = ");
                    this.varListCountStack.push(0);
                    this.emitJavascript(varDecl.init, TypeScript.TokenID.Comma, false);
                    this.varListCountStack.pop();
                }
                this.onEmitVar();
                if((tokenId != TypeScript.TokenID.OpenParen)) {
                    if(this.varListCount() < 0) {
                        this.writeToOutput(", ");
                    } else {
                        if(tokenId != TypeScript.TokenID.For) {
                            this.writeToOutputTrimmable(";");
                        }
                    }
                }
                this.recordSourceMappingEnd(varDecl);
                this.emitParensAndCommentsInPlace(varDecl, false);
            }
        };
        Emitter.prototype.declEnclosed = function (moduleDecl) {
            if(moduleDecl == null) {
                return true;
            }
            for(var i = 0, len = this.moduleDeclList.length; i < len; i++) {
                if(this.moduleDeclList[i] == moduleDecl) {
                    return true;
                }
            }
            return false;
        };
        Emitter.prototype.emitJavascriptName = function (name, addThis) {
            var sym = name.sym;
            this.emitParensAndCommentsInPlace(name, true);
            this.recordSourceMappingStart(name);
            if(!name.isMissing()) {
                if(addThis && (this.emitState.container != EmitContainer.Args) && sym) {
                    if(sym.container && (sym.container.name != TypeScript.globalId)) {
                        if(TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Static) && (TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Property))) {
                            if(sym.declModule && TypeScript.hasFlag(sym.declModule.modFlags, TypeScript.ModuleFlags.IsDynamic)) {
                                this.writeToOutput("exports.");
                            } else {
                                this.writeToOutput(sym.container.name + ".");
                            }
                        } else {
                            if(sym.kind() == TypeScript.SymbolKind.Field) {
                                var fieldSym = sym;
                                if(TypeScript.hasFlag(fieldSym.flags, TypeScript.SymbolFlags.ModuleMember)) {
                                    if((sym.container != this.checker.gloMod) && ((TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Property)) || TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Exported))) {
                                        if(TypeScript.hasFlag(sym.declModule.modFlags, TypeScript.ModuleFlags.IsDynamic)) {
                                            this.writeToOutput("exports.");
                                        } else {
                                            this.writeToOutput(sym.container.name + ".");
                                        }
                                    }
                                } else {
                                    if(sym.isInstanceProperty()) {
                                        this.emitThis();
                                        this.writeToOutput(".");
                                    }
                                }
                            } else {
                                if(sym.kind() == TypeScript.SymbolKind.Type) {
                                    if(sym.isInstanceProperty()) {
                                        var typeSym = sym;
                                        var type = typeSym.type;
                                        if(type.call && !TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.ModuleMember)) {
                                            this.emitThis();
                                            this.writeToOutput(".");
                                        }
                                    } else {
                                        if((sym.unitIndex != this.checker.locationInfo.unitIndex) || (!this.declEnclosed(sym.declModule))) {
                                            this.writeToOutput(sym.container.name + ".");
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        if(sym.container == this.checker.gloMod && TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Exported) && !TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Ambient) && !((sym.isType() || sym.isMember()) && sym.declModule && TypeScript.hasFlag(sym.declModule.modFlags, TypeScript.ModuleFlags.Ambient)) && this.emitState.container == EmitContainer.Prog && sym.declAST.nodeType != TypeScript.NodeType.FuncDecl) {
                            this.writeToOutput("this.");
                        }
                    }
                }
                if(sym && sym.declAST && sym.declAST.nodeType == TypeScript.NodeType.ModuleDeclaration && (TypeScript.hasFlag((sym.declAST).modFlags, TypeScript.ModuleFlags.IsDynamic))) {
                    var moduleDecl = sym.declAST;
                    if(TypeScript.moduleGenTarget == TypeScript.ModuleGenTarget.Asynchronous) {
                        this.writeLineToOutput("__" + this.modAliasId + "__;");
                    } else {
                        var modPath = name.actualText;
                        var isAmbient = moduleDecl.mod.symbol.declAST && TypeScript.hasFlag((moduleDecl.mod.symbol.declAST).modFlags, TypeScript.ModuleFlags.Ambient);
                        modPath = isAmbient ? modPath : this.firstModAlias ? this.firstModAlias : TypeScript.quoteBaseName(modPath);
                        modPath = isAmbient ? modPath : (!TypeScript.isRelative(TypeScript.stripQuotes(modPath)) ? TypeScript.quoteStr("./" + TypeScript.stripQuotes(modPath)) : modPath);
                        this.writeToOutput("require(" + modPath + ")");
                    }
                } else {
                    this.writeToOutput(name.actualText);
                }
            }
            this.recordSourceMappingEnd(name);
            this.emitParensAndCommentsInPlace(name, false);
        };
        Emitter.prototype.emitJavascriptStatements = function (stmts, emitEmptyBod) {
            if(stmts) {
                if(stmts.nodeType != TypeScript.NodeType.Block) {
                    var hasContents = (stmts && (stmts.nodeType != TypeScript.NodeType.List || ((stmts).members.length > 0)));
                    if(emitEmptyBod || hasContents) {
                        var hasOnlyBlockStatement = ((stmts.nodeType == TypeScript.NodeType.Block) || ((stmts.nodeType == TypeScript.NodeType.List) && ((stmts).members.length == 1) && ((stmts).members[0].nodeType == TypeScript.NodeType.Block)));
                        this.recordSourceMappingStart(stmts);
                        if(!hasOnlyBlockStatement) {
                            this.writeLineToOutput(" {");
                            this.indenter.increaseIndent();
                        }
                        this.emitJavascriptList(stmts, null, TypeScript.TokenID.Semicolon, true, false, false);
                        if(!hasOnlyBlockStatement) {
                            this.writeLineToOutput("");
                            this.indenter.decreaseIndent();
                            this.emitIndent();
                            this.writeToOutput("}");
                        }
                        this.recordSourceMappingEnd(stmts);
                    }
                } else {
                    this.emitJavascript(stmts, TypeScript.TokenID.Semicolon, true);
                }
            } else {
                if(emitEmptyBod) {
                    this.writeToOutput("{ }");
                }
            }
        };
        Emitter.prototype.emitBareJavascriptStatements = function (stmts, emitClassPropertiesAfterSuperCall) {
            if (typeof emitClassPropertiesAfterSuperCall === "undefined") { emitClassPropertiesAfterSuperCall = false; }
            if(stmts.nodeType != TypeScript.NodeType.Block) {
                if(stmts.nodeType == TypeScript.NodeType.List) {
                    var stmtList = stmts;
                    if((stmtList.members.length == 2) && (stmtList.members[0].nodeType == TypeScript.NodeType.Block) && (stmtList.members[1].nodeType == TypeScript.NodeType.EndCode)) {
                        this.emitJavascript(stmtList.members[0], TypeScript.TokenID.Semicolon, true);
                        this.writeLineToOutput("");
                    } else {
                        this.emitJavascriptList(stmts, null, TypeScript.TokenID.Semicolon, true, false, emitClassPropertiesAfterSuperCall);
                    }
                } else {
                    this.emitJavascript(stmts, TypeScript.TokenID.Semicolon, true);
                }
            } else {
                this.emitJavascript(stmts, TypeScript.TokenID.Semicolon, true);
            }
        };
        Emitter.prototype.recordSourceMappingNameStart = function (name) {
            if(this.sourceMapper) {
                var finalName = name;
                if(!name) {
                    finalName = "";
                } else {
                    if(this.sourceMapper.currentNameIndex.length > 0) {
                        finalName = this.sourceMapper.names[this.sourceMapper.currentNameIndex.length - 1] + "." + name;
                    }
                }
                this.sourceMapper.names.push(finalName);
                this.sourceMapper.currentNameIndex.push(this.sourceMapper.names.length - 1);
            }
        };
        Emitter.prototype.recordSourceMappingNameEnd = function () {
            if(this.sourceMapper) {
                this.sourceMapper.currentNameIndex.pop();
            }
        };
        Emitter.prototype.recordSourceMappingStart = function (ast) {
            if(this.sourceMapper && TypeScript.isValidAstNode(ast)) {
                var lineCol = {
                    line: -1,
                    col: -1
                };
                var sourceMapping = new TypeScript.SourceMapping();
                sourceMapping.start.emittedColumn = this.emitState.column;
                sourceMapping.start.emittedLine = this.emitState.line;
                TypeScript.getSourceLineColFromMap(lineCol, ast.minChar, this.checker.locationInfo.lineMap);
                sourceMapping.start.sourceColumn = lineCol.col;
                sourceMapping.start.sourceLine = lineCol.line;
                TypeScript.getSourceLineColFromMap(lineCol, ast.limChar, this.checker.locationInfo.lineMap);
                sourceMapping.end.sourceColumn = lineCol.col;
                sourceMapping.end.sourceLine = lineCol.line;
                if(this.sourceMapper.currentNameIndex.length > 0) {
                    sourceMapping.nameIndex = this.sourceMapper.currentNameIndex[this.sourceMapper.currentNameIndex.length - 1];
                }
                var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];
                siblings.push(sourceMapping);
                this.sourceMapper.currentMappings.push(sourceMapping.childMappings);
            }
        };
        Emitter.prototype.recordSourceMappingEnd = function (ast) {
            if(this.sourceMapper && TypeScript.isValidAstNode(ast)) {
                this.sourceMapper.currentMappings.pop();
                var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];
                var sourceMapping = siblings[siblings.length - 1];
                sourceMapping.end.emittedColumn = this.emitState.column;
                sourceMapping.end.emittedLine = this.emitState.line;
            }
        };
        Emitter.prototype.Close = function () {
            if(this.sourceMapper != null) {
                TypeScript.SourceMapper.EmitSourceMapping(this.allSourceMappers);
            }
            try  {
                this.outfile.Close();
            } catch (ex) {
                this.errorReporter.emitterError(null, ex.message);
            }
        };
        Emitter.prototype.emitJavascriptList = function (ast, delimiter, tokenId, startLine, onlyStatics, emitClassPropertiesAfterSuperCall, emitPrologue, requiresExtendsBlock) {
            if (typeof emitClassPropertiesAfterSuperCall === "undefined") { emitClassPropertiesAfterSuperCall = false; }
            if (typeof emitPrologue === "undefined") { emitPrologue = false; }
            if(ast == null) {
                return;
            } else {
                if(ast.nodeType != TypeScript.NodeType.List) {
                    this.emitPrologue(emitPrologue);
                    this.emitJavascript(ast, tokenId, startLine);
                } else {
                    var list = ast;
                    if(list.members.length == 0) {
                        return;
                    }
                    this.emitParensAndCommentsInPlace(ast, true);
                    var len = list.members.length;
                    for(var i = 0; i < len; i++) {
                        if(emitPrologue) {
                            if(i == 1 || !TypeScript.hasFlag(list.flags, TypeScript.ASTFlags.StrictMode)) {
                                this.emitPrologue(requiresExtendsBlock);
                                emitPrologue = false;
                            }
                        }
                        if(i == 1 && emitClassPropertiesAfterSuperCall) {
                            var constructorDecl = (this.thisClassNode).constructorDecl;
                            if(constructorDecl && constructorDecl.arguments) {
                                var argsLen = constructorDecl.arguments.members.length;
                                for(var iArg = 0; iArg < argsLen; iArg++) {
                                    var arg = constructorDecl.arguments.members[iArg];
                                    if((arg.varFlags & TypeScript.VarFlags.Property) != TypeScript.VarFlags.None) {
                                        this.emitIndent();
                                        this.recordSourceMappingStart(arg);
                                        this.recordSourceMappingStart(arg.id);
                                        this.writeToOutput("this." + arg.id.actualText);
                                        this.recordSourceMappingEnd(arg.id);
                                        this.writeToOutput(" = ");
                                        this.recordSourceMappingStart(arg.id);
                                        this.writeToOutput(arg.id.actualText);
                                        this.recordSourceMappingEnd(arg.id);
                                        this.writeLineToOutput(";");
                                        this.recordSourceMappingEnd(arg);
                                    }
                                }
                            }
                            var nProps = (this.thisClassNode.members).members.length;
                            for(var iMember = 0; iMember < nProps; iMember++) {
                                if((this.thisClassNode.members).members[iMember].nodeType == TypeScript.NodeType.VarDecl) {
                                    var varDecl = (this.thisClassNode.members).members[iMember];
                                    if(!TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Static) && varDecl.init) {
                                        this.emitIndent();
                                        this.emitJavascriptVarDecl(varDecl, TypeScript.TokenID.Tilde);
                                        this.writeLineToOutput("");
                                    }
                                }
                            }
                        }
                        var emitNode = list.members[i];
                        var isStaticDecl = (emitNode.nodeType == TypeScript.NodeType.FuncDecl && TypeScript.hasFlag((emitNode).fncFlags, TypeScript.FncFlags.Static)) || (emitNode.nodeType == TypeScript.NodeType.VarDecl && TypeScript.hasFlag((emitNode).varFlags, TypeScript.VarFlags.Static));
                        if(onlyStatics ? !isStaticDecl : isStaticDecl) {
                            continue;
                        }
                        this.emitJavascript(emitNode, tokenId, startLine);
                        if(delimiter && (i < (len - 1))) {
                            if(startLine) {
                                this.writeLineToOutput(delimiter);
                            } else {
                                this.writeToOutput(delimiter);
                            }
                        } else {
                            if(startLine && (emitNode.nodeType != TypeScript.NodeType.ModuleDeclaration) && (emitNode.nodeType != TypeScript.NodeType.InterfaceDeclaration) && (!((emitNode.nodeType == TypeScript.NodeType.VarDecl) && ((((emitNode).varFlags) & TypeScript.VarFlags.Ambient) == TypeScript.VarFlags.Ambient) && (((emitNode).init) == null)) && this.varListCount() >= 0) && (emitNode.nodeType != TypeScript.NodeType.Block || (emitNode).isStatementBlock) && (emitNode.nodeType != TypeScript.NodeType.EndCode) && (emitNode.nodeType != TypeScript.NodeType.FuncDecl)) {
                                this.writeLineToOutput("");
                            }
                        }
                    }
                    this.emitParensAndCommentsInPlace(ast, false);
                }
            }
        };
        Emitter.prototype.emitJavascript = function (ast, tokenId, startLine) {
            if(ast == null) {
                return;
            }
            if(startLine && (this.indenter.indentAmt > 0) && (ast.nodeType != TypeScript.NodeType.List) && (ast.nodeType != TypeScript.NodeType.Block)) {
                if((ast.nodeType != TypeScript.NodeType.InterfaceDeclaration) && (!((ast.nodeType == TypeScript.NodeType.VarDecl) && ((((ast).varFlags) & TypeScript.VarFlags.Ambient) == TypeScript.VarFlags.Ambient) && (((ast).init) == null)) && this.varListCount() >= 0) && (ast.nodeType != TypeScript.NodeType.EndCode) && ((ast.nodeType != TypeScript.NodeType.FuncDecl) || (this.emitState.container != EmitContainer.Constructor))) {
                    this.emitIndent();
                }
            }
            ast.emit(this, tokenId, startLine);
            if((tokenId == TypeScript.TokenID.Semicolon) && (ast.nodeType < TypeScript.NodeType.GeneralNode)) {
                this.writeToOutput(";");
            }
        };
        Emitter.prototype.emitPropertyAccessor = function (funcDecl, className, isProto) {
            if(!(funcDecl.accessorSymbol).hasBeenEmitted) {
                var accessorSymbol = funcDecl.accessorSymbol;
                this.emitIndent();
                this.recordSourceMappingStart(funcDecl);
                this.writeLineToOutput("Object.defineProperty(" + className + (isProto ? ".prototype, \"" : ", \"") + funcDecl.name.actualText + "\"" + ", {");
                this.indenter.increaseIndent();
                if(accessorSymbol.getter) {
                    var getter = accessorSymbol.getter.declAST;
                    this.emitIndent();
                    this.recordSourceMappingStart(getter);
                    this.writeToOutput("get: ");
                    this.emitInnerFunction(getter, false, isProto, null, Emitter.shouldCaptureThis(getter), null);
                    this.writeLineToOutput(",");
                }
                if(accessorSymbol.setter) {
                    var setter = accessorSymbol.setter.declAST;
                    this.emitIndent();
                    this.recordSourceMappingStart(setter);
                    this.writeToOutput("set: ");
                    this.emitInnerFunction(setter, false, isProto, null, Emitter.shouldCaptureThis(setter), null);
                    this.writeLineToOutput(",");
                }
                this.emitIndent();
                this.writeLineToOutput("enumerable: true,");
                this.emitIndent();
                this.writeLineToOutput("configurable: true");
                this.indenter.decreaseIndent();
                this.emitIndent();
                this.writeLineToOutput("});");
                this.recordSourceMappingEnd(funcDecl);
                accessorSymbol.hasBeenEmitted = true;
            }
        };
        Emitter.prototype.emitPrototypeMember = function (member, className) {
            if(member.nodeType == TypeScript.NodeType.FuncDecl) {
                var funcDecl = member;
                if(funcDecl.isAccessor()) {
                    this.emitPropertyAccessor(funcDecl, className, true);
                } else {
                    this.emitIndent();
                    this.recordSourceMappingStart(funcDecl);
                    this.writeToOutput(className + ".prototype." + funcDecl.getNameText() + " = ");
                    this.emitInnerFunction(funcDecl, false, true, null, Emitter.shouldCaptureThis(funcDecl), null);
                    this.writeLineToOutput(";");
                }
            } else {
                if(member.nodeType == TypeScript.NodeType.VarDecl) {
                    var varDecl = member;
                    if(varDecl.init) {
                        this.emitIndent();
                        this.recordSourceMappingStart(varDecl);
                        this.recordSourceMappingStart(varDecl.id);
                        this.writeToOutput(className + ".prototype." + varDecl.id.actualText);
                        this.recordSourceMappingEnd(varDecl.id);
                        this.writeToOutput(" = ");
                        this.emitJavascript(varDecl.init, TypeScript.TokenID.Equals, false);
                        this.recordSourceMappingEnd(varDecl);
                        this.writeLineToOutput(";");
                    }
                }
            }
        };
        Emitter.prototype.emitAddBaseMethods = function (className, base, classDecl) {
            if(base.members) {
                var baseSymbol = base.symbol;
                var baseName = baseSymbol.name;
                if(baseSymbol.declModule != classDecl.type.symbol.declModule) {
                    baseName = baseSymbol.fullName();
                }
                base.members.allMembers.map(function (key, s, c) {
                    var sym = s;
                    if((sym.kind() == TypeScript.SymbolKind.Type) && (sym).type.call) {
                        this.recordSourceMappingStart(sym.declAST);
                        this.writeLineToOutput(className + ".prototype." + sym.name + " = " + baseName + ".prototype." + sym.name + ";");
                        this.recordSourceMappingEnd(sym.declAST);
                    }
                }, null);
            }
            if(base.extendsList) {
                for(var i = 0, len = base.extendsList.length; i < len; i++) {
                    this.emitAddBaseMethods(className, base.extendsList[i], classDecl);
                }
            }
        };
        Emitter.prototype.emitJavascriptClass = function (classDecl) {
            if(!TypeScript.hasFlag(classDecl.varFlags, TypeScript.VarFlags.Ambient)) {
                var svClassNode = this.thisClassNode;
                var i = 0;
                this.thisClassNode = classDecl;
                var className = classDecl.name.actualText;
                this.emitParensAndCommentsInPlace(classDecl, true);
                var temp = this.setContainer(EmitContainer.Class);
                this.recordSourceMappingStart(classDecl);
                if(TypeScript.hasFlag(classDecl.varFlags, TypeScript.VarFlags.Exported) && classDecl.type.symbol.container == this.checker.gloMod) {
                    this.writeToOutput("this." + className);
                } else {
                    this.writeToOutput("var " + className);
                }
                var hasBaseClass = classDecl.extendsList && classDecl.extendsList.members.length;
                var baseNameDecl = null;
                var baseName = null;
                if(hasBaseClass) {
                    this.writeLineToOutput(" = (function (_super) {");
                } else {
                    this.writeLineToOutput(" = (function () {");
                }
                this.recordSourceMappingNameStart(className);
                this.indenter.increaseIndent();
                if(hasBaseClass) {
                    baseNameDecl = classDecl.extendsList.members[0];
                    baseName = baseNameDecl.nodeType == TypeScript.NodeType.Call ? (baseNameDecl).target : baseNameDecl;
                    this.emitIndent();
                    this.writeLineToOutput("__extends(" + className + ", _super);");
                }
                this.emitIndent();
                var constrDecl = classDecl.constructorDecl;
                if(constrDecl) {
                    this.emitJavascript(classDecl.constructorDecl, TypeScript.TokenID.OpenParen, false);
                } else {
                    var wroteProps = 0;
                    this.recordSourceMappingStart(classDecl);
                    this.indenter.increaseIndent();
                    this.writeToOutput("function " + classDecl.name.actualText + "() {");
                    this.recordSourceMappingNameStart("constructor");
                    if(hasBaseClass) {
                        this.writeLineToOutput("");
                        this.emitIndent();
                        this.writeLineToOutput("_super.apply(this, arguments);");
                        wroteProps++;
                    }
                    if(classDecl.varFlags & TypeScript.VarFlags.MustCaptureThis) {
                        this.writeCaptureThisStatement(classDecl);
                    }
                    var members = (this.thisClassNode.members).members;
                    for(var i = 0; i < members.length; i++) {
                        if(members[i].nodeType == TypeScript.NodeType.VarDecl) {
                            var varDecl = members[i];
                            if(!TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Static) && varDecl.init) {
                                this.writeLineToOutput("");
                                this.emitIndent();
                                this.emitJavascriptVarDecl(varDecl, TypeScript.TokenID.Tilde);
                                wroteProps++;
                            }
                        }
                    }
                    if(wroteProps) {
                        this.writeLineToOutput("");
                        this.indenter.decreaseIndent();
                        this.emitIndent();
                        this.writeLineToOutput("}");
                    } else {
                        this.writeLineToOutput(" }");
                        this.indenter.decreaseIndent();
                    }
                    this.recordSourceMappingNameEnd();
                    this.recordSourceMappingEnd(classDecl);
                }
                var membersLen = classDecl.members.members.length;
                for(var j = 0; j < membersLen; j++) {
                    var memberDecl = classDecl.members.members[j];
                    if(memberDecl.nodeType == TypeScript.NodeType.FuncDecl) {
                        var fn = memberDecl;
                        if(TypeScript.hasFlag(fn.fncFlags, TypeScript.FncFlags.Method) && !fn.isSignature()) {
                            if(!TypeScript.hasFlag(fn.fncFlags, TypeScript.FncFlags.Static)) {
                                this.emitPrototypeMember(fn, className);
                            } else {
                                if(fn.isAccessor()) {
                                    this.emitPropertyAccessor(fn, this.thisClassNode.name.actualText, false);
                                } else {
                                    this.emitIndent();
                                    this.recordSourceMappingStart(fn);
                                    this.writeToOutput(classDecl.name.actualText + "." + fn.name.actualText + " = ");
                                    this.emitInnerFunction(fn, (fn.name && !fn.name.isMissing()), true, null, Emitter.shouldCaptureThis(fn), null);
                                    this.writeLineToOutput(";");
                                }
                            }
                        }
                    } else {
                        if(memberDecl.nodeType == TypeScript.NodeType.VarDecl) {
                            var varDecl = memberDecl;
                            if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Static)) {
                                if(varDecl.init) {
                                    this.emitIndent();
                                    this.recordSourceMappingStart(varDecl);
                                    this.writeToOutput(classDecl.name.actualText + "." + varDecl.id.actualText + " = ");
                                    this.emitJavascript(varDecl.init, TypeScript.TokenID.Equals, false);
                                    this.writeLineToOutput(";");
                                    this.recordSourceMappingEnd(varDecl);
                                }
                            }
                        } else {
                            throw Error("We want to catch this");
                        }
                    }
                }
                this.emitIndent();
                this.recordSourceMappingStart(classDecl.endingToken);
                this.writeLineToOutput("return " + className + ";");
                this.recordSourceMappingEnd(classDecl.endingToken);
                this.indenter.decreaseIndent();
                this.emitIndent();
                this.recordSourceMappingStart(classDecl.endingToken);
                this.writeToOutput("}");
                this.recordSourceMappingNameEnd();
                this.recordSourceMappingEnd(classDecl.endingToken);
                this.recordSourceMappingStart(classDecl);
                this.writeToOutput(")(");
                if(hasBaseClass) {
                    this.emitJavascript(baseName, TypeScript.TokenID.Tilde, false);
                }
                this.writeToOutput(");");
                this.recordSourceMappingEnd(classDecl);
                if((temp == EmitContainer.Module || temp == EmitContainer.DynamicModule) && TypeScript.hasFlag(classDecl.varFlags, TypeScript.VarFlags.Exported)) {
                    this.writeLineToOutput("");
                    this.emitIndent();
                    var modName = temp == EmitContainer.Module ? this.moduleName : "exports";
                    this.recordSourceMappingStart(classDecl);
                    this.writeToOutput(modName + "." + className + " = " + className + ";");
                    this.recordSourceMappingEnd(classDecl);
                }
                this.emitIndent();
                this.recordSourceMappingEnd(classDecl);
                this.emitParensAndCommentsInPlace(classDecl, false);
                this.setContainer(temp);
                this.thisClassNode = svClassNode;
            }
        };
        Emitter.prototype.emitPrologue = function (reqInherits) {
            if(!this.prologueEmitted) {
                if(reqInherits) {
                    this.prologueEmitted = true;
                    this.writeLineToOutput("var __extends = this.__extends || function (d, b) {");
                    this.writeLineToOutput("    function __() { this.constructor = d; }");
                    this.writeLineToOutput("    __.prototype = b.prototype;");
                    this.writeLineToOutput("    d.prototype = new __();");
                    this.writeLineToOutput("};");
                }
                if(this.checker.mustCaptureGlobalThis) {
                    this.prologueEmitted = true;
                    this.writeLineToOutput(this.captureThisStmtString);
                }
            }
        };
        Emitter.prototype.emitSuperReference = function () {
            this.writeToOutput("_super.prototype");
        };
        Emitter.prototype.emitSuperCall = function (callEx) {
            if(callEx.target.nodeType == TypeScript.NodeType.Dot) {
                var dotNode = callEx.target;
                if(dotNode.operand1.nodeType == TypeScript.NodeType.Super) {
                    this.emitJavascript(dotNode, TypeScript.TokenID.OpenParen, false);
                    this.writeToOutput(".call(");
                    this.emitThis();
                    if(callEx.arguments && callEx.arguments.members.length > 0) {
                        this.writeToOutput(", ");
                        this.emitJavascriptList(callEx.arguments, ", ", TypeScript.TokenID.Comma, false, false, false);
                    }
                    this.writeToOutput(")");
                    return true;
                }
            }
            return false;
        };
        Emitter.prototype.emitThis = function () {
            if(this.thisFnc && !this.thisFnc.isMethod() && (!this.thisFnc.isConstructor)) {
                this.writeToOutput("_this");
            } else {
                this.writeToOutput("this");
            }
        };
        Emitter.shouldCaptureThis = function shouldCaptureThis(func) {
            return func.hasSelfReference() || func.hasSuperReferenceInFatArrowFunction();
        }
        Emitter.prototype.createFile = function (fileName, useUTF8) {
            try  {
                return this.emitOptions.ioHost.createFile(fileName, useUTF8);
            } catch (ex) {
                this.errorReporter.emitterError(null, ex.message);
            }
        };
        return Emitter;
    })();
    TypeScript.Emitter = Emitter;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var ErrorReporter = (function () {
        function ErrorReporter(outfile) {
            this.outfile = outfile;
            this.parser = null;
            this.checker = null;
            this.lineCol = {
                line: 0,
                col: 0
            };
            this.emitAsComments = true;
            this.hasErrors = false;
            this.pushToErrorSink = false;
            this.errorSink = [];
        }
        ErrorReporter.prototype.getCapturedErrors = function () {
            return this.errorSink;
        };
        ErrorReporter.prototype.freeCapturedErrors = function () {
            this.errorSink = [];
        };
        ErrorReporter.prototype.captureError = function (emsg) {
            this.errorSink[this.errorSink.length] = emsg;
        };
        ErrorReporter.prototype.setErrOut = function (outerr) {
            this.outfile = outerr;
            this.emitAsComments = false;
        };
        ErrorReporter.prototype.emitPrefix = function () {
            if(this.emitAsComments) {
                this.outfile.Write("// ");
            }
            this.outfile.Write(this.checker.locationInfo.filename + "(" + this.lineCol.line + "," + this.lineCol.col + "): ");
        };
        ErrorReporter.prototype.writePrefix = function (ast) {
            if(ast) {
                this.setError(ast);
            } else {
                this.lineCol.line = 0;
                this.lineCol.col = 0;
            }
            this.emitPrefix();
        };
        ErrorReporter.prototype.writePrefixFromSym = function (symbol) {
            if(symbol && this.checker.locationInfo.lineMap) {
                TypeScript.getSourceLineColFromMap(this.lineCol, symbol.location, this.checker.locationInfo.lineMap);
            } else {
                this.lineCol.line = -1;
                this.lineCol.col = -1;
            }
            this.emitPrefix();
        };
        ErrorReporter.prototype.setError = function (ast) {
            if(ast) {
                ast.flags |= TypeScript.ASTFlags.Error;
                if(this.checker.locationInfo.lineMap) {
                    TypeScript.getSourceLineColFromMap(this.lineCol, ast.minChar, this.checker.locationInfo.lineMap);
                }
            }
        };
        ErrorReporter.prototype.reportError = function (ast, message) {
            if(this.pushToErrorSink) {
                this.captureError(message);
                return;
            }
            this.hasErrors = true;
            if(ast && this.parser.errorRecovery && this.parser.errorCallback) {
                var len = (ast.limChar - ast.minChar);
                this.parser.errorCallback(ast.minChar, len, message, this.checker.locationInfo.unitIndex);
            } else {
                this.writePrefix(ast);
                this.outfile.WriteLine(message);
            }
        };
        ErrorReporter.prototype.reportErrorFromSym = function (symbol, message) {
            if(this.pushToErrorSink) {
                this.captureError(message);
                return;
            }
            this.hasErrors = true;
            if(this.parser.errorRecovery && this.parser.errorCallback) {
                this.parser.errorCallback(symbol.location, symbol.length, message, this.checker.locationInfo.unitIndex);
            } else {
                this.writePrefixFromSym(symbol);
                this.outfile.WriteLine(message);
            }
        };
        ErrorReporter.prototype.emitterError = function (ast, message) {
            this.reportError(ast, message);
            throw Error("EmitError");
        };
        ErrorReporter.prototype.duplicateIdentifier = function (ast, name) {
            this.reportError(ast, "Duplicate identifier '" + name + "'");
        };
        ErrorReporter.prototype.showRef = function (ast, text, symbol) {
            var defLineCol = {
                line: -1,
                col: -1
            };
            this.parser.getSourceLineCol(defLineCol, symbol.location);
            this.reportError(ast, "symbol " + text + " defined at (" + defLineCol.line + "," + defLineCol.col + ")");
        };
        ErrorReporter.prototype.unresolvedSymbol = function (ast, name) {
            this.reportError(ast, "The name '" + name + "' does not exist in the current scope");
        };
        ErrorReporter.prototype.symbolDoesNotReferToAValue = function (ast, name) {
            this.reportError(ast, "The name '" + name + "' does not refer to a value");
        };
        ErrorReporter.prototype.styleError = function (ast, msg) {
            var bkThrow = this.pushToErrorSink;
            this.pushToErrorSink = false;
            this.reportError(ast, "STYLE: " + msg);
            this.pushToErrorSink = bkThrow;
        };
        ErrorReporter.prototype.simpleError = function (ast, msg) {
            this.reportError(ast, msg);
        };
        ErrorReporter.prototype.simpleErrorFromSym = function (sym, msg) {
            this.reportErrorFromSym(sym, msg);
        };
        ErrorReporter.prototype.invalidSuperReference = function (ast) {
            this.simpleError(ast, "Keyword 'super' can only be used inside a class instance method");
        };
        ErrorReporter.prototype.valueCannotBeModified = function (ast) {
            this.simpleError(ast, "The left-hand side of an assignment expression must be a variable, property or indexer");
        };
        ErrorReporter.prototype.invalidCall = function (ast, nodeType, scope) {
            var targetType = ast.target.type;
            var typeName = targetType.getScopedTypeName(scope);
            if(targetType.construct && (nodeType == TypeScript.NodeType.Call)) {
                this.reportError(ast, "Value of type '" + typeName + "' is not callable.  Did you mean to include 'new'?");
            } else {
                var catString = (nodeType == TypeScript.NodeType.Call) ? "callable" : "newable";
                this.reportError(ast, "Value of type '" + typeName + "' is not " + catString);
            }
        };
        ErrorReporter.prototype.indexLHS = function (ast, scope) {
            var targetType = ast.operand1.type.getScopedTypeName(scope);
            var indexType = ast.operand2.type.getScopedTypeName(scope);
            this.simpleError(ast, "Value of type '" + targetType + "' is not indexable by type '" + indexType + "'");
        };
        ErrorReporter.prototype.incompatibleTypes = function (ast, t1, t2, op, scope, comparisonInfo) {
            if(!t1) {
                t1 = this.checker.anyType;
            }
            if(!t2) {
                t2 = this.checker.anyType;
            }
            var reason = comparisonInfo ? comparisonInfo.message : "";
            if(op) {
                this.reportError(ast, "Operator '" + op + "' cannot be applied to types '" + t1.getScopedTypeName(scope) + "' and '" + t2.getScopedTypeName(scope) + "'" + (reason ? ": " + reason : ""));
            } else {
                this.reportError(ast, "Cannot convert '" + t1.getScopedTypeName(scope) + "' to '" + t2.getScopedTypeName(scope) + "'" + (reason ? ": " + reason : ""));
            }
        };
        ErrorReporter.prototype.expectedClassOrInterface = function (ast) {
            this.simpleError(ast, "Expected var, class, interface, or module");
        };
        ErrorReporter.prototype.unaryOperatorTypeError = function (ast, op, type) {
            this.reportError(ast, "Operator '" + op + "' cannot be applied to type '" + type.getTypeName() + "'");
        };
        return ErrorReporter;
    })();
    TypeScript.ErrorReporter = ErrorReporter;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (TypeContext) {
        TypeContext._map = [];
        TypeContext.NoTypes = 0;
        TypeContext.ArraySuffix = 1;
        TypeContext.Primitive = 2;
        TypeContext.Named = 4;
        TypeContext.AllSimpleTypes = TypeContext.Primitive | TypeContext.Named;
        TypeContext.AllTypes = TypeContext.Primitive | TypeContext.Named | TypeContext.ArraySuffix;
    })(TypeScript.TypeContext || (TypeScript.TypeContext = {}));
    var TypeContext = TypeScript.TypeContext;
    (function (ParseState) {
        ParseState._map = [];
        ParseState._map[0] = "None";
        ParseState.None = 0;
        ParseState._map[1] = "StartScript";
        ParseState.StartScript = 1;
        ParseState._map[2] = "StartStatementList";
        ParseState.StartStatementList = 2;
        ParseState._map[3] = "StartStatement";
        ParseState.StartStatement = 3;
        ParseState._map[4] = "StartFncDecl";
        ParseState.StartFncDecl = 4;
        ParseState._map[5] = "FncDeclName";
        ParseState.FncDeclName = 5;
        ParseState._map[6] = "FncDeclArgs";
        ParseState.FncDeclArgs = 6;
        ParseState._map[7] = "FncDeclReturnType";
        ParseState.FncDeclReturnType = 7;
        ParseState._map[8] = "ForInit";
        ParseState.ForInit = 8;
        ParseState._map[9] = "ForInitAfterVar";
        ParseState.ForInitAfterVar = 9;
        ParseState._map[10] = "ForCondStart";
        ParseState.ForCondStart = 10;
        ParseState._map[11] = "EndStmtList";
        ParseState.EndStmtList = 11;
        ParseState._map[12] = "EndScript";
        ParseState.EndScript = 12;
    })(TypeScript.ParseState || (TypeScript.ParseState = {}));
    var ParseState = TypeScript.ParseState;
    var QuickParseResult = (function () {
        function QuickParseResult(Script, endLexState) {
            this.Script = Script;
            this.endLexState = endLexState;
        }
        return QuickParseResult;
    })();
    TypeScript.QuickParseResult = QuickParseResult;    
    var Parser = (function () {
        function Parser() {
            this.varLists = [];
            this.scopeLists = [];
            this.staticsLists = [];
            this.scanner = new TypeScript.Scanner();
            this.currentToken = null;
            this.needTerminator = false;
            this.inFunction = false;
            this.inInterfaceDecl = false;
            this.currentClassDecl = null;
            this.inFncDecl = false;
            this.anonId = new TypeScript.Identifier("_anonymous");
            this.style_requireSemi = false;
            this.style_funcInLoop = true;
            this.incremental = false;
            this.errorRecovery = false;
            this.outfile = undefined;
            this.errorCallback = null;
            this.state = ParseState.StartStatementList;
            this.ambientModule = false;
            this.ambientClass = false;
            this.topLevel = true;
            this.allowImportDeclaration = true;
            this.currentUnitIndex = (-1);
            this.prevIDTok = null;
            this.statementInfoStack = new Array();
            this.hasTopLevelImportOrExport = false;
            this.strictMode = false;
            this.nestingLevel = 0;
            this.prevExpr = null;
            this.currentClassDefinition = null;
            this.parsingClassConstructorDefinition = false;
            this.parsingDeclareFile = false;
            this.amdDependencies = [];
            this.inferPropertiesFromThisAssignment = false;
            this.requiresExtendsBlock = false;
            this.fname = "";
        }
        Parser.prototype.resetStmtStack = function () {
            this.statementInfoStack = new Array();
        };
        Parser.prototype.inLoop = function () {
            for(var j = this.statementInfoStack.length - 1; j >= 0; j--) {
                if(this.statementInfoStack[j].stmt.isLoop()) {
                    return true;
                }
            }
            return false;
        };
        Parser.prototype.pushStmt = function (stmt, labels) {
            var info = {
                stmt: stmt,
                labels: labels
            };
            this.statementInfoStack.push(info);
        };
        Parser.prototype.popStmt = function () {
            return this.statementInfoStack.pop();
        };
        Parser.prototype.resolveJumpTarget = function (jump) {
            var resolvedTarget = TypeScript.AST.getResolvedIdentifierName(jump.target);
            var len = this.statementInfoStack.length;
            for(var i = len - 1; i >= 0; i--) {
                var info = this.statementInfoStack[i];
                if(jump.target) {
                    if(info.labels && (info.labels.members.length > 0)) {
                        for(var j = 0, labLen = info.labels.members.length; j < labLen; j++) {
                            var label = info.labels.members[j];
                            if(label.id.text == resolvedTarget) {
                                jump.setResolvedTarget(this, info.stmt);
                                return;
                            }
                        }
                    }
                } else {
                    if(info.stmt.isLoop()) {
                        jump.setResolvedTarget(this, info.stmt);
                        return;
                    } else {
                        if((info.stmt.nodeType == TypeScript.NodeType.Switch) && (jump.nodeType == TypeScript.NodeType.Break)) {
                            jump.setResolvedTarget(this, info.stmt);
                            return;
                        }
                    }
                }
            }
            if(jump.target) {
                this.reportParseError("could not find enclosing statement with label " + jump.target);
            } else {
                if(jump.nodeType == TypeScript.NodeType.Break) {
                    this.reportParseError("break statement requires enclosing loop or switch");
                } else {
                    this.reportParseError("continue statement requires enclosing loop");
                }
            }
        };
        Parser.prototype.setErrorRecovery = function (outfile) {
            this.outfile = outfile;
            this.errorRecovery = true;
        };
        Parser.prototype.getSourceLineCol = function (lineCol, minChar) {
            TypeScript.getSourceLineColFromMap(lineCol, minChar, this.scanner.lineMap);
        };
        Parser.prototype.createRef = function (text, hasEscapeSequence, minChar) {
            var id = new TypeScript.Identifier(text, hasEscapeSequence);
            id.minChar = minChar;
            return id;
        };
        Parser.prototype.reportParseStyleError = function (message) {
            this.reportParseError("STYLE: " + message);
        };
        Parser.prototype.reportParseError = function (message, startPos, pos) {
            if (typeof startPos === "undefined") { startPos = this.scanner.startPos; }
            if (typeof pos === "undefined") { pos = this.scanner.pos; }
            var len = Math.max(1, pos - startPos);
            if(this.errorCallback) {
                this.errorCallback(startPos, len, message, this.currentUnitIndex);
            } else {
                if(this.errorRecovery) {
                    var lineCol = {
                        line: -1,
                        col: -1
                    };
                    this.getSourceLineCol(lineCol, startPos);
                    if(this.outfile) {
                        this.outfile.WriteLine("// " + this.fname + " (" + lineCol.line + "," + lineCol.col + "): " + message);
                    }
                } else {
                    throw new SyntaxError(this.fname + " (" + this.scanner.line + "," + this.scanner.col + "): " + message);
                }
            }
        };
        Parser.prototype.checkNextToken = function (tokenId, errorRecoverySet, errorText) {
            if (typeof errorText === "undefined") { errorText = null; }
            this.currentToken = this.scanner.scan();
            this.checkCurrentToken(tokenId, errorRecoverySet, errorText);
        };
        Parser.prototype.skip = function (errorRecoverySet) {
            errorRecoverySet |= TypeScript.ErrorRecoverySet.EOF;
            var ersTok = TypeScript.ErrorRecoverySet.None;
            var tokenInfo = TypeScript.lookupToken(this.currentToken.tokenId);
            if(tokenInfo != undefined) {
                ersTok = tokenInfo.ers;
            }
            var pendingRightCurlies = 0;
            while(((ersTok & errorRecoverySet) == TypeScript.ErrorRecoverySet.None) || (this.currentToken.tokenId == TypeScript.TokenID.CloseBrace) && (pendingRightCurlies > 0)) {
                if(this.currentToken.tokenId == TypeScript.TokenID.OpenBrace) {
                    pendingRightCurlies++;
                } else {
                    if(this.currentToken.tokenId == TypeScript.TokenID.CloseBrace) {
                        pendingRightCurlies--;
                    }
                }
                this.currentToken = this.scanner.scan();
                ersTok = TypeScript.ErrorRecoverySet.None;
                tokenInfo = TypeScript.lookupToken(this.currentToken.tokenId);
                if(tokenInfo != undefined) {
                    ersTok = tokenInfo.ers;
                }
            }
        };
        Parser.prototype.checkCurrentToken = function (tokenId, errorRecoverySet, errorText) {
            if (typeof errorText === "undefined") { errorText = null; }
            if(this.currentToken.tokenId != tokenId) {
                errorText = errorText == null ? ("Expected '" + TypeScript.tokenTable[tokenId].text + "'") : errorText;
                this.reportParseError(errorText);
                if(this.errorRecovery) {
                    this.skip(errorRecoverySet);
                }
            } else {
                this.currentToken = this.scanner.scan();
            }
        };
        Parser.prototype.pushDeclLists = function () {
            this.staticsLists.push(new TypeScript.ASTList());
            this.varLists.push(new TypeScript.ASTList());
            this.scopeLists.push(new TypeScript.ASTList());
        };
        Parser.prototype.popDeclLists = function () {
            this.staticsLists.pop();
            this.varLists.pop();
            this.scopeLists.pop();
        };
        Parser.prototype.topVarList = function () {
            return this.varLists[this.varLists.length - 1];
        };
        Parser.prototype.topScopeList = function () {
            return this.scopeLists[this.scopeLists.length - 1];
        };
        Parser.prototype.topStaticsList = function () {
            return this.staticsLists[this.staticsLists.length - 1];
        };
        Parser.prototype.parseComment = function (comment) {
            if(comment) {
                var c = new TypeScript.Comment(comment.value, comment.isBlock, comment.endsLine);
                c.minChar = comment.startPos;
                c.limChar = comment.startPos + comment.value.length;
                var lineCol = {
                    line: -1,
                    col: -1
                };
                this.getSourceLineCol(lineCol, c.minChar);
                c.minLine = lineCol.line;
                this.getSourceLineCol(lineCol, c.limChar);
                c.limLine = lineCol.line;
                if(!comment.isBlock && comment.value.length > 3 && comment.value.substring(0, 3) == "///") {
                    var dependencyPath = TypeScript.getAdditionalDependencyPath(comment.value);
                    if(dependencyPath) {
                        this.amdDependencies.push(dependencyPath);
                    }
                    if(TypeScript.getImplicitImport(comment.value)) {
                        this.hasTopLevelImportOrExport = true;
                    }
                }
                return c;
            } else {
                return null;
            }
        };
        Parser.prototype.parseCommentsInner = function (comments) {
            if(comments) {
                var commentASTs = new Array();
                for(var i = 0; i < comments.length; i++) {
                    commentASTs.push(this.parseComment(comments[i]));
                }
                return commentASTs;
            } else {
                return null;
            }
        };
        Parser.prototype.parseComments = function () {
            var comments = this.scanner.getComments();
            return this.parseCommentsInner(comments);
        };
        Parser.prototype.parseCommentsForLine = function (line) {
            var comments = this.scanner.getCommentsForLine(line);
            return this.parseCommentsInner(comments);
        };
        Parser.prototype.combineComments = function (comment1, comment2) {
            if(comment1 == null) {
                return comment2;
            } else {
                if(comment2 == null) {
                    return comment1;
                } else {
                    return comment1.concat(comment2);
                }
            }
        };
        Parser.prototype.parseEnumDecl = function (errorRecoverySet, modifiers) {
            var leftCurlyCount = this.scanner.leftCurlyCount;
            var rightCurlyCount = this.scanner.rightCurlyCount;
            var name = null;
            if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                name = TypeScript.Identifier.fromToken(this.currentToken);
                name.minChar = this.scanner.startPos;
                name.limChar = this.scanner.pos;
                this.currentToken = this.scanner.scan();
            } else {
                this.reportParseError("Enum declaration requires identifier");
                if(this.errorRecovery) {
                    name = new TypeScript.MissingIdentifier();
                    name.minChar = this.scanner.startPos;
                    name.limChar = this.scanner.startPos;
                    name.flags |= TypeScript.ASTFlags.Error;
                }
            }
            var membersMinChar = this.scanner.startPos;
            this.checkCurrentToken(TypeScript.TokenID.OpenBrace, errorRecoverySet | TypeScript.ErrorRecoverySet.ID);
            this.pushDeclLists();
            var members = new TypeScript.ASTList();
            members.minChar = membersMinChar;
            var mapDecl = new TypeScript.VarDecl(new TypeScript.Identifier("_map"), 0);
            mapDecl.varFlags |= TypeScript.VarFlags.Exported;
            mapDecl.varFlags |= TypeScript.VarFlags.Private;
            mapDecl.varFlags |= (TypeScript.VarFlags.Property | TypeScript.VarFlags.Public);
            mapDecl.init = new TypeScript.UnaryExpression(TypeScript.NodeType.ArrayLit, null);
            members.append(mapDecl);
            var lastValue = null;
            for(; ; ) {
                var minChar = this.scanner.startPos;
                var limChar;
                var memberName = null;
                var memberValue = null;
                var preComments = null;
                var postComments = null;
                if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToIDName(this.currentToken)) {
                    memberName = TypeScript.Identifier.fromToken(this.currentToken);
                    memberName.minChar = this.scanner.startPos;
                    memberName.limChar = this.scanner.pos;
                } else {
                    if(this.currentToken.tokenId == TypeScript.TokenID.CloseBrace) {
                        break;
                    } else {
                        this.reportParseError("Expected identifer of enum member");
                        if(this.errorRecovery) {
                            memberName = new TypeScript.MissingIdentifier();
                            memberName.minChar = this.scanner.startPos;
                            memberName.limChar = this.scanner.startPos;
                            memberName.flags |= TypeScript.ASTFlags.Error;
                        }
                    }
                }
                limChar = this.scanner.pos;
                preComments = this.parseComments();
                this.currentToken = this.scanner.scan();
                postComments = this.parseComments();
                if(this.currentToken.tokenId == TypeScript.TokenID.Equals) {
                    this.currentToken = this.scanner.scan();
                    memberValue = this.parseExpr(errorRecoverySet, TypeScript.OperatorPrecedence.Comma, true, TypeContext.NoTypes);
                    lastValue = memberValue;
                    limChar = memberValue.limChar;
                } else {
                    if(lastValue == null) {
                        memberValue = new TypeScript.NumberLiteral(0);
                        lastValue = memberValue;
                    } else {
                        memberValue = new TypeScript.NumberLiteral(lastValue.value + 1);
                        lastValue = memberValue;
                    }
                    var map = new TypeScript.BinaryExpression(TypeScript.NodeType.Asg, new TypeScript.BinaryExpression(TypeScript.NodeType.Index, new TypeScript.Identifier("_map"), memberValue), new TypeScript.StringLiteral('"' + memberName.actualText + '"'));
                    members.append(map);
                }
                var member = new TypeScript.VarDecl(memberName, this.nestingLevel);
                member.minChar = minChar;
                member.limChar = limChar;
                member.init = memberValue;
                member.typeExpr = new TypeScript.TypeReference(this.createRef(name.actualText, name.hasEscapeSequence, -1), 0);
                member.varFlags |= (TypeScript.VarFlags.Readonly | TypeScript.VarFlags.Property);
                if(memberValue.nodeType == TypeScript.NodeType.NumberLit) {
                    member.varFlags |= TypeScript.VarFlags.Constant;
                }
                member.preComments = preComments;
                members.append(member);
                member.postComments = postComments;
                member.varFlags |= TypeScript.VarFlags.Exported;
                if(this.currentToken.tokenId == TypeScript.TokenID.Comma) {
                    this.currentToken = this.scanner.scan();
                    member.postComments = this.combineComments(member.postComments, this.parseCommentsForLine(this.scanner.prevLine));
                    if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || (TypeScript.convertTokToIDName(this.currentToken))) {
                        continue;
                    }
                }
                break;
            }
            var endingToken = new TypeScript.ASTSpan();
            endingToken.minChar = this.scanner.startPos;
            endingToken.limChar = this.scanner.pos;
            this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
            members.limChar = this.scanner.lastTokenLimChar();
            var modDecl = new TypeScript.ModuleDeclaration(name, members, this.topVarList(), this.topScopeList(), endingToken);
            modDecl.modFlags |= TypeScript.ModuleFlags.IsEnum;
            this.popDeclLists();
            modDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;
            modDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;
            return modDecl;
        };
        Parser.prototype.parseDottedName = function (enclosedList) {
            this.currentToken = this.scanner.scan();
            if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                var id = TypeScript.Identifier.fromToken(this.currentToken);
                id.preComments = this.parseComments();
                enclosedList[enclosedList.length] = id;
                id.minChar = this.scanner.startPos;
                id.limChar = this.scanner.pos;
                this.currentToken = this.scanner.scan();
                if(this.currentToken.tokenId == TypeScript.TokenID.Dot) {
                    this.parseDottedName(enclosedList);
                }
            } else {
                this.reportParseError("need identifier after '.'");
            }
        };
        Parser.prototype.isValidImportPath = function (importPath) {
            importPath = TypeScript.stripQuotes(importPath);
            if(!importPath || importPath.indexOf(':') != -1 || importPath.indexOf('\\') != -1 || importPath.charAt(0) == '/') {
                return false;
            }
            return true;
        };
        Parser.prototype.parseImportDeclaration = function (errorRecoverySet, modifiers) {
            var name = null;
            var alias = null;
            var importDecl = null;
            var minChar = this.scanner.startPos;
            var isDynamicImport = false;
            this.currentToken = this.scanner.scan();
            if(this.currentToken.tokenId == TypeScript.TokenID.Identifier || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                name = TypeScript.Identifier.fromToken(this.currentToken);
            } else {
                this.reportParseError("Expected identifer after 'import'");
                name = new TypeScript.MissingIdentifier();
            }
            name.minChar = this.scanner.startPos;
            name.limChar = this.scanner.pos;
            this.currentToken = this.scanner.scan();
            this.checkCurrentToken(TypeScript.TokenID.Equals, errorRecoverySet | TypeScript.ErrorRecoverySet.ID);
            var aliasPreComments = this.parseComments();
            var limChar;
            if(this.currentToken.tokenId == TypeScript.TokenID.Identifier || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                if(this.currentToken.tokenId == TypeScript.TokenID.Module) {
                    limChar = this.scanner.pos;
                    this.currentToken = this.scanner.scan();
                    if(this.currentToken.tokenId == TypeScript.TokenID.OpenParen) {
                        this.currentToken = this.scanner.scan();
                        if(this.currentToken.tokenId == TypeScript.TokenID.StringLiteral || this.currentToken.tokenId == TypeScript.TokenID.Identifier || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                            if(this.currentToken.tokenId == TypeScript.TokenID.StringLiteral) {
                                if(this.topLevel) {
                                    this.hasTopLevelImportOrExport = true;
                                } else {
                                    if(!this.allowImportDeclaration) {
                                        this.reportParseError("Import declaration of external module is permitted only in global or top level dynamic modules");
                                    }
                                }
                                var aliasText = this.currentToken.getText();
                                alias = TypeScript.Identifier.fromToken(this.currentToken);
                                alias.minChar = this.scanner.startPos;
                                alias.limChar = this.scanner.pos;
                                if(!this.isValidImportPath((alias).text)) {
                                    this.reportParseError("Invalid import path");
                                }
                                isDynamicImport = true;
                                this.currentToken = this.scanner.scan();
                                alias.preComments = aliasPreComments;
                            } else {
                                alias = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, TypeScript.OperatorPrecedence.Assignment, true, TypeContext.NoTypes);
                                alias.preComments = aliasPreComments;
                            }
                        }
                        limChar = this.scanner.pos;
                        this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet | TypeScript.ErrorRecoverySet.ID);
                        if(alias) {
                            alias.postComments = this.parseComments();
                        }
                    }
                } else {
                    alias = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, TypeScript.OperatorPrecedence.Assignment, true, TypeContext.NoTypes);
                    limChar = this.scanner.pos;
                }
            } else {
                this.reportParseError("Expected module name");
                alias = new TypeScript.MissingIdentifier();
                alias.minChar = this.scanner.startPos;
                if(this.currentToken.tokenId == TypeScript.TokenID.Semicolon) {
                    alias.limChar = this.scanner.startPos;
                } else {
                    alias.limChar = this.scanner.pos;
                    this.currentToken = this.scanner.scan();
                }
                alias.flags |= TypeScript.ASTFlags.Error;
                limChar = alias.limChar;
            }
            importDecl = new TypeScript.ImportDeclaration(name, alias);
            importDecl.isDynamicImport = isDynamicImport;
            importDecl.minChar = minChar;
            importDecl.limChar = limChar;
            return importDecl;
        };
        Parser.prototype.parseModuleDecl = function (errorRecoverySet, modifiers, preComments) {
            var leftCurlyCount = this.scanner.leftCurlyCount;
            var rightCurlyCount = this.scanner.rightCurlyCount;
            var svAmbient = this.ambientModule;
            var svTopLevel = this.topLevel;
            this.topLevel = false;
            if(this.parsingDeclareFile || svAmbient || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                this.ambientModule = true;
            }
            this.currentToken = this.scanner.scan();
            var name = null;
            var enclosedList = null;
            this.pushDeclLists();
            var minChar = this.scanner.startPos;
            var isDynamicMod = false;
            if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || (this.currentToken.tokenId == TypeScript.TokenID.StringLiteral) || (!TypeScript.isPrimitiveTypeToken(this.currentToken) && TypeScript.convertTokToID(this.currentToken, this.strictMode))) {
                var nameText = this.currentToken.getText();
                if(this.currentToken.tokenId == TypeScript.TokenID.StringLiteral) {
                    isDynamicMod = true;
                    if(!this.ambientModule) {
                        this.reportParseError("Only ambient dynamic modules may have string literal names");
                    }
                    if(!svTopLevel) {
                        this.reportParseError("Dynamic modules may not be nested within other modules");
                    }
                }
                name = TypeScript.Identifier.fromToken(this.currentToken);
                name.minChar = this.scanner.startPos;
                name.limChar = this.scanner.pos;
                this.currentToken = this.scanner.scan();
            } else {
                if(this.currentToken.tokenId == TypeScript.TokenID.OpenBrace) {
                    this.reportParseError("Module name missing");
                    name = new TypeScript.Identifier("");
                    name.minChar = minChar;
                    name.limChar = minChar;
                }
            }
            if(this.currentToken.tokenId == TypeScript.TokenID.Dot) {
                enclosedList = new Array();
                this.parseDottedName(enclosedList);
            }
            if(name == null) {
                name = new TypeScript.MissingIdentifier();
            }
            var moduleBody = new TypeScript.ASTList();
            var bodyMinChar = this.scanner.startPos;
            this.checkCurrentToken(TypeScript.TokenID.OpenBrace, errorRecoverySet | TypeScript.ErrorRecoverySet.ID);
            if(svTopLevel && isDynamicMod) {
                this.allowImportDeclaration = true;
            } else {
                this.allowImportDeclaration = false;
            }
            this.parseStatementList(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly, moduleBody, true, true, TypeScript.AllowedElements.Global, modifiers);
            moduleBody.minChar = bodyMinChar;
            moduleBody.limChar = this.scanner.pos;
            var endingToken = new TypeScript.ASTSpan();
            endingToken.minChar = this.scanner.startPos;
            endingToken.limChar = this.scanner.pos;
            this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
            var limChar = this.scanner.lastTokenLimChar();
            var moduleDecl;
            this.allowImportDeclaration = svTopLevel;
            if(enclosedList && (enclosedList.length > 0)) {
                var len = enclosedList.length;
                var innerName = enclosedList[len - 1];
                var innerDecl = new TypeScript.ModuleDeclaration(innerName, moduleBody, this.topVarList(), this.topScopeList(), endingToken);
                innerDecl.preComments = preComments;
                if(this.parsingDeclareFile || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                    innerDecl.modFlags |= TypeScript.ModuleFlags.Ambient;
                }
                innerDecl.modFlags |= TypeScript.ModuleFlags.Exported;
                innerDecl.minChar = minChar;
                innerDecl.limChar = limChar;
                this.popDeclLists();
                var outerModBod;
                for(var i = len - 2; i >= 0; i--) {
                    outerModBod = new TypeScript.ASTList();
                    outerModBod.append(innerDecl);
                    innerName = enclosedList[i];
                    innerDecl = new TypeScript.ModuleDeclaration(innerName, outerModBod, new TypeScript.ASTList(), new TypeScript.ASTList(), endingToken);
                    outerModBod.minChar = innerDecl.minChar = minChar;
                    outerModBod.limChar = innerDecl.limChar = limChar;
                    if(this.parsingDeclareFile || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                        innerDecl.modFlags |= TypeScript.ModuleFlags.Ambient;
                    }
                    innerDecl.modFlags |= TypeScript.ModuleFlags.Exported;
                }
                outerModBod = new TypeScript.ASTList();
                outerModBod.append(innerDecl);
                outerModBod.minChar = minChar;
                outerModBod.limChar = limChar;
                moduleDecl = new TypeScript.ModuleDeclaration(name, outerModBod, new TypeScript.ASTList(), new TypeScript.ASTList(), endingToken);
            } else {
                moduleDecl = new TypeScript.ModuleDeclaration(name, moduleBody, this.topVarList(), this.topScopeList(), endingToken);
                moduleDecl.preComments = preComments;
                this.popDeclLists();
            }
            if(this.parsingDeclareFile || svAmbient || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                moduleDecl.modFlags |= TypeScript.ModuleFlags.Ambient;
            }
            if(svAmbient || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                moduleDecl.modFlags |= TypeScript.ModuleFlags.Exported;
            }
            if(isDynamicMod) {
                moduleDecl.modFlags |= TypeScript.ModuleFlags.IsDynamic;
            }
            this.ambientModule = svAmbient;
            this.topLevel = svTopLevel;
            moduleDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;
            moduleDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;
            moduleDecl.limChar = moduleBody.limChar;
            return moduleDecl;
        };
        Parser.prototype.parseTypeReferenceTail = function (errorRecoverySet, minChar, term) {
            var result = new TypeScript.TypeReference(term, 0);
            result.minChar = minChar;
            while(this.currentToken.tokenId == TypeScript.TokenID.OpenBracket) {
                this.currentToken = this.scanner.scan();
                result.arrayCount++;
                this.checkCurrentToken(TypeScript.TokenID.CloseBracket, errorRecoverySet | TypeScript.ErrorRecoverySet.LBrack);
            }
            result.limChar = this.scanner.lastTokenLimChar();
            return result;
        };
        Parser.prototype.parseNamedType = function (errorRecoverySet, minChar, term, tail) {
            this.currentToken = this.scanner.scan();
            if(this.currentToken.tokenId == TypeScript.TokenID.Dot) {
                var curpos = this.scanner.pos;
                this.currentToken = this.scanner.scan();
                if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || ((!this.errorRecovery || !this.scanner.lastTokenHadNewline()) && TypeScript.convertTokToID(this.currentToken, this.strictMode))) {
                    var op2 = TypeScript.Identifier.fromToken(this.currentToken);
                    op2.minChar = this.scanner.startPos;
                    op2.limChar = this.scanner.pos;
                    var dotNode = new TypeScript.BinaryExpression(TypeScript.NodeType.Dot, term, op2);
                    dotNode.minChar = term.minChar;
                    dotNode.limChar = op2.limChar;
                    return this.parseNamedType(errorRecoverySet, minChar, dotNode, tail);
                } else {
                    this.reportParseError("need identifier after '.'");
                    if(this.errorRecovery) {
                        term.flags |= TypeScript.ASTFlags.DotLHS;
                        term.limChar = this.scanner.lastTokenLimChar();
                        return term;
                    } else {
                        var eop2 = new TypeScript.MissingIdentifier();
                        eop2.minChar = this.scanner.pos;
                        eop2.limChar = this.scanner.pos;
                        var edotNode = new TypeScript.BinaryExpression(TypeScript.NodeType.Dot, term, eop2);
                        edotNode.flags |= TypeScript.ASTFlags.Error;
                        edotNode.minChar = term.minChar;
                        edotNode.limChar = eop2.limChar;
                        return this.parseNamedType(errorRecoverySet, minChar, edotNode, tail);
                    }
                }
            } else {
                if(tail) {
                    return this.parseTypeReferenceTail(errorRecoverySet, minChar, term);
                } else {
                    return term;
                }
            }
        };
        Parser.prototype.parseTypeReference = function (errorRecoverySet, allowVoid) {
            var minChar = this.scanner.startPos;
            var isConstructorMember = false;
            switch(this.currentToken.tokenId) {
                case TypeScript.TokenID.Void: {
                    if(!allowVoid) {
                        this.reportParseError("void not a valid type in this context");
                    }

                }
                case TypeScript.TokenID.Any:
                case TypeScript.TokenID.Number:
                case TypeScript.TokenID.Bool:
                case TypeScript.TokenID.String: {
                    var text = TypeScript.tokenTable[this.currentToken.tokenId].text;
                    var predefinedIdentifier = new TypeScript.Identifier(text);
                    predefinedIdentifier.minChar = minChar;
                    predefinedIdentifier.limChar = this.scanner.pos;
                    this.currentToken = this.scanner.scan();
                    return this.parseTypeReferenceTail(errorRecoverySet, minChar, predefinedIdentifier);
                }

                case TypeScript.TokenID.Identifier: {
                    var ident = this.createRef(this.currentToken.getText(), (this.currentToken).hasEscapeSequence, minChar);
                    ident.limChar = this.scanner.pos;
                    return this.parseNamedType(errorRecoverySet, minChar, ident, true);

                }
                case TypeScript.TokenID.OpenBrace: {
                    return this.parseObjectType(minChar, errorRecoverySet);

                }
                case TypeScript.TokenID.New: {
                    this.currentToken = this.scanner.scan();
                    if(this.currentToken.tokenId != TypeScript.TokenID.OpenParen) {
                        this.reportParseError("Expected '('");
                    } else {
                        isConstructorMember = true;
                    }

                }
                case TypeScript.TokenID.OpenParen: {
                    var formals = new TypeScript.ASTList();
                    var variableArgList = this.parseFormalParameterList(errorRecoverySet | TypeScript.ErrorRecoverySet.RParen, formals, false, true, false, false, false, false, null, true);
                    this.checkCurrentToken(TypeScript.TokenID.EqualsGreaterThan, errorRecoverySet);
                    var returnType = this.parseTypeReference(errorRecoverySet, true);
                    var funcDecl = new TypeScript.FuncDecl(null, null, false, formals, null, null, null, TypeScript.NodeType.FuncDecl);
                    funcDecl.returnTypeAnnotation = returnType;
                    funcDecl.variableArgList = variableArgList;
                    funcDecl.fncFlags |= TypeScript.FncFlags.Signature;
                    if(isConstructorMember) {
                        funcDecl.fncFlags |= TypeScript.FncFlags.ConstructMember;
                        funcDecl.hint = "_construct";
                        funcDecl.classDecl = null;
                    }
                    funcDecl.minChar = minChar;
                    return this.parseTypeReferenceTail(errorRecoverySet, minChar, funcDecl);
                }

                default: {
                    this.reportParseError("Expected type name");
                    var etr = new TypeScript.TypeReference(null, 0);
                    etr.flags |= TypeScript.ASTFlags.Error;
                    etr.minChar = this.scanner.pos;
                    etr.limChar = this.scanner.pos;
                    return etr;

                }
            }
        };
        Parser.prototype.parseObjectType = function (minChar, errorRecoverySet) {
            this.currentToken = this.scanner.scan();
            var members = new TypeScript.ASTList();
            members.minChar = minChar;
            var prevInInterfaceDecl = this.inInterfaceDecl;
            this.inInterfaceDecl = true;
            this.parseTypeMemberList(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly, members);
            this.inInterfaceDecl = prevInInterfaceDecl;
            this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
            var interfaceDecl = new TypeScript.InterfaceDeclaration(this.anonId, members, null, null);
            interfaceDecl.minChar = minChar;
            interfaceDecl.limChar = members.limChar;
            return this.parseTypeReferenceTail(errorRecoverySet, minChar, interfaceDecl);
        };
        Parser.prototype.parseFunctionBlock = function (errorRecoverySet, allowedElements, parentModifiers, bod, bodMinChar) {
            this.state = ParseState.StartStatementList;
            this.checkCurrentToken(TypeScript.TokenID.OpenBrace, errorRecoverySet | TypeScript.ErrorRecoverySet.StmtStart);
            var savedInFunction = this.inFunction;
            this.inFunction = true;
            this.parseStatementList(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly | TypeScript.ErrorRecoverySet.StmtStart, bod, true, false, allowedElements, parentModifiers);
            bod.minChar = bodMinChar;
            bod.limChar = this.scanner.pos;
            this.inFunction = savedInFunction;
            var ec = new TypeScript.EndCode();
            ec.minChar = bod.limChar;
            ec.limChar = ec.minChar;
            bod.append(ec);
        };
        Parser.prototype.parseFunctionStatements = function (errorRecoverySet, name, isConstructor, isMethod, args, allowedElements, minChar, requiresSignature, parentModifiers) {
            this.pushDeclLists();
            var svStmtStack = this.statementInfoStack;
            this.resetStmtStack();
            var bod = null;
            var wasShorthand = false;
            var isAnonLambda = false;
            var limChar;
            if(requiresSignature) {
                limChar = this.scanner.pos;
                if(this.currentToken.tokenId === TypeScript.TokenID.OpenBrace) {
                    this.reportParseError("Function declarations are not permitted within interfaces, ambient modules or classes");
                    bod = new TypeScript.ASTList();
                    var bodMinChar = this.scanner.startPos;
                    this.parseFunctionBlock(errorRecoverySet, allowedElements, parentModifiers, bod, bodMinChar);
                    this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
                    if(this.currentToken.tokenId === TypeScript.TokenID.Semicolon) {
                        this.currentToken = this.scanner.scan();
                    }
                } else {
                    this.checkCurrentToken(TypeScript.TokenID.Semicolon, errorRecoverySet, "Expected ';'");
                }
            } else {
                bod = new TypeScript.ASTList();
                var bodMinChar = this.scanner.startPos;
                if(this.currentToken.tokenId == TypeScript.TokenID.EqualsGreaterThan) {
                    if(isMethod) {
                        this.reportParseError("'=>' may not be used for class methods");
                    }
                    wasShorthand = true;
                    this.currentToken = this.scanner.scan();
                }
                if(wasShorthand && this.currentToken.tokenId != TypeScript.TokenID.OpenBrace) {
                    var retExpr = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, TypeScript.OperatorPrecedence.Assignment, true, TypeContext.NoTypes);
                    var retStmt = new TypeScript.ReturnStatement();
                    retStmt.returnExpression = retExpr;
                    retStmt.minChar = retExpr.minChar;
                    retStmt.limChar = retExpr.limChar;
                    bod.minChar = bodMinChar;
                    bod.append(retStmt);
                } else {
                    isAnonLambda = wasShorthand;
                    this.parseFunctionBlock(errorRecoverySet, allowedElements, parentModifiers, bod, bodMinChar);
                }
                limChar = this.scanner.pos;
            }
            var funcDecl = new TypeScript.FuncDecl(name, bod, isConstructor, args, this.topVarList(), this.topScopeList(), this.topStaticsList(), TypeScript.NodeType.FuncDecl);
            this.popDeclLists();
            var scopeList = this.topScopeList();
            scopeList.append(funcDecl);
            var staticFuncDecl = false;
            if(!requiresSignature) {
                if(!wasShorthand || isAnonLambda) {
                    funcDecl.endingToken = new TypeScript.ASTSpan();
                    funcDecl.endingToken.minChar = this.scanner.startPos;
                    funcDecl.endingToken.limChar = this.scanner.pos;
                    this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
                    if(isAnonLambda) {
                        funcDecl.fncFlags |= TypeScript.FncFlags.IsFatArrowFunction;
                    }
                } else {
                    funcDecl.fncFlags |= TypeScript.FncFlags.IsFatArrowFunction;
                    funcDecl.endingToken = new TypeScript.ASTSpan();
                    funcDecl.endingToken.minChar = bod.members[0].minChar;
                    funcDecl.endingToken.limChar = bod.members[0].limChar;
                }
            }
            funcDecl.minChar = minChar;
            funcDecl.limChar = limChar;
            if(!requiresSignature) {
                funcDecl.fncFlags |= TypeScript.FncFlags.Definition;
            }
            this.statementInfoStack = svStmtStack;
            return funcDecl;
        };
        Parser.prototype.transformAnonymousArgsIntoFormals = function (formals, argList) {
            var _this = this;
            var translateBinExOperand = function (operand) {
                if(operand.nodeType == TypeScript.NodeType.Comma) {
                    return _this.transformAnonymousArgsIntoFormals(formals, operand);
                } else {
                    if(operand.nodeType == TypeScript.NodeType.Name || operand.nodeType == TypeScript.NodeType.Asg) {
                        var opArg = operand.nodeType == TypeScript.NodeType.Asg ? (operand).operand1 : operand;
                        var arg = new TypeScript.ArgDecl(opArg);
                        arg.preComments = opArg.preComments;
                        arg.postComments = opArg.postComments;
                        arg.minChar = operand.minChar;
                        arg.limChar = operand.limChar;
                        if(TypeScript.hasFlag(opArg.flags, TypeScript.ASTFlags.PossibleOptionalParameter)) {
                            arg.isOptional = true;
                        }
                        if(operand.nodeType == TypeScript.NodeType.Asg) {
                            arg.init = (operand).operand2;
                        }
                        formals.append(arg);
                        return arg.isOptional || arg.init;
                    } else {
                        _this.reportParseError("Invalid lambda argument");
                    }
                }
                return false;
            };
            if(argList) {
                if(argList.nodeType == TypeScript.NodeType.Comma) {
                    var commaList = argList;
                    if(commaList.operand1.isParenthesized) {
                        this.reportParseError("Invalid lambda argument", commaList.operand1.minChar, commaList.operand1.limChar);
                    }
                    if(commaList.operand2.isParenthesized) {
                        this.reportParseError("Invalid lambda argument", commaList.operand2.minChar, commaList.operand2.limChar);
                    }
                    var isOptional = translateBinExOperand(commaList.operand1);
                    isOptional = translateBinExOperand(commaList.operand2) || isOptional;
                    return isOptional;
                } else {
                    return translateBinExOperand(argList);
                }
            }
        };
        Parser.prototype.parseFormalParameterList = function (errorRecoverySet, formals, isClassConstr, isSig, isIndexer, isGetter, isSetter, isLambda, preProcessedLambdaArgs, expectClosingRParen) {
            formals.minChar = this.scanner.startPos;
            if(isIndexer) {
                this.currentToken = this.scanner.scan();
            } else {
                if(!isLambda) {
                    this.checkCurrentToken(TypeScript.TokenID.OpenParen, errorRecoverySet | TypeScript.ErrorRecoverySet.RParen);
                }
            }
            var sawEllipsis = false;
            var firstArg = true;
            var hasOptional = false;
            var haveFirstArgID = false;
            if(isLambda && preProcessedLambdaArgs && preProcessedLambdaArgs.nodeType != TypeScript.NodeType.EmptyExpr) {
                hasOptional = this.transformAnonymousArgsIntoFormals(formals, preProcessedLambdaArgs);
                haveFirstArgID = true;
            }
            while(true) {
                var munchedArg = false;
                var argFlags = TypeScript.VarFlags.None;
                var argMinChar = this.scanner.startPos;
                if(this.inferPropertiesFromThisAssignment && this.currentToken.tokenId == TypeScript.TokenID.This) {
                    if(!isClassConstr) {
                        this.reportParseError("Instance property declarations using 'this' may only be used in class constructors");
                    }
                    this.currentToken = this.scanner.scan();
                    argFlags |= (TypeScript.VarFlags.Public | TypeScript.VarFlags.Property);
                    if(this.currentClassDefinition) {
                        this.currentClassDefinition.varFlags |= TypeScript.VarFlags.ClassSuperMustBeFirstCallInConstructor;
                    }
                }
                if(this.currentToken.tokenId == TypeScript.TokenID.Public) {
                    argFlags |= (TypeScript.VarFlags.Public | TypeScript.VarFlags.Property);
                    if(this.currentClassDefinition) {
                        this.currentClassDefinition.varFlags |= TypeScript.VarFlags.ClassSuperMustBeFirstCallInConstructor;
                    }
                } else {
                    if(this.currentToken.tokenId == TypeScript.TokenID.Private) {
                        argFlags |= (TypeScript.VarFlags.Private | TypeScript.VarFlags.Property);
                        if(this.currentClassDefinition) {
                            this.currentClassDefinition.varFlags |= TypeScript.VarFlags.ClassSuperMustBeFirstCallInConstructor;
                        }
                    } else {
                        if(this.currentToken.tokenId == TypeScript.TokenID.Static && isClassConstr) {
                            this.reportParseError("Static properties can not be declared as parameter properties");
                            this.currentToken = this.scanner.scan();
                        }
                    }
                }
                if(argFlags != TypeScript.VarFlags.None) {
                    if(!isClassConstr) {
                        this.reportParseError("only constructor parameters can be properties");
                    }
                    this.currentToken = this.scanner.scan();
                    if(TypeScript.isModifier(this.currentToken)) {
                        this.reportParseError("Multiple modifiers may not be applied to parameters");
                        this.currentToken = this.scanner.scan();
                    }
                    if(this.inferPropertiesFromThisAssignment && this.currentToken.tokenId == TypeScript.TokenID.This) {
                        if(!isClassConstr) {
                            this.reportParseError("Instance property declarations using 'this' may only be used in class constructors");
                        }
                        this.currentToken = this.scanner.scan();
                        this.currentToken = this.scanner.scan();
                    }
                } else {
                    if(this.currentToken.tokenId == TypeScript.TokenID.DotDotDot) {
                        sawEllipsis = true;
                        this.currentToken = this.scanner.scan();
                        if(!(this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                            this.reportParseError("'...' parameters require both a parameter name and an array type annotation to be specified");
                            sawEllipsis = false;
                        }
                    }
                }
                var argId = null;
                if(!haveFirstArgID && (this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                    argId = TypeScript.Identifier.fromToken(this.currentToken);
                    argId.minChar = this.scanner.startPos;
                    argId.limChar = this.scanner.pos;
                }
                if(haveFirstArgID || argId) {
                    munchedArg = true;
                    var type = null;
                    var arg = null;
                    if(haveFirstArgID && formals.members.length) {
                        arg = formals.members[formals.members.length - 1];
                        if(arg.isOptional) {
                            hasOptional = true;
                        }
                    } else {
                        arg = new TypeScript.ArgDecl(argId);
                        if(isGetter) {
                            this.reportParseError("Property getters may not take any arguments");
                        }
                        if(isSetter && !firstArg) {
                            this.reportParseError("Property setters may only take one argument");
                        }
                        arg.minChar = argMinChar;
                        arg.preComments = this.parseComments();
                        this.currentToken = this.scanner.scan();
                    }
                    if(this.currentToken.tokenId == TypeScript.TokenID.Question) {
                        arg.isOptional = true;
                        hasOptional = true;
                        this.currentToken = this.scanner.scan();
                    }
                    if(this.currentToken.tokenId == TypeScript.TokenID.Colon) {
                        this.currentToken = this.scanner.scan();
                        type = this.parseTypeReference(errorRecoverySet, false);
                    }
                    if(this.currentToken.tokenId == TypeScript.TokenID.Equals) {
                        if(isSig) {
                            this.reportParseError("Arguments in signatures may not have default values");
                        }
                        hasOptional = true;
                        this.currentToken = this.scanner.scan();
                        arg.init = this.parseExpr(TypeScript.ErrorRecoverySet.Comma | errorRecoverySet, TypeScript.OperatorPrecedence.Comma, false, TypeContext.NoTypes);
                    }
                    if(hasOptional && !arg.isOptionalArg() && !sawEllipsis) {
                        this.reportParseError("Optional parameters may only be followed by other optional parameters");
                    }
                    if(sawEllipsis && arg.isOptionalArg()) {
                        this.reportParseError("Varargs may not be optional or have default parameters");
                    }
                    if(sawEllipsis && !type) {
                        this.reportParseError("'...' parameters require both a parameter name and an array type annotation to be specified");
                    }
                    arg.postComments = this.parseComments();
                    arg.typeExpr = type;
                    arg.limChar = this.scanner.lastTokenLimChar();
                    arg.varFlags |= argFlags;
                    if(!haveFirstArgID) {
                        formals.append(arg);
                    } else {
                        haveFirstArgID = false;
                    }
                }
                firstArg = false;
                if(this.currentToken.tokenId == TypeScript.TokenID.Comma) {
                    if((munchedArg) && (!sawEllipsis)) {
                        this.currentToken = this.scanner.scan();
                        continue;
                    } else {
                        this.reportParseError("Unexpected ',' in argument list");
                        if(this.errorRecovery) {
                            this.currentToken = this.scanner.scan();
                            continue;
                        }
                    }
                } else {
                    break;
                }
            }
            if(isIndexer) {
                this.checkCurrentToken(TypeScript.TokenID.CloseBracket, errorRecoverySet | TypeScript.ErrorRecoverySet.LCurly | TypeScript.ErrorRecoverySet.SColon);
            } else {
                if(expectClosingRParen) {
                    this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet | TypeScript.ErrorRecoverySet.LCurly | TypeScript.ErrorRecoverySet.SColon);
                }
            }
            formals.limChar = this.scanner.lastTokenLimChar();
            return sawEllipsis;
        };
        Parser.prototype.parseFncDecl = function (errorRecoverySet, isDecl, requiresSignature, isMethod, methodName, indexer, isStatic, markedAsAmbient, modifiers, lambdaArgContext, expectClosingRParen) {
            var leftCurlyCount = this.scanner.leftCurlyCount;
            var rightCurlyCount = this.scanner.rightCurlyCount;
            var prevInConstr = this.parsingClassConstructorDefinition;
            this.parsingClassConstructorDefinition = false;
            var name = null;
            var fnMin = this.scanner.startPos;
            var minChar = this.scanner.pos;
            var prevNestingLevel = this.nestingLevel;
            var preComments = this.parseComments();
            var isLambda = !!lambdaArgContext;
            this.nestingLevel = 0;
            if((!this.style_funcInLoop) && this.inLoop()) {
                this.reportParseStyleError("function declaration in loop");
            }
            if(!isMethod && !isStatic && !indexer && !lambdaArgContext) {
                this.currentToken = this.scanner.scan();
                this.state = ParseState.StartFncDecl;
                if((this.currentToken.tokenId != TypeScript.TokenID.Identifier) && (!TypeScript.convertTokToID(this.currentToken, this.strictMode))) {
                    if(isDecl) {
                        this.reportParseError("Function declaration must include identifier");
                        this.nestingLevel = prevNestingLevel;
                        return new TypeScript.IncompleteAST(fnMin, this.scanner.pos);
                    }
                } else {
                    name = TypeScript.Identifier.fromToken(this.currentToken);
                    name.minChar = this.scanner.startPos;
                    name.limChar = this.scanner.pos;
                    this.currentToken = this.scanner.scan();
                }
            } else {
                if(methodName) {
                    name = methodName;
                }
            }
            this.state = ParseState.FncDeclName;
            var args = new TypeScript.ASTList();
            var variableArgList = false;
            var isOverload = false;
            var isGetter = TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Getter);
            var isSetter = TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Setter);
            if((this.currentToken.tokenId == TypeScript.TokenID.OpenParen) || (indexer && (this.currentToken.tokenId == TypeScript.TokenID.OpenBracket)) || (lambdaArgContext && (lambdaArgContext.preProcessedLambdaArgs || this.currentToken.tokenId == TypeScript.TokenID.DotDotDot))) {
                variableArgList = this.parseFormalParameterList(errorRecoverySet, args, false, requiresSignature, indexer, isGetter, isSetter, isLambda, lambdaArgContext ? lambdaArgContext.preProcessedLambdaArgs : null, expectClosingRParen);
            }
            this.state = ParseState.FncDeclArgs;
            var returnType = null;
            if(this.currentToken.tokenId == TypeScript.TokenID.Colon) {
                this.currentToken = this.scanner.scan();
                if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Setter)) {
                    this.reportParseError("Property setters may not declare a return type");
                }
                returnType = this.parseTypeReference(errorRecoverySet, true);
            }
            if(indexer && args.members.length == 0) {
                this.reportParseError("Index signatures require a parameter type to be specified");
            }
            this.state = ParseState.FncDeclReturnType;
            if(isLambda && this.currentToken.tokenId != TypeScript.TokenID.EqualsGreaterThan) {
                this.reportParseError("Expected '=>'");
            }
            if(isDecl && !(this.parsingDeclareFile || markedAsAmbient) && (!isMethod || !(this.ambientModule || this.ambientClass || this.inInterfaceDecl)) && this.currentToken.tokenId == TypeScript.TokenID.Semicolon) {
                isOverload = true;
                isDecl = false;
                requiresSignature = true;
            }
            var svInFncDecl = this.inFncDecl;
            this.inFncDecl = true;
            var funcDecl = this.parseFunctionStatements(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly, name, false, isMethod, args, TypeScript.AllowedElements.None, minChar, requiresSignature, TypeScript.Modifiers.None);
            this.inFncDecl = svInFncDecl;
            funcDecl.variableArgList = variableArgList;
            funcDecl.isOverload = isOverload;
            if(!requiresSignature) {
                funcDecl.fncFlags |= TypeScript.FncFlags.Definition;
            }
            if(isStatic) {
                funcDecl.fncFlags |= TypeScript.FncFlags.Static;
            }
            if(requiresSignature) {
                funcDecl.fncFlags |= TypeScript.FncFlags.Signature;
            }
            if(indexer) {
                funcDecl.fncFlags |= TypeScript.FncFlags.IndexerMember;
            }
            funcDecl.returnTypeAnnotation = returnType;
            if(isMethod) {
                funcDecl.fncFlags |= TypeScript.FncFlags.Method;
                funcDecl.fncFlags |= TypeScript.FncFlags.ClassPropertyMethodExported;
            }
            funcDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;
            funcDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;
            this.nestingLevel = prevNestingLevel;
            this.parsingClassConstructorDefinition = prevInConstr;
            funcDecl.preComments = preComments;
            return funcDecl;
        };
        Parser.prototype.convertToTypeReference = function (ast) {
            var result;
            switch(ast.nodeType) {
                case TypeScript.NodeType.TypeRef: {
                    return ast;

                }
                case TypeScript.NodeType.Name: {
                    result = new TypeScript.TypeReference(ast, 0);
                    result.minChar = ast.minChar;
                    result.limChar = ast.limChar;
                    return result;

                }
                case TypeScript.NodeType.Index: {
                    var expr = ast;
                    result = this.convertToTypeReference(expr.operand1);
                    if(result) {
                        result.arrayCount++;
                        result.minChar = expr.minChar;
                        result.limChar = expr.limChar;
                        return result;
                    } else {
                        var etr = new TypeScript.AST(TypeScript.NodeType.Error);
                        return etr;
                    }
                }

            }
            return null;
        };
        Parser.prototype.parseArgList = function (errorRecoverySet) {
            var args = new TypeScript.ASTList();
            args.minChar = this.scanner.startPos;
            this.currentToken = this.scanner.scan();
            if(this.currentToken.tokenId !== TypeScript.TokenID.CloseParen) {
                while(true) {
                    if(args.members.length > 65535) {
                        this.reportParseError("max number of args exceeded");
                        break;
                    }
                    var arg = this.parseExpr(TypeScript.ErrorRecoverySet.Comma | errorRecoverySet, TypeScript.OperatorPrecedence.Comma, true, TypeContext.NoTypes);
                    args.append(arg);
                    if(this.currentToken.tokenId != TypeScript.TokenID.Comma) {
                        break;
                    }
                    this.currentToken = this.scanner.scan();
                }
            }
            args.limChar = this.scanner.pos;
            return args;
        };
        Parser.prototype.parseBaseList = function (extendsList, implementsList, errorRecoverySet, isClass) {
            var keyword = true;
            var currentList = extendsList;
            for(; ; ) {
                if(keyword) {
                    if(this.currentToken.tokenId === TypeScript.TokenID.Implements) {
                        currentList = implementsList;
                    } else {
                        if(this.currentToken.tokenId == TypeScript.TokenID.Extends && !this.requiresExtendsBlock) {
                            this.requiresExtendsBlock = isClass;
                        }
                    }
                    this.currentToken = this.scanner.scan();
                    keyword = false;
                }
                var baseName = null;
                if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                    var minChar = this.scanner.startPos;
                    baseName = TypeScript.Identifier.fromToken(this.currentToken);
                    baseName.minChar = minChar;
                    baseName.limChar = this.scanner.pos;
                    baseName = this.parseNamedType(errorRecoverySet | TypeScript.ErrorRecoverySet.LCurly, minChar, baseName, false);
                } else {
                    this.reportParseError("Expected base name");
                    if(this.errorRecovery) {
                        baseName = new TypeScript.MissingIdentifier();
                        baseName.minChar = this.scanner.pos;
                        baseName.limChar = this.scanner.pos;
                        baseName.flags |= TypeScript.ASTFlags.Error;
                    }
                }
                if(this.currentToken.tokenId == TypeScript.TokenID.OpenParen) {
                    if(isClass) {
                        this.reportParseError("Base classes may only be initialized via a 'super' call within the constructor body");
                    } else {
                        this.reportParseError("Interfaces may not be extended with a call expression");
                    }
                } else {
                    currentList.append(baseName);
                }
                if(isClass && currentList == extendsList && extendsList.members.length > 1) {
                    this.reportParseError("A class may only extend one other class");
                }
                if(this.currentToken.tokenId == TypeScript.TokenID.Comma) {
                    this.currentToken = this.scanner.scan();
                    continue;
                } else {
                    if((this.currentToken.tokenId == TypeScript.TokenID.Extends) || (this.currentToken.tokenId == TypeScript.TokenID.Implements)) {
                        if(this.currentToken.tokenId == TypeScript.TokenID.Extends && !this.requiresExtendsBlock) {
                            this.requiresExtendsBlock = isClass;
                        }
                        currentList = extendsList;
                        keyword = true;
                        continue;
                    }
                }
                break;
            }
        };
        Parser.prototype.parseClassDecl = function (errorRecoverySet, minChar, modifiers) {
            var leftCurlyCount = this.scanner.leftCurlyCount;
            var rightCurlyCount = this.scanner.rightCurlyCount;
            if((modifiers & TypeScript.Modifiers.Readonly) != TypeScript.Modifiers.None) {
                this.reportParseError("const modifier is implicit for class");
            }
            if(this.parsingDeclareFile || this.ambientModule) {
                modifiers |= TypeScript.Modifiers.Ambient;
                modifiers |= TypeScript.Modifiers.Exported;
            }
            var classIsMarkedAsAmbient = this.parsingDeclareFile || (modifiers & TypeScript.Modifiers.Ambient) != TypeScript.Modifiers.None;
            var svAmbientClass = this.ambientClass;
            this.ambientClass = classIsMarkedAsAmbient;
            this.currentToken = this.scanner.scan();
            var name = null;
            if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || (!TypeScript.isPrimitiveTypeToken(this.currentToken) && TypeScript.convertTokToID(this.currentToken, this.strictMode))) {
                name = TypeScript.Identifier.fromToken(this.currentToken);
                name.minChar = this.scanner.startPos;
                name.limChar = this.scanner.pos;
                this.currentToken = this.scanner.scan();
            } else {
                this.reportParseError("class missing name");
                if(this.errorRecovery) {
                    name = new TypeScript.MissingIdentifier();
                    name.minChar = this.scanner.pos;
                    name.limChar = this.scanner.pos;
                    name.flags |= TypeScript.ASTFlags.Error;
                }
            }
            var extendsList = null;
            var implementsList = null;
            var requiresSignature = false;
            if((this.currentToken.tokenId == TypeScript.TokenID.Extends) || (this.currentToken.tokenId == TypeScript.TokenID.Implements)) {
                extendsList = new TypeScript.ASTList();
                implementsList = new TypeScript.ASTList();
                this.parseBaseList(extendsList, implementsList, errorRecoverySet, true);
            }
            var classDecl = new TypeScript.ClassDeclaration(name, new TypeScript.ASTList(), extendsList, implementsList);
            this.currentClassDefinition = classDecl;
            this.parseClassElements(classDecl, errorRecoverySet, modifiers);
            if(this.ambientModule || this.parsingDeclareFile || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                classDecl.varFlags |= TypeScript.VarFlags.Exported;
            }
            if(this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                classDecl.varFlags |= TypeScript.VarFlags.Ambient;
            }
            classDecl.varFlags |= TypeScript.VarFlags.Class;
            this.ambientClass = svAmbientClass;
            classDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;
            classDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;
            return classDecl;
        };
        Parser.prototype.parseClassElements = function (classDecl, errorRecoverySet, parentModifiers) {
            var modifiers = parentModifiers;
            var resetModifiers = false;
            var membersMinChar = this.scanner.startPos;
            this.checkCurrentToken(TypeScript.TokenID.OpenBrace, errorRecoverySet);
            this.nestingLevel++;
            var currentMemberMinChar = this.scanner.startPos;
            var wasGetOrSetId = false;
            while(!(this.currentToken.tokenId == TypeScript.TokenID.CloseBrace || this.currentToken.tokenId == TypeScript.TokenID.EndOfFile)) {
                var scanNext = true;
                var publicOrPrivateFlags = TypeScript.Modifiers.Public | TypeScript.Modifiers.Private;
                if(this.currentToken.tokenId == TypeScript.TokenID.Get) {
                    if(modifiers & TypeScript.Modifiers.Getter) {
                        this.reportParseError("Duplicate 'get' declaration in class body");
                    }
                    if(modifiers & TypeScript.Modifiers.Setter) {
                        this.reportParseError("Getter already marked as a setter");
                    }
                    modifiers |= TypeScript.Modifiers.Getter;
                } else {
                    if(this.currentToken.tokenId == TypeScript.TokenID.Set) {
                        if(modifiers & TypeScript.Modifiers.Setter) {
                            this.reportParseError("Duplicate 'set' declaration in class body");
                        }
                        if(modifiers & TypeScript.Modifiers.Getter) {
                            this.reportParseError("Setter already marked as a getter");
                        }
                        modifiers |= TypeScript.Modifiers.Setter;
                    } else {
                        if(this.currentToken.tokenId == TypeScript.TokenID.Private) {
                            if(modifiers & publicOrPrivateFlags) {
                                this.reportParseError("Multiple modifiers may not be applied to class members");
                            }
                            modifiers |= TypeScript.Modifiers.Private;
                        } else {
                            if(this.currentToken.tokenId == TypeScript.TokenID.Public) {
                                if(modifiers & publicOrPrivateFlags) {
                                    this.reportParseError("Multiple modifiers may not be applied to class members");
                                }
                                modifiers |= TypeScript.Modifiers.Public;
                            } else {
                                if(this.currentToken.tokenId == TypeScript.TokenID.Static) {
                                    if(modifiers & TypeScript.Modifiers.Static) {
                                        this.reportParseError("Multiple modifiers may not be applied to class members");
                                    }
                                    modifiers |= TypeScript.Modifiers.Static;
                                } else {
                                    if(this.currentToken.tokenId == TypeScript.TokenID.Constructor) {
                                        if(modifiers != parentModifiers) {
                                            this.reportParseError("Constructors may not have modifiers");
                                        }
                                        this.parseClassConstructorDeclaration(currentMemberMinChar, errorRecoverySet, modifiers);
                                        scanNext = false;
                                        resetModifiers = true;
                                    } else {
                                        if(wasGetOrSetId || this.currentToken.tokenId == TypeScript.TokenID.Identifier || TypeScript.convertTokToIDName(this.currentToken)) {
                                            var idText = wasGetOrSetId ? ((modifiers & TypeScript.Modifiers.Getter) ? "get" : "set") : this.currentToken.getText();
                                            var id = wasGetOrSetId ? new TypeScript.Identifier(idText) : TypeScript.Identifier.fromToken(this.currentToken);
                                            id.minChar = this.scanner.startPos;
                                            id.limChar = this.scanner.pos;
                                            if(wasGetOrSetId) {
                                                modifiers = modifiers ^ ((modifiers & TypeScript.Modifiers.Getter) ? TypeScript.Modifiers.Getter : TypeScript.Modifiers.Setter);
                                                wasGetOrSetId = false;
                                            } else {
                                                this.currentToken = this.scanner.scan();
                                            }
                                            if(this.currentToken.tokenId == TypeScript.TokenID.OpenParen) {
                                                this.parseClassMemberFunctionDeclaration(id, currentMemberMinChar, errorRecoverySet, modifiers);
                                                scanNext = false;
                                            } else {
                                                if(modifiers & TypeScript.Modifiers.Getter || modifiers & TypeScript.Modifiers.Setter) {
                                                    this.reportParseError("Property accessors must be functions");
                                                }
                                                var varDecl = this.parseClassMemberVariableDeclaration(id, currentMemberMinChar, false, errorRecoverySet, modifiers);
                                                if(varDecl.init && varDecl.init.nodeType == TypeScript.NodeType.FuncDecl) {
                                                    if(this.currentToken.tokenId == TypeScript.TokenID.CloseBrace) {
                                                        scanNext = false;
                                                    }
                                                } else {
                                                    if(varDecl.init && varDecl.init.nodeType == TypeScript.NodeType.ObjectLit && this.currentToken.tokenId != TypeScript.TokenID.Semicolon) {
                                                        scanNext = false;
                                                        varDecl.init.flags |= TypeScript.ASTFlags.AutomaticSemicolon;
                                                    } else {
                                                        if(this.currentToken.tokenId != TypeScript.TokenID.Semicolon) {
                                                            this.reportParseError("Expected ';'");
                                                            scanNext = false;
                                                        }
                                                    }
                                                }
                                            }
                                            resetModifiers = true;
                                        } else {
                                            if(this.currentToken.tokenId == TypeScript.TokenID.Super) {
                                                this.reportParseError("Base class initializers must be the first statement in a class definition");
                                            } else {
                                                if(!wasGetOrSetId && ((modifiers & TypeScript.Modifiers.Getter) || (modifiers & TypeScript.Modifiers.Setter)) && ((this.currentToken.tokenId == TypeScript.TokenID.OpenParen) || (this.currentToken.tokenId == TypeScript.TokenID.Equals) || (this.currentToken.tokenId == TypeScript.TokenID.Colon) || (this.currentToken.tokenId == TypeScript.TokenID.Semicolon))) {
                                                    wasGetOrSetId = true;
                                                    scanNext = false;
                                                } else {
                                                    if(this.currentToken.tokenId != TypeScript.TokenID.Semicolon) {
                                                        this.reportParseError("Unexpected '" + this.currentToken.getText() + "' in class definition");
                                                        resetModifiers = true;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if(scanNext) {
                    this.currentToken = this.scanner.scan();
                    if (this.currentToken === undefined) this.currentToken = this.scanner.scan();
                }
                if(resetModifiers) {
                    modifiers = parentModifiers;
                    currentMemberMinChar = this.scanner.startPos;
                    resetModifiers = false;
                }
            }
            var membersLimChar = this.scanner.pos;
            if(this.currentToken.tokenId == TypeScript.TokenID.CloseBrace) {
                classDecl.endingToken = new TypeScript.ASTSpan();
                classDecl.endingToken.minChar = this.scanner.startPos;
                classDecl.endingToken.limChar = this.scanner.pos;
                if(!this.currentClassDefinition.members.members.length) {
                    this.currentClassDefinition.preComments = this.parseComments();
                }
                this.currentToken = this.scanner.scan();
            }
            this.nestingLevel--;
            this.currentClassDefinition.members.minChar = membersMinChar;
            this.currentClassDefinition.members.limChar = membersLimChar;
            this.currentClassDefinition.limChar = membersLimChar;
            this.currentClassDefinition = null;
        };
        Parser.prototype.parseClassConstructorDeclaration = function (minChar, errorRecoverySet, modifiers) {
            this.parsingClassConstructorDefinition = true;
            var isAmbient = this.parsingDeclareFile || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient);
            var args = new TypeScript.ASTList();
            var variableArgList = false;
            var preComments = this.parseComments();
            this.currentToken = this.scanner.scan();
            if(this.currentToken.tokenId == TypeScript.TokenID.OpenParen) {
                variableArgList = this.parseFormalParameterList(errorRecoverySet, args, true, isAmbient, false, false, false, false, null, true);
                if(args.members.length > 0) {
                    var lastArg = args.members[args.members.length - 1];
                }
            }
            var requiresSignature = isAmbient || this.currentToken.tokenId == TypeScript.TokenID.Semicolon;
            if(requiresSignature) {
                for(var i = 0; i < args.members.length; i++) {
                    var arg = args.members[i];
                    if(TypeScript.hasFlag(arg.varFlags, TypeScript.VarFlags.Property)) {
                        this.reportParseError("Overload or ambient signatures may not specify parameter properties", arg.minChar, arg.limChar);
                    }
                }
            }
            if(!requiresSignature) {
                this.currentClassDefinition.constructorNestingLevel = this.nestingLevel + 1;
            }
            var constructorFuncDecl = this.parseFunctionStatements(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly, this.currentClassDefinition.name, true, false, args, TypeScript.AllowedElements.Properties, minChar, requiresSignature, modifiers);
            constructorFuncDecl.preComments = preComments;
            if(requiresSignature && !isAmbient) {
                constructorFuncDecl.isOverload = true;
            }
            constructorFuncDecl.variableArgList = variableArgList;
            this.currentClassDecl = null;
            constructorFuncDecl.returnTypeAnnotation = this.convertToTypeReference(this.currentClassDefinition.name);
            constructorFuncDecl.classDecl = this.currentClassDefinition;
            if(isAmbient) {
                constructorFuncDecl.fncFlags |= TypeScript.FncFlags.Ambient;
            }
            if(requiresSignature) {
                constructorFuncDecl.fncFlags |= TypeScript.FncFlags.Signature;
            }
            if(this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                constructorFuncDecl.fncFlags |= TypeScript.FncFlags.Exported;
            }
            if(this.currentClassDefinition.constructorDecl) {
                if(!isAmbient && !this.currentClassDefinition.constructorDecl.isSignature() && !constructorFuncDecl.isSignature()) {
                    this.reportParseError("Duplicate constructor definition");
                }
            }
            if(isAmbient || !constructorFuncDecl.isSignature()) {
                this.currentClassDefinition.constructorDecl = constructorFuncDecl;
            }
            constructorFuncDecl.fncFlags |= TypeScript.FncFlags.ClassMethod;
            this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = constructorFuncDecl;
            this.parsingClassConstructorDefinition = false;
            return constructorFuncDecl;
        };
        Parser.prototype.parseClassMemberVariableDeclaration = function (text, minChar, isDeclaredInConstructor, errorRecoverySet, modifiers) {
            var varDecl = new TypeScript.VarDecl(text, this.nestingLevel);
            varDecl.minChar = minChar;
            var isStatic = false;
            varDecl.preComments = this.parseComments();
            if(this.currentToken.tokenId == TypeScript.TokenID.Colon) {
                this.currentToken = this.scanner.scan();
                varDecl.typeExpr = this.parseTypeReference(errorRecoverySet | TypeScript.ErrorRecoverySet.Asg | TypeScript.ErrorRecoverySet.Comma, false);
                if(varDecl.typeExpr && varDecl.typeExpr.nodeType == TypeScript.NodeType.TypeRef) {
                    var typeExpr = (varDecl.typeExpr);
                    if(typeExpr.term && typeExpr.term.nodeType == TypeScript.NodeType.FuncDecl) {
                        typeExpr.term.preComments = varDecl.preComments;
                    }
                }
            }
            if(this.currentToken.tokenId == TypeScript.TokenID.Equals) {
                if(this.parsingDeclareFile || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                    this.reportParseError("context does not permit variable initializer");
                    if(this.errorRecovery) {
                        this.skip(errorRecoverySet);
                        varDecl.flags |= TypeScript.ASTFlags.Error;
                        varDecl.limChar = this.scanner.lastTokenLimChar();
                        return varDecl;
                    }
                }
                this.currentToken = this.scanner.scan();
                varDecl.init = this.parseExpr(TypeScript.ErrorRecoverySet.Comma | errorRecoverySet, TypeScript.OperatorPrecedence.Comma, true, TypeContext.NoTypes);
                varDecl.limChar = varDecl.init.limChar;
                if(!(modifiers & TypeScript.Modifiers.Static)) {
                    this.currentClassDefinition.varFlags |= TypeScript.VarFlags.ClassSuperMustBeFirstCallInConstructor;
                }
            } else {
                varDecl.limChar = this.scanner.pos;
            }
            if(modifiers & TypeScript.Modifiers.Static) {
                varDecl.varFlags |= TypeScript.VarFlags.Static;
                isStatic = true;
            }
            if((modifiers & TypeScript.Modifiers.Private) != TypeScript.Modifiers.None) {
                varDecl.varFlags |= TypeScript.VarFlags.Private;
            } else {
                varDecl.varFlags |= TypeScript.VarFlags.Public;
            }
            varDecl.varFlags |= TypeScript.VarFlags.Property;
            if(isDeclaredInConstructor) {
                varDecl.varFlags |= TypeScript.VarFlags.ClassConstructorProperty;
            }
            if(!isDeclaredInConstructor && !isStatic) {
                varDecl.varFlags |= TypeScript.VarFlags.ClassBodyProperty;
            }
            this.currentClassDefinition.knownMemberNames[text.actualText] = true;
            if(!isDeclaredInConstructor) {
                this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = varDecl;
            }
            varDecl.postComments = this.parseComments();
            return varDecl;
        };
        Parser.prototype.parseClassMemberFunctionDeclaration = function (methodName, minChar, errorRecoverySet, modifiers) {
            var wasAccessorID = this.prevIDTok != null;
            var isAccessor = TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Getter) || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Setter);
            var isStatic = TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Static);
            var isAmbient = this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient);
            errorRecoverySet |= TypeScript.ErrorRecoverySet.RParen;
            if(isAccessor && (modifiers & TypeScript.Modifiers.Ambient)) {
                this.reportParseError("Property accessors may not be declared in ambient classes");
            }
            var ast = this.parseFncDecl(errorRecoverySet, true, isAmbient, true, methodName, false, isStatic, isAmbient, modifiers, null, true);
            if(ast.nodeType == TypeScript.NodeType.Error) {
                return ast;
            }
            var funcDecl = ast;
            funcDecl.minChar = minChar;
            if(funcDecl.bod !== null) {
                funcDecl.limChar = funcDecl.bod.limChar;
            }
            if(modifiers & TypeScript.Modifiers.Private) {
                funcDecl.fncFlags |= TypeScript.FncFlags.Private;
            } else {
                funcDecl.fncFlags |= TypeScript.FncFlags.Public;
            }
            if(isStatic) {
                funcDecl.fncFlags |= TypeScript.FncFlags.Static;
            }
            if(isAccessor) {
                if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Getter)) {
                    funcDecl.fncFlags |= TypeScript.FncFlags.GetAccessor;
                    funcDecl.hint = "get" + funcDecl.name.actualText;
                } else {
                    funcDecl.fncFlags |= TypeScript.FncFlags.SetAccessor;
                    funcDecl.hint = "set" + funcDecl.name.actualText;
                }
                funcDecl.fncFlags |= TypeScript.FncFlags.IsFunctionExpression;
                if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                    this.reportParseError("Property accessors are only available when targeting ES5 or greater", funcDecl.minChar, funcDecl.limChar);
                }
            }
            funcDecl.fncFlags |= TypeScript.FncFlags.ClassMethod;
            this.currentClassDefinition.knownMemberNames[methodName.actualText] = true;
            this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = funcDecl;
            return funcDecl;
        };
        Parser.prototype.parseTypeMember = function (errorRecoverySet) {
            var minChar = this.scanner.startPos;
            var propertyDecl = this.parsePropertyDeclaration(errorRecoverySet, TypeScript.Modifiers.Public, true, false);
            if(propertyDecl) {
                propertyDecl.minChar = minChar;
                if(propertyDecl.nodeType == TypeScript.NodeType.VarDecl) {
                    this.checkCurrentToken(TypeScript.TokenID.Semicolon, errorRecoverySet);
                }
            }
            return propertyDecl;
        };
        Parser.prototype.parseTypeMemberList = function (errorRecoverySet, members) {
            errorRecoverySet |= TypeScript.ErrorRecoverySet.TypeScriptS;
            while(true) {
                switch(this.currentToken.tokenId) {
                    case TypeScript.TokenID.CloseBrace:
                    case TypeScript.TokenID.EndOfFile: {
                        members.limChar = this.scanner.pos;
                        return;

                    }
                }
                var element = this.parseTypeMember(errorRecoverySet);
                if(element) {
                    members.append(element);
                }
            }
        };
        Parser.prototype.parseInterfaceDecl = function (errorRecoverySet, modifiers) {
            var leftCurlyCount = this.scanner.leftCurlyCount;
            var rightCurlyCount = this.scanner.rightCurlyCount;
            this.currentToken = this.scanner.scan();
            var minChar = this.scanner.pos;
            var name = null;
            if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || (!TypeScript.isPrimitiveTypeToken(this.currentToken) && TypeScript.convertTokToID(this.currentToken, this.strictMode))) {
                name = TypeScript.Identifier.fromToken(this.currentToken);
                name.minChar = this.scanner.startPos;
                name.limChar = this.scanner.pos;
                this.currentToken = this.scanner.scan();
            } else {
                this.reportParseError("interface missing name");
                if(this.errorRecovery) {
                    name = new TypeScript.MissingIdentifier();
                    name.minChar = this.scanner.pos;
                    name.limChar = this.scanner.pos;
                    name.flags |= TypeScript.ASTFlags.Error;
                }
            }
            var extendsList = null;
            var implementsList = null;
            if(this.currentToken.tokenId === TypeScript.TokenID.Extends || this.currentToken.tokenId === TypeScript.TokenID.Implements) {
                if(this.currentToken.tokenId === TypeScript.TokenID.Implements) {
                    this.reportParseError("Expected 'extends'");
                }
                extendsList = new TypeScript.ASTList();
                implementsList = new TypeScript.ASTList();
                extendsList.minChar = this.scanner.startPos;
                this.parseBaseList(extendsList, implementsList, errorRecoverySet, false);
            }
            var membersMinChar = this.scanner.startPos;
            this.checkCurrentToken(TypeScript.TokenID.OpenBrace, errorRecoverySet | TypeScript.ErrorRecoverySet.TypeScriptS);
            var members = new TypeScript.ASTList();
            members.minChar = membersMinChar;
            var prevInInterfaceDecl = this.inInterfaceDecl;
            this.inInterfaceDecl = true;
            this.parseTypeMemberList(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly, members);
            this.inInterfaceDecl = prevInInterfaceDecl;
            this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
            var interfaceDecl = new TypeScript.InterfaceDeclaration(name, members, extendsList, null);
            if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Private)) {
                interfaceDecl.varFlags |= TypeScript.VarFlags.Private;
            }
            if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Public)) {
                interfaceDecl.varFlags |= TypeScript.VarFlags.Public;
            }
            if(this.parsingDeclareFile || this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                interfaceDecl.varFlags |= TypeScript.VarFlags.Exported;
            }
            interfaceDecl.limChar = members.limChar;
            interfaceDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;
            interfaceDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;
            return interfaceDecl;
        };
        Parser.prototype.makeVarDecl = function (id, nest) {
            var varDecl = new TypeScript.VarDecl(id, nest);
            var currentVarList = this.topVarList();
            if(currentVarList) {
                currentVarList.append(varDecl);
            }
            return varDecl;
        };
        Parser.prototype.parsePropertyDeclaration = function (errorRecoverySet, modifiers, requireSignature, isStatic) {
            var text = null;
            var minChar = this.scanner.startPos;
            var nameLimChar = minChar;
            var isNew = false;
            var isIndexer = false;
            var wasAccessorID = this.prevIDTok != null;
            var isAccessor = TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Getter) || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Setter);
            if(this.parsingDeclareFile || this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                requireSignature = true;
            }
            if(this.currentToken.tokenId == TypeScript.TokenID.OpenParen && !wasAccessorID) {
                if(!requireSignature && !isStatic) {
                    this.reportParseError("Expected identifier in property declaration");
                    if(this.errorRecovery) {
                        this.skip(errorRecoverySet);
                        text = new TypeScript.MissingIdentifier();
                    }
                }
            } else {
                if(this.currentToken.tokenId == TypeScript.TokenID.New) {
                    if(requireSignature) {
                        this.currentToken = this.scanner.scan();
                        if(this.currentToken.tokenId == TypeScript.TokenID.OpenParen) {
                            isNew = true;
                        }
                    }
                    if(!isNew) {
                        if(!requireSignature) {
                            this.currentToken = this.scanner.scan();
                        }
                        text = new TypeScript.Identifier("new");
                        text.minChar = this.scanner.pos - 3;
                        text.limChar = this.scanner.pos;
                        nameLimChar = this.scanner.pos;
                    }
                } else {
                    if((this.currentToken.tokenId == TypeScript.TokenID.OpenBracket) && requireSignature) {
                        isIndexer = true;
                        text = new TypeScript.Identifier("__item");
                    } else {
                        if((this.currentToken.tokenId != TypeScript.TokenID.Identifier) && (!TypeScript.convertTokToIDName(this.currentToken)) && !wasAccessorID) {
                            this.reportParseError("Expected identifier in property declaration");
                            if(this.errorRecovery) {
                                var eminChar = this.scanner.startPos;
                                var curpos = this.scanner.pos;
                                this.skip(errorRecoverySet & (~TypeScript.ErrorRecoverySet.Comma));
                                if(this.scanner.pos == curpos) {
                                    this.currentToken = this.scanner.scan();
                                }
                                var epd = new TypeScript.VarDecl(new TypeScript.MissingIdentifier(), this.nestingLevel);
                                epd.flags |= TypeScript.ASTFlags.Error;
                                epd.minChar = eminChar;
                                epd.limChar = this.scanner.lastTokenLimChar();
                                return epd;
                            }
                        } else {
                            if(wasAccessorID) {
                                text = TypeScript.Identifier.fromToken(this.prevIDTok);
                                text.minChar = this.scanner.lastTokenLimChar() - 3;
                                text.limChar = this.scanner.lastTokenLimChar();
                                nameLimChar = text.limChar;
                                if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                                    this.reportParseError("Property accessors are only available when targeting ES5 or greater");
                                }
                                if(this.currentToken.getText() == text.actualText && this.currentToken != this.prevIDTok) {
                                    this.currentToken = this.scanner.scan();
                                }
                                this.prevIDTok = null;
                            } else {
                                text = TypeScript.Identifier.fromToken(this.currentToken);
                                text.minChar = this.scanner.startPos;
                                text.limChar = this.scanner.pos;
                                nameLimChar = this.scanner.pos;
                                this.currentToken = this.scanner.scan();
                            }
                        }
                    }
                }
            }
            if(this.currentToken.tokenId == TypeScript.TokenID.Question) {
                if(this.inInterfaceDecl && text) {
                    text.flags |= TypeScript.ASTFlags.OptionalName;
                } else {
                    this.reportParseError("Optional properties may only be declared on interface or object types");
                }
                this.currentToken = this.scanner.scan();
            }
            if((this.currentToken.tokenId == TypeScript.TokenID.OpenParen) || (isIndexer && (this.currentToken.tokenId == TypeScript.TokenID.OpenBracket))) {
                var ers = errorRecoverySet | TypeScript.ErrorRecoverySet.RParen;
                if(isIndexer) {
                    ers = errorRecoverySet | TypeScript.ErrorRecoverySet.RBrack;
                }
                var ast = this.parseFncDecl(ers, true, requireSignature, !this.inFncDecl, text, isIndexer, isStatic, (this.parsingDeclareFile || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)), modifiers, null, true);
                var funcDecl;
                if(ast.nodeType == TypeScript.NodeType.Error) {
                    return ast;
                } else {
                    funcDecl = ast;
                }
                if(funcDecl.name) {
                    funcDecl.name.minChar = minChar;
                    funcDecl.name.limChar = nameLimChar;
                }
                if((modifiers & TypeScript.Modifiers.Public) != TypeScript.Modifiers.None) {
                    funcDecl.fncFlags |= TypeScript.FncFlags.Public;
                }
                if((modifiers & TypeScript.Modifiers.Private) != TypeScript.Modifiers.None) {
                    funcDecl.fncFlags |= TypeScript.FncFlags.Private;
                }
                if(isStatic) {
                    funcDecl.fncFlags |= TypeScript.FncFlags.Static;
                }
                if(this.parsingDeclareFile || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                    funcDecl.fncFlags |= TypeScript.FncFlags.Ambient;
                }
                if(isAccessor) {
                    if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Getter)) {
                        funcDecl.fncFlags |= TypeScript.FncFlags.GetAccessor;
                        funcDecl.hint = "get" + funcDecl.name.actualText;
                    } else {
                        funcDecl.fncFlags |= TypeScript.FncFlags.SetAccessor;
                        funcDecl.hint = "set" + funcDecl.name.actualText;
                    }
                    funcDecl.fncFlags |= TypeScript.FncFlags.IsFunctionExpression;
                    if(modifiers & TypeScript.Modifiers.Ambient) {
                        this.reportParseError("Property accessors may not be declared in ambient types");
                    }
                }
                if(text == null) {
                    if(isNew) {
                        funcDecl.fncFlags |= TypeScript.FncFlags.ConstructMember;
                        funcDecl.hint = "_construct";
                        funcDecl.classDecl = this.currentClassDecl;
                    } else {
                        funcDecl.hint = "_call";
                        funcDecl.fncFlags |= TypeScript.FncFlags.CallMember;
                    }
                }
                return funcDecl;
            } else {
                var varDecl = new TypeScript.VarDecl(text, this.nestingLevel);
                varDecl.preComments = this.parseComments();
                varDecl.minChar = minChar;
                if(this.currentToken.tokenId == TypeScript.TokenID.Colon) {
                    this.currentToken = this.scanner.scan();
                    varDecl.typeExpr = this.parseTypeReference(errorRecoverySet | TypeScript.ErrorRecoverySet.Asg | TypeScript.ErrorRecoverySet.Comma, false);
                    if(varDecl.typeExpr && varDecl.typeExpr.nodeType == TypeScript.NodeType.TypeRef) {
                        var typeExpr = (varDecl.typeExpr);
                        if(typeExpr.term && typeExpr.term.nodeType == TypeScript.NodeType.FuncDecl) {
                            typeExpr.term.preComments = varDecl.preComments;
                        }
                    }
                }
                if(this.currentToken.tokenId == TypeScript.TokenID.Equals) {
                    if(requireSignature) {
                        this.reportParseError("context does not permit variable initializer");
                        if(this.errorRecovery) {
                            this.skip(errorRecoverySet);
                            varDecl.flags |= TypeScript.ASTFlags.Error;
                            varDecl.limChar = this.scanner.lastTokenLimChar();
                            return varDecl;
                        }
                    }
                    this.currentToken = this.scanner.scan();
                    varDecl.init = this.parseExpr(TypeScript.ErrorRecoverySet.Comma | errorRecoverySet, TypeScript.OperatorPrecedence.Comma, true, TypeContext.NoTypes);
                    varDecl.limChar = varDecl.init.limChar;
                    if(varDecl.init.nodeType == TypeScript.NodeType.FuncDecl) {
                        var funcDecl = varDecl.init;
                        funcDecl.hint = varDecl.id.text;
                        funcDecl.boundToProperty = varDecl;
                    } else {
                        if(isAccessor) {
                            this.reportParseError("Accessors may only be functions");
                        }
                    }
                } else {
                    varDecl.limChar = this.scanner.pos;
                }
                if((modifiers & TypeScript.Modifiers.Readonly) != TypeScript.Modifiers.None) {
                    varDecl.varFlags |= TypeScript.VarFlags.Readonly;
                }
                if(isStatic) {
                    varDecl.varFlags |= TypeScript.VarFlags.Static;
                }
                if((modifiers & TypeScript.Modifiers.Public) != TypeScript.Modifiers.None) {
                    varDecl.varFlags |= TypeScript.VarFlags.Public;
                }
                if((modifiers & TypeScript.Modifiers.Private) != TypeScript.Modifiers.None) {
                    varDecl.varFlags |= TypeScript.VarFlags.Private;
                }
                varDecl.varFlags |= TypeScript.VarFlags.Property;
                return varDecl;
            }
        };
        Parser.prototype.parseVariableDeclaration = function (errorRecoverySet, modifiers, allowIn, isStatic) {
            var isConst = TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Readonly);
            var minChar = this.scanner.startPos;
            var varDecl = null;
            var declList = null;
            var multivar = false;
            this.currentToken = this.scanner.scan();
            var varDeclPreComments = this.parseComments();
            while(true) {
                if((this.currentToken.tokenId != TypeScript.TokenID.Identifier) && (!TypeScript.convertTokToID(this.currentToken, this.strictMode))) {
                    this.reportParseError("Expected identifier in variable declaration");
                    if(this.errorRecovery) {
                        varDecl = new TypeScript.VarDecl(new TypeScript.MissingIdentifier(), this.nestingLevel);
                        varDecl.minChar = minChar;
                        this.skip(errorRecoverySet);
                        varDecl.flags |= TypeScript.ASTFlags.Error;
                        varDecl.limChar = this.scanner.lastTokenLimChar();
                        return varDecl;
                    }
                }
                var varDeclName = TypeScript.Identifier.fromToken(this.currentToken);
                if(this.strictMode && (varDeclName.text == "eval")) {
                    this.reportParseError("'eval' may not name a variable in strict mode");
                }
                varDecl = this.makeVarDecl(varDeclName, this.nestingLevel);
                varDecl.id.minChar = this.scanner.startPos;
                varDecl.id.limChar = this.scanner.pos;
                varDecl.preComments = varDeclPreComments;
                if(isStatic) {
                    varDecl.varFlags |= TypeScript.VarFlags.Static;
                }
                if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Readonly)) {
                    varDecl.varFlags |= TypeScript.VarFlags.Readonly;
                }
                if(this.parsingDeclareFile || this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                    varDecl.varFlags |= TypeScript.VarFlags.Ambient;
                }
                if(this.parsingDeclareFile || this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                    varDecl.varFlags |= TypeScript.VarFlags.Exported;
                }
                varDecl.minChar = minChar;
                if(declList) {
                    declList.append(varDecl);
                }
                this.currentToken = this.scanner.scan();
                if(this.currentToken.tokenId == TypeScript.TokenID.Colon) {
                    this.currentToken = this.scanner.scan();
                    var prevInFncDecl = this.inFncDecl;
                    this.inFncDecl = false;
                    varDecl.typeExpr = this.parseTypeReference(errorRecoverySet | TypeScript.ErrorRecoverySet.Asg | TypeScript.ErrorRecoverySet.Comma, false);
                    this.inFncDecl = prevInFncDecl;
                }
                if(this.currentToken.tokenId == TypeScript.TokenID.Equals) {
                    if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Ambient)) {
                        this.reportParseError("Ambient variable can not have an initializer");
                    }
                    this.currentToken = this.scanner.scan();
                    varDecl.init = this.parseExpr(TypeScript.ErrorRecoverySet.Comma | errorRecoverySet, TypeScript.OperatorPrecedence.Comma, allowIn, TypeContext.NoTypes);
                    varDecl.limChar = varDecl.init.limChar;
                    if(varDecl.init.nodeType == TypeScript.NodeType.FuncDecl) {
                        var funcDecl = varDecl.init;
                        funcDecl.hint = varDecl.id.actualText;
                    }
                } else {
                    if(isConst) {
                        this.reportParseError("const declaration requires initializer");
                    }
                    varDecl.limChar = this.scanner.pos;
                }
                varDecl.postComments = this.parseCommentsForLine(this.scanner.line);
                if(this.currentToken.tokenId != TypeScript.TokenID.Comma) {
                    if(declList) {
                        declList.limChar = varDecl.limChar;
                        return declList;
                    } else {
                        return varDecl;
                    }
                }
                if(!multivar) {
                    declList = new TypeScript.ASTList();
                    declList.minChar = varDecl.minChar;
                    declList.append(varDecl);
                    multivar = true;
                }
                this.currentToken = this.scanner.scan();
                minChar = this.scanner.startPos;
            }
        };
        Parser.prototype.parseMemberList = function (errorRecoverySet) {
            var elements = new TypeScript.ASTList();
            if(this.currentToken.tokenId == TypeScript.TokenID.CloseBrace) {
                return elements;
            }
            var idHint = null;
            var memberName = null;
            var memberExpr = null;
            var member = null;
            var minChar = this.scanner.startPos;
            var isSet = false;
            var skippedTokenForGetSetId = false;
            var getSetTok = null;
            var getSetStartPos = 0;
            var getSetPos = 0;
            for(; ; ) {
                var accessorPattern = false;
                if(this.currentToken.tokenId == TypeScript.TokenID.Get || this.currentToken.tokenId == TypeScript.TokenID.Set) {
                    isSet = this.currentToken.tokenId == TypeScript.TokenID.Set;
                    getSetTok = this.currentToken;
                    getSetStartPos = this.scanner.startPos;
                    getSetPos = this.scanner.pos;
                    this.currentToken = this.scanner.scan();
                    if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToIDName(this.currentToken)) {
                        idHint = isSet ? "set" : "get";
                        idHint = idHint + this.currentToken.getText();
                        memberName = TypeScript.Identifier.fromToken(this.currentToken);
                        memberName.minChar = this.scanner.startPos;
                        accessorPattern = true;
                        if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                            this.reportParseError("Property accessors are only available when targeting ES5 or greater");
                        }
                    } else {
                        if(this.currentToken.tokenId != TypeScript.TokenID.Colon) {
                            this.reportParseError("Expected identifier, string or number as accessor name");
                        } else {
                            skippedTokenForGetSetId = true;
                            memberName = TypeScript.Identifier.fromToken(getSetTok);
                            memberName.minChar = getSetStartPos;
                            memberName.limChar = getSetPos;
                        }
                    }
                } else {
                    if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToIDName(this.currentToken)) {
                        idHint = this.currentToken.getText();
                        memberName = TypeScript.Identifier.fromToken(this.currentToken);
                        memberName.minChar = this.scanner.startPos;
                        memberName.limChar = this.scanner.pos;
                    } else {
                        if(this.currentToken.tokenId == TypeScript.TokenID.StringLiteral) {
                            idHint = this.currentToken.getText();
                            memberName = new TypeScript.StringLiteral(idHint);
                            memberName.minChar = this.scanner.startPos;
                            memberName.limChar = this.scanner.pos;
                        } else {
                            if(this.currentToken.tokenId == TypeScript.TokenID.NumberLiteral) {
                                var ntok = this.currentToken;
                                idHint = ntok.value.toString();
                                memberName = new TypeScript.StringLiteral(idHint);
                                memberName.minChar = this.scanner.startPos;
                                memberName.limChar = this.scanner.pos;
                            } else {
                                this.reportParseError("Expected identifier, string or number as member name");
                                if(this.errorRecovery) {
                                    memberName = new TypeScript.MissingIdentifier();
                                    memberName.minChar = this.scanner.startPos;
                                    memberName.flags |= TypeScript.ASTFlags.Error;
                                    this.skip(errorRecoverySet | TypeScript.ErrorRecoverySet.Comma);
                                    memberName.limChar = this.scanner.lastTokenLimChar();
                                }
                            }
                        }
                    }
                }
                if(!skippedTokenForGetSetId) {
                    this.currentToken = this.scanner.scan();
                } else {
                    skippedTokenForGetSetId = false;
                }
                if(this.currentToken.tokenId == TypeScript.TokenID.Question) {
                    memberName.flags |= TypeScript.ASTFlags.OptionalName;
                    this.currentToken = this.scanner.scan();
                }
                if(accessorPattern) {
                    var args = new TypeScript.ASTList();
                    this.parseFormalParameterList(errorRecoverySet | TypeScript.ErrorRecoverySet.RParen, args, false, true, false, !isSet, isSet, false, null, true);
                    var funcDecl = this.parseFunctionStatements(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly, memberName, false, true, args, TypeScript.AllowedElements.None, this.scanner.startPos, false, TypeScript.Modifiers.None);
                    if(isSet && funcDecl.returnTypeAnnotation) {
                        this.reportParseError("Property setters may not declare a return type");
                    }
                    funcDecl.fncFlags |= isSet ? TypeScript.FncFlags.SetAccessor : TypeScript.FncFlags.GetAccessor;
                    funcDecl.fncFlags |= TypeScript.FncFlags.IsFunctionExpression;
                    funcDecl.hint = idHint;
                    memberExpr = funcDecl;
                    member = new TypeScript.BinaryExpression(TypeScript.NodeType.Member, memberName, memberExpr);
                    member.minChar = memberName.minChar;
                    if(memberExpr.nodeType == TypeScript.NodeType.FuncDecl) {
                        var funcDecl = memberExpr;
                        funcDecl.hint = idHint;
                    }
                } else {
                    if(this.currentToken.tokenId == TypeScript.TokenID.Colon) {
                        this.currentToken = this.scanner.scan();
                        memberExpr = this.parseExpr(TypeScript.ErrorRecoverySet.Comma | errorRecoverySet, TypeScript.OperatorPrecedence.Comma, true, TypeContext.NoTypes);
                        if(memberExpr.nodeType == TypeScript.NodeType.TypeRef) {
                            this.reportParseError("Expected 'new' on array declaration in member definition");
                        }
                        member = new TypeScript.BinaryExpression(TypeScript.NodeType.Member, memberName, memberExpr);
                        member.minChar = memberName.minChar;
                        if(memberExpr.nodeType == TypeScript.NodeType.FuncDecl) {
                            var funcDecl = memberExpr;
                            funcDecl.hint = idHint;
                        }
                    } else {
                        this.reportParseError("Expected ':' in member definition");
                        if(this.errorRecovery) {
                            this.skip(errorRecoverySet);
                            elements.flags |= TypeScript.ASTFlags.Error;
                            elements.minChar = minChar;
                            elements.limChar = this.scanner.lastTokenLimChar();
                            return elements;
                        }
                    }
                }
                idHint = null;
                elements.append(member);
                member.limChar = this.scanner.lastTokenLimChar();
                if(this.currentToken.tokenId != TypeScript.TokenID.Comma) {
                    break;
                } else {
                    this.currentToken = this.scanner.scan();
                }
                if(this.currentToken.tokenId == TypeScript.TokenID.CloseBrace) {
                    break;
                }
            }
            if(member) {
                elements.limChar = member.limChar;
            }
            elements.minChar = minChar;
            return elements;
        };
        Parser.prototype.parseArrayList = function (errorRecoverySet) {
            var elements = null;
            if(this.currentToken.tokenId == TypeScript.TokenID.CloseBracket) {
                return elements;
            } else {
                elements = new TypeScript.ASTList();
                elements.minChar = this.scanner.startPos;
            }
            var arg;
            for(; ; ) {
                if((this.currentToken.tokenId == TypeScript.TokenID.Comma) || (this.currentToken.tokenId == TypeScript.TokenID.CloseBracket)) {
                    arg = new TypeScript.AST(TypeScript.NodeType.EmptyExpr);
                } else {
                    arg = this.parseExpr(TypeScript.ErrorRecoverySet.Comma | errorRecoverySet, TypeScript.OperatorPrecedence.Comma, true, TypeContext.NoTypes);
                }
                elements.append(arg);
                if(this.currentToken.tokenId != TypeScript.TokenID.Comma) {
                    break;
                }
                this.currentToken = this.scanner.scan();
            }
            elements.limChar = this.scanner.lastTokenLimChar();
            return elements;
        };
        Parser.prototype.parseArrayLiteral = function (errorRecoverySet) {
            var arrayLiteral = null;
            arrayLiteral = new TypeScript.UnaryExpression(TypeScript.NodeType.ArrayLit, this.parseArrayList(errorRecoverySet));
            return arrayLiteral;
        };
        Parser.prototype.parseTerm = function (errorRecoverySet, allowCall, typeContext, inCast) {
            var ast = null;
            var sawId = false;
            var inNew = false;
            var minChar = this.scanner.startPos;
            var limChar = this.scanner.pos;
            var parseAsLambda = false;
            var expectlambdaRParen = false;
            switch(this.currentToken.tokenId) {
                case TypeScript.TokenID.Number:
                case TypeScript.TokenID.Bool:
                case TypeScript.TokenID.Any:
                case TypeScript.TokenID.String: {
                    var tid = new TypeScript.Identifier(TypeScript.tokenTable[this.currentToken.tokenId].text);
                    if(TypeScript.hasFlag(typeContext, TypeContext.Primitive)) {
                        ast = new TypeScript.TypeReference(tid, 0);
                        sawId = true;
                    } else {
                        ast = tid;
                        sawId = true;
                    }
                    ast.minChar = minChar;
                    this.currentToken = this.scanner.scan();
                    limChar = this.scanner.lastTokenLimChar();
                    break;

                }
                case TypeScript.TokenID.This: {
                    ast = new TypeScript.AST(TypeScript.NodeType.This);
                    ast.minChar = minChar;
                    this.currentToken = this.scanner.scan();
                    limChar = this.scanner.lastTokenLimChar();
                    break;

                }
                case TypeScript.TokenID.Super: {
                    ast = new TypeScript.AST(TypeScript.NodeType.Super);
                    ast.minChar = minChar;
                    this.currentToken = this.scanner.scan();
                    limChar = this.scanner.lastTokenLimChar();
                    break;

                }
                case TypeScript.TokenID.True: {
                    ast = new TypeScript.AST(TypeScript.NodeType.True);
                    this.currentToken = this.scanner.scan();
                    ast.minChar = minChar;
                    break;

                }
                case TypeScript.TokenID.False: {
                    ast = new TypeScript.AST(TypeScript.NodeType.False);
                    this.currentToken = this.scanner.scan();
                    ast.minChar = minChar;
                    break;

                }
                case TypeScript.TokenID.Null: {
                    ast = new TypeScript.AST(TypeScript.NodeType.Null);
                    this.currentToken = this.scanner.scan();
                    ast.minChar = minChar;
                    break;

                }
                case TypeScript.TokenID.New: {
                    minChar = this.scanner.pos;
                    this.currentToken = this.scanner.scan();
                    var target = this.parseTerm(errorRecoverySet, false, TypeContext.AllSimpleTypes, inCast);
                    if(target.nodeType == TypeScript.NodeType.Error || (target.nodeType == TypeScript.NodeType.Index && (target).operand1.nodeType == TypeScript.NodeType.TypeRef)) {
                        this.reportParseError("Cannot invoke 'new' on this expression");
                    } else {
                        ast = new TypeScript.CallExpression(TypeScript.NodeType.New, target, null);
                        ast.minChar = minChar;
                        limChar = this.scanner.lastTokenLimChar();
                        inNew = true;
                    }
                    break;

                }
                case TypeScript.TokenID.Function: {
                    minChar = this.scanner.pos;
                    ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, TypeScript.Modifiers.None, null, true);
                    (ast).fncFlags |= TypeScript.FncFlags.IsFunctionExpression;
                    ast.minChar = minChar;
                    limChar = this.scanner.lastTokenLimChar();
                    ast.limChar = limChar;
                    break;

                }
            }
            if(ast == null) {
                if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                    var idText = this.currentToken.getText();
                    ast = this.createRef(idText, (this.currentToken).hasEscapeSequence, minChar);
                    sawId = true;
                    ast.minChar = minChar;
                    this.currentToken = this.scanner.scan();
                    if(this.currentToken.tokenId == TypeScript.TokenID.Question) {
                        ast.flags |= TypeScript.ASTFlags.PossibleOptionalParameter;
                    }
                    limChar = this.scanner.lastTokenLimChar();
                }
            }
            if(inCast) {
                this.checkCurrentToken(TypeScript.TokenID.GreaterThan, errorRecoverySet);
            }
            if(ast == null) {
                switch(this.currentToken.tokenId) {
                    case TypeScript.TokenID.OpenParen: {
                        minChar = this.scanner.pos;
                        var prevTokId = this.scanner.previousToken().tokenId;
                        this.currentToken = this.scanner.scan();
                        var couldBeLambda = prevTokId == TypeScript.TokenID.OpenParen || prevTokId == TypeScript.TokenID.Comma || prevTokId == TypeScript.TokenID.EqualsEquals || prevTokId == TypeScript.TokenID.Colon;
                        if(couldBeLambda && this.currentToken.tokenId == TypeScript.TokenID.CloseParen) {
                            parseAsLambda = true;
                            expectlambdaRParen = false;
                            this.currentToken = this.scanner.scan();
                        } else {
                            if(couldBeLambda && this.currentToken.tokenId == TypeScript.TokenID.DotDotDot) {
                                parseAsLambda = true;
                                expectlambdaRParen = true;
                            } else {
                                ast = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.RParen, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes, couldBeLambda);
                                limChar = this.scanner.lastTokenLimChar();
                                parseAsLambda = couldBeLambda && (ast.nodeType == TypeScript.NodeType.Name || ast.nodeType == TypeScript.NodeType.Comma) && (this.currentToken.tokenId == TypeScript.TokenID.Colon || this.currentToken.tokenId == TypeScript.TokenID.Question);
                                expectlambdaRParen = true;
                            }
                        }
                        if((ast && !parseAsLambda)) {
                            if(TypeScript.hasFlag(ast.flags, TypeScript.ASTFlags.SkipNextRParen)) {
                                ast.flags = ast.flags & (~(TypeScript.ASTFlags.SkipNextRParen));
                                break;
                            }
                            this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet);
                            ast.isParenthesized = true;
                        }
                        break;

                    }
                    case TypeScript.TokenID.NumberLiteral: {
                        var numTok = this.currentToken;
                        this.currentToken = this.scanner.scan();
                        ast = new TypeScript.NumberLiteral(numTok.value, numTok.hasEmptyFraction);
                        ast.minChar = minChar;
                        limChar = this.scanner.lastTokenLimChar();
                        break;
                    }

                    case TypeScript.TokenID.StringLiteral: {
                        ast = new TypeScript.StringLiteral(this.currentToken.getText());
                        this.currentToken = this.scanner.scan();
                        ast.minChar = minChar;
                        limChar = this.scanner.lastTokenLimChar();
                        break;

                    }
                    case TypeScript.TokenID.RegularExpressionLiteral: {
                        var rtok = this.currentToken;
                        ast = new TypeScript.RegexLiteral(rtok.regex);
                        this.currentToken = this.scanner.scan();
                        ast.minChar = minChar;
                        limChar = this.scanner.lastTokenLimChar();
                        break;
                    }

                    case TypeScript.TokenID.OpenBracket: {
                        minChar = this.scanner.startPos;
                        this.currentToken = this.scanner.scan();
                        ast = this.parseArrayLiteral(TypeScript.ErrorRecoverySet.RBrack | errorRecoverySet);
                        ast.minChar = minChar;
                        limChar = this.scanner.pos;
                        this.checkCurrentToken(TypeScript.TokenID.CloseBracket, errorRecoverySet);
                        break;

                    }
                    case TypeScript.TokenID.OpenBrace: {
                        minChar = this.scanner.startPos;
                        this.currentToken = this.scanner.scan();
                        var members = this.parseMemberList(TypeScript.ErrorRecoverySet.RCurly | errorRecoverySet);
                        this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
                        ast = new TypeScript.UnaryExpression(TypeScript.NodeType.ObjectLit, members);
                        ast.minChar = minChar;
                        limChar = this.scanner.lastTokenLimChar();
                        members.minChar = minChar;
                        members.limChar = limChar;
                        break;

                    }
                    case TypeScript.TokenID.LessThan: {
                        minChar = this.scanner.startPos;
                        this.currentToken = this.scanner.scan();
                        var term = this.parseTypeReference(TypeScript.ErrorRecoverySet.BinOp, false);
                        this.checkCurrentToken(TypeScript.TokenID.GreaterThan, errorRecoverySet);
                        ast = new TypeScript.UnaryExpression(TypeScript.NodeType.TypeAssertion, this.parseExpr(errorRecoverySet, TypeScript.OperatorPrecedence.Unary, false, TypeContext.NoTypes));
                        (ast).castTerm = term;
                        break;

                    }
                    default: {
                        if(this.prevExpr && TypeScript.hasFlag(this.prevExpr.flags, TypeScript.ASTFlags.PossibleOptionalParameter)) {
                            parseAsLambda = true;
                            ast = this.prevExpr;
                        } else {
                            this.reportParseError("Check format of expression term");
                            if(this.errorRecovery) {
                                var ident = new TypeScript.MissingIdentifier();
                                ident.minChar = minChar;
                                ident.flags |= TypeScript.ASTFlags.Error;
                                this.skip(errorRecoverySet | TypeScript.ErrorRecoverySet.Postfix);
                                if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                                    ident.setText(this.currentToken.getText(), (this.currentToken).hasEscapeSequence);
                                    this.currentToken = this.scanner.scan();
                                    limChar = this.scanner.lastTokenLimChar();
                                } else {
                                    limChar = this.scanner.lastTokenLimChar();
                                }
                                ast = ident;
                            }
                        }

                    }
                }
            }
            if(parseAsLambda) {
                if(this.currentToken.tokenId == TypeScript.TokenID.Colon || this.currentToken.tokenId == TypeScript.TokenID.Comma || this.currentToken.tokenId == TypeScript.TokenID.CloseParen || this.currentToken.tokenId == TypeScript.TokenID.DotDotDot) {
                    ast = this.parseLambdaExpr(errorRecoverySet, ast, true, expectlambdaRParen);
                    ast.minChar = minChar;
                    limChar = this.scanner.lastTokenLimChar();
                    ast.limChar = limChar;
                } else {
                    if(ast) {
                        ast.isParenthesized = true;
                    }
                }
            }
            if(sawId && (typeContext != TypeContext.NoTypes)) {
                typeContext |= TypeContext.ArraySuffix;
            }
            var postFix = this.parsePostfixOperators(errorRecoverySet, ast, allowCall, inNew, typeContext, minChar, limChar);
            if(postFix) {
                if(sawId && (postFix.nodeType == TypeScript.NodeType.Index)) {
                    var binExpr = postFix;
                    if(binExpr.operand2 == null) {
                        postFix = this.convertToTypeReference(postFix);
                    }
                }
                postFix.minChar = minChar;
                postFix.limChar = TypeScript.max(postFix.limChar, this.scanner.lastTokenLimChar());
                return postFix;
            } else {
                return new TypeScript.AST(TypeScript.NodeType.Error);
            }
        };
        Parser.prototype.parseLambdaExpr = function (errorRecoverySet, lambdaArgs, skipNextRParen, expectClosingRParen) {
            var ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, TypeScript.Modifiers.None, {
                preProcessedLambdaArgs: lambdaArgs
            }, expectClosingRParen);
            (ast).fncFlags |= TypeScript.FncFlags.IsFunctionExpression;
            (ast).fncFlags |= TypeScript.FncFlags.IsFatArrowFunction;
            if(!skipNextRParen) {
                ast.flags |= TypeScript.ASTFlags.SkipNextRParen;
            }
            ast.limChar = this.scanner.lastTokenLimChar();
            ; ;
            return ast;
        };
        Parser.prototype.parseExpr = function (errorRecoverySet, minPrecedence, allowIn, typeContext, possiblyInLambda) {
            if (typeof possiblyInLambda === "undefined") { possiblyInLambda = false; }
            var ast = null;
            var tokenInfo = TypeScript.lookupToken(this.currentToken.tokenId);
            var canAssign = true;
            var idHint = null;
            var minChar = this.scanner.startPos;
            var preComments = this.parseComments();
            var exprIsAnonLambda = false;
            if((tokenInfo != undefined) && (tokenInfo.unopNodeType != TypeScript.NodeType.None)) {
                canAssign = false;
                this.currentToken = this.scanner.scan();
                var tempExpr = this.parseExpr(TypeScript.ErrorRecoverySet.BinOp | errorRecoverySet, tokenInfo.unopPrecedence, allowIn, TypeContext.NoTypes);
                if((tokenInfo.unopNodeType == TypeScript.NodeType.Pos) && (tempExpr.nodeType == TypeScript.NodeType.NumberLit)) {
                    ast = tempExpr;
                } else {
                    if((tokenInfo.unopNodeType == TypeScript.NodeType.Neg) && (tempExpr.nodeType == TypeScript.NodeType.NumberLit)) {
                        var numLit = tempExpr;
                        numLit.value = (-numLit.value);
                        if(numLit.value == 0) {
                            numLit.isNegativeZero = true;
                        }
                        ast = tempExpr;
                    } else {
                        ast = new TypeScript.UnaryExpression(tokenInfo.unopNodeType, tempExpr);
                        ast.limChar = tempExpr.limChar;
                    }
                }
                ast.minChar = minChar;
            } else {
                ast = this.parseTerm(TypeScript.ErrorRecoverySet.BinOp | TypeScript.ErrorRecoverySet.AddOp | errorRecoverySet, true, typeContext, false);
                var id;
                var temp;
                if(ast.nodeType == TypeScript.NodeType.Name) {
                    id = ast;
                    idHint = id.actualText;
                } else {
                    if(ast.nodeType == TypeScript.NodeType.Dot) {
                        var subsumedExpr = false;
                        if(this.inferPropertiesFromThisAssignment && (this.currentToken.tokenId == TypeScript.TokenID.Colon || this.currentToken.tokenId == TypeScript.TokenID.Equals) && this.parsingClassConstructorDefinition && this.nestingLevel == this.currentClassDefinition.constructorNestingLevel && (ast).operand1.nodeType == TypeScript.NodeType.This) {
                            if((ast).operand2.nodeType == TypeScript.NodeType.Name) {
                                var op2ID = ((ast).operand2);
                                if(!this.currentClassDefinition.knownMemberNames[op2ID.actualText]) {
                                    ast = this.parseClassMemberVariableDeclaration(op2ID, ast.minChar, true, errorRecoverySet, TypeScript.Modifiers.Public);
                                    subsumedExpr = true;
                                }
                            }
                        }
                        if(!subsumedExpr) {
                            temp = ast;
                            while(temp.nodeType == TypeScript.NodeType.Dot) {
                                var binExpr = temp;
                                temp = binExpr.operand2;
                            }
                            if(temp.nodeType == TypeScript.NodeType.Name) {
                                id = temp;
                                idHint = id.actualText;
                            }
                        }
                    }
                }
                if((!this.scanner.lastTokenHadNewline()) && ((this.currentToken.tokenId == TypeScript.TokenID.PlusPlus) || (this.currentToken.tokenId == TypeScript.TokenID.MinusMinus))) {
                    canAssign = false;
                    var operand = ast;
                    ast = new TypeScript.UnaryExpression((this.currentToken.tokenId == TypeScript.TokenID.PlusPlus) ? TypeScript.NodeType.IncPost : TypeScript.NodeType.DecPost, operand);
                    ast.limChar = this.scanner.pos;
                    ast.minChar = operand.minChar;
                    this.currentToken = this.scanner.scan();
                }
            }
            for(; ; ) {
                tokenInfo = TypeScript.lookupToken(this.currentToken.tokenId);
                if((tokenInfo == undefined) || (tokenInfo.binopNodeType == TypeScript.NodeType.None)) {
                    break;
                }
                if((!allowIn) && (tokenInfo.binopNodeType == TypeScript.NodeType.In)) {
                    break;
                }
                if(tokenInfo.binopPrecedence == TypeScript.OperatorPrecedence.Assignment) {
                    if(tokenInfo.binopPrecedence < minPrecedence) {
                        break;
                    }
                    if(!canAssign) {
                        this.reportParseError("illegal assignment");
                    }
                } else {
                    if(tokenInfo.binopPrecedence <= minPrecedence) {
                        break;
                    }
                }
                if(possiblyInLambda && this.currentToken.tokenId == TypeScript.TokenID.Comma && this.scanner.getLookAheadToken().tokenId == TypeScript.TokenID.DotDotDot) {
                    exprIsAnonLambda = true;
                    canAssign = false;
                    ast = this.parseLambdaExpr(errorRecoverySet, ast, false, true);
                    break;
                }
                this.currentToken = this.scanner.scan();
                canAssign = false;
                if(tokenInfo.binopNodeType == TypeScript.NodeType.ConditionalExpression) {
                    if(possiblyInLambda && (this.currentToken.tokenId == TypeScript.TokenID.Equals || this.currentToken.tokenId == TypeScript.TokenID.Colon || this.currentToken.tokenId == TypeScript.TokenID.CloseParen || this.currentToken.tokenId == TypeScript.TokenID.Comma)) {
                        exprIsAnonLambda = true;
                        canAssign = true;
                    } else {
                        this.prevExpr = ast;
                        var whenTrue = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.Colon, TypeScript.OperatorPrecedence.Assignment, allowIn, TypeContext.NoTypes);
                        this.prevExpr = null;
                        this.checkCurrentToken(TypeScript.TokenID.Colon, errorRecoverySet | TypeScript.ErrorRecoverySet.ExprStart);
                        var whenFalse = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.BinOp, TypeScript.OperatorPrecedence.Assignment, allowIn, TypeContext.NoTypes);
                        ast = new TypeScript.ConditionalExpression(ast, whenTrue, whenFalse);
                    }
                } else {
                    var tc = TypeContext.NoTypes;
                    var binExpr2;
                    binExpr2 = new TypeScript.BinaryExpression(tokenInfo.binopNodeType, ast, this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.BinOp, tokenInfo.binopPrecedence, allowIn, TypeContext.NoTypes, possiblyInLambda));
                    if(binExpr2.operand2.nodeType == TypeScript.NodeType.FuncDecl) {
                        var funcDecl = binExpr2.operand2;
                        funcDecl.hint = idHint;
                    }
                    binExpr2.minChar = ast.minChar;
                    binExpr2.limChar = this.scanner.lastTokenLimChar();
                    idHint = null;
                    ast = binExpr2;
                }
            }
            if(canAssign) {
                ast.flags |= TypeScript.ASTFlags.Writeable;
            }
            if(!exprIsAnonLambda) {
                ast.minChar = minChar;
                ast.limChar = TypeScript.max(ast.limChar, this.scanner.lastTokenLimChar());
                ast.preComments = preComments;
                ast.postComments = this.parseCommentsForLine(this.scanner.line);
            }
            return ast;
        };
        Parser.prototype.parsePostfixOperators = function (errorRecoverySet, ast, allowCall, inNew, typeContext, lhsMinChar, lhsLimChar) {
            var count = 0;
            if(!ast) {
                ast = new TypeScript.AST(TypeScript.NodeType.EmptyExpr);
                ast.isParenthesized = true;
            }
            ast.minChar = lhsMinChar;
            ast.limChar = lhsLimChar;
            for(; ; ) {
                switch(this.currentToken.tokenId) {
                    case TypeScript.TokenID.OpenParen: {
                        if(inNew) {
                            var callExpr = ast;
                            callExpr.arguments = this.parseArgList(errorRecoverySet);
                            inNew = false;
                        } else {
                            if(!allowCall) {
                                return ast;
                            }
                            ast = new TypeScript.CallExpression(TypeScript.NodeType.Call, ast, this.parseArgList(errorRecoverySet));
                            ast.minChar = lhsMinChar;
                        }
                        ast.limChar = this.scanner.pos;
                        this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet);
                        break;

                    }
                    case TypeScript.TokenID.OpenBracket: {
                        this.currentToken = this.scanner.scan();
                        if(this.currentToken.tokenId == TypeScript.TokenID.CloseBracket) {
                            if(TypeScript.hasFlag(typeContext, TypeContext.ArraySuffix)) {
                                this.currentToken = this.scanner.scan();
                                if(ast.nodeType == TypeScript.NodeType.TypeRef) {
                                    var typeRef = ast;
                                    typeRef.arrayCount++;
                                } else {
                                    ast = new TypeScript.BinaryExpression(TypeScript.NodeType.Index, ast, null);
                                }
                                ast.limChar = this.scanner.pos;
                                break;
                            }
                        }
                        ast = new TypeScript.BinaryExpression(TypeScript.NodeType.Index, ast, this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.RBrack, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes));
                        ast.minChar = lhsMinChar;
                        ast.limChar = this.scanner.pos;
                        this.checkCurrentToken(TypeScript.TokenID.CloseBracket, errorRecoverySet);
                        break;

                    }
                    case TypeScript.TokenID.Dot: {
                        var name = null;
                        var curpos = this.scanner.pos;
                        this.currentToken = this.scanner.scan();
                        if (this.currentToken === undefined) {
                            this.currentToken = this.scanner.scan();
                            continue;
                        }
                        if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || ((!this.errorRecovery || !this.scanner.lastTokenHadNewline()) && TypeScript.convertTokToIDName(this.currentToken))) {
                            ast.flags |= TypeScript.ASTFlags.DotLHS;
                            name = this.createRef(this.currentToken.getText(), (this.currentToken).hasEscapeSequence, this.scanner.startPos);
                            name.limChar = this.scanner.pos;
                            this.currentToken = this.scanner.scan();
                        } else {
                            this.reportParseError("Expected identifier following dot");
                            if(this.errorRecovery) {
                                this.skip(errorRecoverySet);
                                ast.flags |= (TypeScript.ASTFlags.Error | TypeScript.ASTFlags.DotLHS);
                                return ast;
                            } else {
                                name = new TypeScript.MissingIdentifier();
                            }
                        }
                        ast = new TypeScript.BinaryExpression(TypeScript.NodeType.Dot, ast, name);
                        ast.minChar = lhsMinChar;
                        ast.limChar = this.scanner.lastTokenLimChar();
                        break;
                    }

                    case TypeScript.TokenID.EqualsGreaterThan: {
                        ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, TypeScript.Modifiers.None, {
                            preProcessedLambdaArgs: ast
                        }, false);
                        (ast).fncFlags |= TypeScript.FncFlags.IsFunctionExpression;
                        ast.minChar = lhsMinChar;
                        ast.limChar = this.scanner.lastTokenLimChar();
                        break;

                    }
                    default: {
                        return ast;

                    }
                }
            }
        };
        Parser.prototype.parseTry = function (tryNode, errorRecoverySet, parentModifiers) {
            var minChar = this.scanner.startPos;
            var preComments = this.parseComments();
            this.currentToken = this.scanner.scan();
            if(this.currentToken.tokenId != TypeScript.TokenID.OpenBrace) {
                this.reportParseError("Expected '{'");
                if(this.errorRecovery) {
                    var etryNode = tryNode;
                    etryNode.minChar = minChar;
                    etryNode.limChar = this.scanner.lastTokenLimChar();
                    etryNode.flags |= TypeScript.ASTFlags.Error;
                    return etryNode;
                }
            }
            tryNode.body = this.parseStatement(errorRecoverySet, TypeScript.AllowedElements.None, parentModifiers);
            tryNode.minChar = minChar;
            tryNode.limChar = tryNode.body.limChar;
            tryNode.preComments = preComments;
            tryNode.postComments = this.parseComments();
            return tryNode;
        };
        Parser.prototype.parseCatch = function (errorRecoverySet, parentModifiers) {
            var catchMinChar = this.scanner.startPos;
            var preComments = this.parseComments();
            this.currentToken = this.scanner.scan();
            this.checkCurrentToken(TypeScript.TokenID.OpenParen, errorRecoverySet | TypeScript.ErrorRecoverySet.ExprStart);
            if((this.currentToken.tokenId != TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                this.reportParseError("Expected identifier in catch header");
                if(this.errorRecovery) {
                    this.skip(errorRecoverySet);
                    var ecatch = new TypeScript.Catch(new TypeScript.VarDecl(new TypeScript.MissingIdentifier(), this.nestingLevel), new TypeScript.Statement(TypeScript.NodeType.Empty));
                    ecatch.statement.minChar = catchMinChar;
                    ecatch.statement.limChar = this.scanner.pos;
                    ecatch.minChar = this.scanner.startPos;
                    ecatch.limChar = this.scanner.pos;
                    ecatch.flags |= TypeScript.ASTFlags.Error;
                    return ecatch;
                }
            }
            var param = new TypeScript.VarDecl(TypeScript.Identifier.fromToken(this.currentToken), this.nestingLevel);
            param.id.minChar = this.scanner.startPos;
            param.id.limChar = this.scanner.pos;
            param.minChar = param.id.minChar;
            param.limChar = param.id.limChar;
            this.currentToken = this.scanner.scan();
            var statementPos = this.scanner.pos;
            this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet | TypeScript.ErrorRecoverySet.StmtStart);
            if(this.currentToken.tokenId != TypeScript.TokenID.OpenBrace) {
                this.reportParseError("Expected '{' to start catch body");
                if(this.errorRecovery) {
                    this.skip(errorRecoverySet);
                    var ecatch = new TypeScript.Catch(new TypeScript.VarDecl(new TypeScript.MissingIdentifier(), this.nestingLevel), new TypeScript.Statement(TypeScript.NodeType.Empty));
                    ecatch.statement.minChar = catchMinChar;
                    ecatch.statement.limChar = statementPos;
                    ecatch.minChar = this.scanner.startPos;
                    ecatch.limChar = this.scanner.pos;
                    ecatch.flags |= TypeScript.ASTFlags.Error;
                    return ecatch;
                }
            }
            var catchStmt = this.parseStatement(errorRecoverySet, TypeScript.AllowedElements.None, parentModifiers);
            var catchNode = new TypeScript.Catch(param, catchStmt);
            catchNode.statement.minChar = catchMinChar;
            catchNode.statement.limChar = statementPos;
            catchNode.minChar = catchMinChar;
            catchNode.limChar = catchStmt.limChar;
            catchNode.preComments = preComments;
            catchNode.postComments = this.parseComments();
            return catchNode;
        };
        Parser.prototype.parseFinally = function (errorRecoverySet, parentModifiers) {
            var finMinChar = this.scanner.startPos;
            var preComments = this.parseComments();
            this.currentToken = this.scanner.scan();
            if(this.currentToken.tokenId != TypeScript.TokenID.OpenBrace) {
                this.reportParseError("Expected '{' to start body of finally statement");
                if(this.errorRecovery) {
                    this.skip(errorRecoverySet);
                    var efin = new TypeScript.Finally(new TypeScript.Statement(TypeScript.NodeType.Empty));
                    efin.flags |= TypeScript.ASTFlags.Error;
                    efin.minChar = this.scanner.startPos;
                    efin.limChar = this.scanner.pos;
                    return efin;
                }
            }
            var finBody = this.parseStatement(errorRecoverySet, TypeScript.AllowedElements.None, parentModifiers);
            var fin = new TypeScript.Finally(finBody);
            fin.minChar = finMinChar;
            fin.limChar = fin.body.limChar;
            fin.preComments = preComments;
            fin.postComments = this.parseComments();
            return fin;
        };
        Parser.prototype.parseTryCatchFinally = function (errorRecoverySet, parentModifiers, labelList) {
            var tryPart = new TypeScript.Try(null);
            var tryMinChar = this.scanner.startPos;
            this.pushStmt(tryPart, labelList);
            this.parseTry(tryPart, errorRecoverySet | TypeScript.ErrorRecoverySet.Catch, parentModifiers);
            this.popStmt();
            var tc = null;
            var tf = null;
            if(this.currentToken.tokenId == TypeScript.TokenID.Catch) {
                var catchPart = this.parseCatch(errorRecoverySet | TypeScript.ErrorRecoverySet.Catch, parentModifiers);
                tc = new TypeScript.TryCatch(tryPart, catchPart);
                tc.minChar = tryPart.minChar;
                tc.limChar = catchPart.limChar;
            }
            if(this.currentToken.tokenId != TypeScript.TokenID.Finally) {
                if(tc == null) {
                    this.reportParseError("try with neither catch nor finally");
                    if(this.errorRecovery) {
                        var etf = new TypeScript.TryFinally(tryPart, new TypeScript.Finally(new TypeScript.AST(TypeScript.NodeType.Empty)));
                        etf.flags |= TypeScript.ASTFlags.Error;
                        etf.minChar = this.scanner.startPos;
                        etf.limChar = this.scanner.pos;
                        return etf;
                    }
                    return new TypeScript.TryFinally(tryPart, new TypeScript.Finally(new TypeScript.AST(TypeScript.NodeType.Empty)));
                } else {
                    return tc;
                }
            } else {
                if(tc) {
                    tryPart = tc;
                }
                var finallyPart = this.parseFinally(errorRecoverySet, parentModifiers);
                tf = new TypeScript.TryFinally(tryPart, finallyPart);
                tf.minChar = tryMinChar;
                tf.limChar = finallyPart.limChar;
                return tf;
            }
        };
        Parser.prototype.parseStatement = function (errorRecoverySet, allowedElements, parentModifiers) {
            var ast = null;
            var labelList = null;
            var astList = null;
            var temp;
            var modifiers = TypeScript.Modifiers.None;
            var minChar = this.scanner.startPos;
            var forInOk = false;
            var needTerminator = false;
            var fnOrVar = null;
            var preComments = this.parseComments();
            this.state = ParseState.StartStatement;
            function isAmbient() {
                return TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient) || TypeScript.hasFlag(parentModifiers, TypeScript.Modifiers.Ambient);
            }
            function mayNotBeExported() {
                if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                    this.reportError("Statement may not be exported");
                }
            }
            for(; ; ) {
                switch(this.currentToken.tokenId) {
                    case TypeScript.TokenID.EndOfFile: {
                        ast = new TypeScript.AST(TypeScript.NodeType.Error);
                        ast.minChar = minChar;
                        ast.limChar = this.scanner.pos;
                        break;

                    }
                    case TypeScript.TokenID.Function: {
                        if(this.parsingDeclareFile || isAmbient() || this.ambientModule) {
                            this.currentToken = this.scanner.scan();
                            fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, modifiers, true, false);
                            if(fnOrVar.nodeType == TypeScript.NodeType.VarDecl) {
                                this.reportParseError("function keyword can only introduce function declaration");
                            } else {
                                if((fnOrVar.nodeType == TypeScript.NodeType.FuncDecl) && ((fnOrVar).fncFlags , TypeScript.FncFlags.IsFatArrowFunction)) {
                                    needTerminator = true;
                                }
                            }
                            ast = fnOrVar;
                            if(this.parsingDeclareFile || this.ambientModule && ast.nodeType == TypeScript.NodeType.FuncDecl) {
                                (ast).fncFlags |= TypeScript.FncFlags.Exported;
                            }
                        } else {
                            ast = this.parseFncDecl(errorRecoverySet, true, false, false, null, false, false, isAmbient(), modifiers, null, true);
                            if(TypeScript.hasFlag((ast).fncFlags, TypeScript.FncFlags.IsFatArrowFunction)) {
                                needTerminator = true;
                            }
                            if(this.ambientModule) {
                                this.reportParseError("function declaration not permitted within ambient module");
                            }
                            if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                                (ast).fncFlags |= TypeScript.FncFlags.Exported;
                            }
                        }
                        break;

                    }
                    case TypeScript.TokenID.Module: {
                        if((allowedElements & TypeScript.AllowedElements.ModuleDeclarations) == TypeScript.AllowedElements.None) {
                            this.reportParseError("module not allowed in this context");
                            this.currentToken = this.scanner.scan();
                            ast = new TypeScript.AST(TypeScript.NodeType.Error);
                            ast.minChar = minChar;
                            ast.limChar = this.scanner.lastTokenLimChar();
                        } else {
                            ast = this.parseModuleDecl(errorRecoverySet, modifiers, preComments);
                            preComments = null;
                        }
                        break;

                    }
                    case TypeScript.TokenID.Import: {
                        if((allowedElements & TypeScript.AllowedElements.ModuleDeclarations) == TypeScript.AllowedElements.None) {
                            this.reportParseError("module not allowed in this context");
                            this.currentToken = this.scanner.scan();
                            ast = new TypeScript.AST(TypeScript.NodeType.Error);
                            ast.minChar = minChar;
                            ast.limChar = this.scanner.lastTokenLimChar();
                        } else {
                            if(TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                                this.reportParseError("export keyword not permitted on import declaration");
                            }
                            ast = this.parseImportDeclaration(errorRecoverySet, modifiers);
                            needTerminator = true;
                        }
                        break;

                    }
                    case TypeScript.TokenID.Export: {
                        if((allowedElements & TypeScript.AllowedElements.ModuleDeclarations) == TypeScript.AllowedElements.None) {
                            this.reportParseError("'export' statements are only allowed at the global and module levels");
                            this.currentToken = this.scanner.scan();
                            ast = new TypeScript.AST(TypeScript.NodeType.Error);
                            ast.minChar = minChar;
                            ast.limChar = this.scanner.lastTokenLimChar();
                        }
                        if(this.topLevel) {
                            this.hasTopLevelImportOrExport = true;
                        }
                        modifiers |= TypeScript.Modifiers.Exported;
                        this.currentToken = this.scanner.scan();
                        break;

                    }
                    case TypeScript.TokenID.Private: {
                        modifiers |= TypeScript.Modifiers.Private;
                        this.currentToken = this.scanner.scan();
                        if(this.parsingClassConstructorDefinition) {
                            if(!this.inferPropertiesFromThisAssignment) {
                                this.reportParseError("Property declarations are not permitted within constructor bodies");
                            }
                            minChar = this.scanner.pos;
                            if(this.inferPropertiesFromThisAssignment && (this.currentToken.tokenId != TypeScript.TokenID.This || (this.currentToken = this.scanner.scan()).tokenId != TypeScript.TokenID.Dot)) {
                                this.reportParseError("Expected 'this.' for property declaration");
                                this.currentToken = this.scanner.scan();
                                ast = new TypeScript.AST(TypeScript.NodeType.Error);
                                ast.minChar = minChar;
                                ast.limChar = this.scanner.lastTokenLimChar();
                            } else {
                                this.currentToken = this.scanner.scan();
                                var id = TypeScript.Identifier.fromToken(this.currentToken);
                                id.minChar = this.scanner.startPos;
                                id.limChar = this.scanner.pos;
                                this.currentToken = this.scanner.scan();
                                ast = this.parseClassMemberVariableDeclaration(id, minChar, this.parsingClassConstructorDefinition, errorRecoverySet, modifiers);
                            }
                        } else {
                            if(this.currentToken.tokenId != TypeScript.TokenID.Interface) {
                                if(this.currentToken.tokenId == TypeScript.TokenID.Get) {
                                    this.prevIDTok = this.currentToken;
                                    this.currentToken = this.scanner.scan();
                                    if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                                        this.reportParseError("Property accessors are only available when targeting ES5 or greater");
                                    }
                                    if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                                        modifiers |= TypeScript.Modifiers.Getter;
                                        this.prevIDTok = null;
                                    }
                                } else {
                                    if(this.currentToken.tokenId == TypeScript.TokenID.Set) {
                                        this.prevIDTok = this.currentToken;
                                        this.currentToken = this.scanner.scan();
                                        if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                                            this.reportParseError("Property accessors are only available when targeting ES5 or greater");
                                        }
                                        if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                                            modifiers |= TypeScript.Modifiers.Setter;
                                            this.prevIDTok = null;
                                        }
                                    }
                                }
                                fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, modifiers, isAmbient(), false);
                                if((fnOrVar.nodeType == TypeScript.NodeType.VarDecl) || ((fnOrVar.nodeType == TypeScript.NodeType.FuncDecl) && (TypeScript.hasFlag((fnOrVar).fncFlags, TypeScript.FncFlags.IsFatArrowFunction)))) {
                                    needTerminator = true;
                                }
                                ast = fnOrVar;
                            }
                        }
                        break;

                    }
                    case TypeScript.TokenID.Public: {
                        if(this.parsingClassConstructorDefinition) {
                            if(!this.inferPropertiesFromThisAssignment) {
                                this.reportParseError("Property declarations are not permitted within constructor bodies");
                            }
                            this.currentToken = this.scanner.scan();
                            minChar = this.scanner.pos;
                            modifiers |= TypeScript.Modifiers.Public;
                            if(this.inferPropertiesFromThisAssignment && (this.currentToken.tokenId != TypeScript.TokenID.This || (this.currentToken = this.scanner.scan()).tokenId != TypeScript.TokenID.Dot)) {
                                this.reportParseError("Expected 'this.' for property declaration");
                                this.currentToken = this.scanner.scan();
                                ast = new TypeScript.AST(TypeScript.NodeType.Error);
                                ast.minChar = minChar;
                                ast.limChar = this.scanner.lastTokenLimChar();
                            } else {
                                this.currentToken = this.scanner.scan();
                                var id = TypeScript.Identifier.fromToken(this.currentToken);
                                id.minChar = this.scanner.startPos;
                                id.limChar = this.scanner.pos;
                                this.currentToken = this.scanner.scan();
                                ast = this.parseClassMemberVariableDeclaration(id, minChar, this.parsingClassConstructorDefinition, errorRecoverySet, modifiers);
                            }
                        } else {
                            if((allowedElements & TypeScript.AllowedElements.Properties) == TypeScript.AllowedElements.None) {
                                this.reportParseError("'property' statements are only allowed within classes");
                                this.currentToken = this.scanner.scan();
                                ast = new TypeScript.AST(TypeScript.NodeType.Error);
                                ast.minChar = minChar;
                                ast.limChar = this.scanner.lastTokenLimChar();
                            } else {
                                modifiers |= TypeScript.Modifiers.Public;
                                this.currentToken = this.scanner.scan();
                                if(this.currentToken.tokenId == TypeScript.TokenID.Get) {
                                    this.prevIDTok = this.currentToken;
                                    this.currentToken = this.scanner.scan();
                                    if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                                        this.reportParseError("Property accessors are only available when targeting ES5 or greater");
                                    }
                                    if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                                        modifiers |= TypeScript.Modifiers.Getter;
                                        this.prevIDTok = null;
                                    }
                                } else {
                                    if(this.currentToken.tokenId == TypeScript.TokenID.Set) {
                                        this.prevIDTok = this.currentToken;
                                        this.currentToken = this.scanner.scan();
                                        if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                                            this.reportParseError("Property accessors are only available when targeting ES5 or greater");
                                        }
                                        if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                                            modifiers |= TypeScript.Modifiers.Setter;
                                            this.prevIDTok = null;
                                        }
                                    }
                                }
                                fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, modifiers, isAmbient(), false);
                                if((fnOrVar.nodeType == TypeScript.NodeType.VarDecl) || ((fnOrVar.nodeType == TypeScript.NodeType.FuncDecl) && TypeScript.hasFlag((fnOrVar).fncFlags, TypeScript.FncFlags.IsFatArrowFunction))) {
                                    needTerminator = true;
                                }
                                ast = fnOrVar;
                            }
                        }
                        break;

                    }
                    case TypeScript.TokenID.Declare: {
                        if(!(allowedElements & TypeScript.AllowedElements.AmbientDeclarations)) {
                            this.reportParseError("Ambient declarations are only allowed at the top-level or module scopes");
                        }
                        if(!this.parsingDeclareFile && TypeScript.hasFlag(parentModifiers, TypeScript.Modifiers.Ambient)) {
                            this.reportParseError("Duplicate ambient declaration in this context. (Is the enclosing module or class already ambient?)");
                        }
                        modifiers |= TypeScript.Modifiers.Ambient;
                        this.currentToken = this.scanner.scan();
                        break;

                    }
                    case TypeScript.TokenID.Class: {
                        if((allowedElements & TypeScript.AllowedElements.ClassDeclarations) == TypeScript.AllowedElements.None) {
                            this.reportParseError("class not allowed in this context");
                            this.currentToken = this.scanner.scan();
                            ast = new TypeScript.AST(TypeScript.NodeType.Error);
                            ast.minChar = minChar;
                            ast.limChar = this.scanner.lastTokenLimChar();
                        } else {
                            ast = this.parseClassDecl(errorRecoverySet, minChar, modifiers);
                        }
                        break;

                    }
                    case TypeScript.TokenID.Interface: {
                        if((allowedElements & TypeScript.AllowedElements.InterfaceDeclarations) == TypeScript.AllowedElements.None) {
                            this.reportParseError("interface not allowed in this context");
                            this.currentToken = this.scanner.scan();
                            ast = new TypeScript.AST(TypeScript.NodeType.Error);
                            ast.minChar = minChar;
                            ast.limChar = this.scanner.lastTokenLimChar();
                        } else {
                            ast = this.parseInterfaceDecl(errorRecoverySet, modifiers);
                        }
                        break;

                    }
                    case TypeScript.TokenID.Var: {
                        var declAst = this.parseVariableDeclaration(errorRecoverySet | TypeScript.ErrorRecoverySet.StmtStart, modifiers, true, false);
                        if(declAst.nodeType == TypeScript.NodeType.VarDecl) {
                            ast = declAst;
                        } else {
                            ast = new TypeScript.Block(declAst, false);
                        }
                        needTerminator = true;
                        break;

                    }
                    case TypeScript.TokenID.Static: {
                        if(this.currentClassDecl == null) {
                            this.reportParseError("Statics may only be class members");
                        }
                        mayNotBeExported();
                        modifiers |= TypeScript.Modifiers.Public;
                        this.currentToken = this.scanner.scan();
                        if(this.currentToken.tokenId == TypeScript.TokenID.Get) {
                            this.prevIDTok = this.currentToken;
                            this.currentToken = this.scanner.scan();
                            if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                                this.reportParseError("Property accessors are only available when targeting ES5 or greater");
                            }
                            if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                                modifiers |= TypeScript.Modifiers.Getter;
                                this.prevIDTok = null;
                            }
                        } else {
                            if(this.currentToken.tokenId == TypeScript.TokenID.Set) {
                                this.currentToken = this.scanner.scan();
                                if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                                    this.reportParseError("Property accessors are only available when targeting ES5 or greater");
                                }
                                if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) || TypeScript.convertTokToID(this.currentToken, this.strictMode)) {
                                    modifiers |= TypeScript.Modifiers.Setter;
                                }
                            }
                        }
                        if(isAmbient()) {
                            modifiers |= TypeScript.Modifiers.Ambient;
                        }
                        fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, modifiers, this.parsingDeclareFile || (modifiers & TypeScript.Modifiers.Ambient) != TypeScript.Modifiers.None, true);
                        var staticsList = this.topStaticsList();
                        if(staticsList && fnOrVar.nodeType == TypeScript.NodeType.VarDecl) {
                            staticsList.append(fnOrVar);
                        }
                        if(fnOrVar.nodeType == TypeScript.NodeType.VarDecl || ((fnOrVar.nodeType == TypeScript.NodeType.FuncDecl) && TypeScript.hasFlag((fnOrVar).fncFlags, TypeScript.FncFlags.IsFatArrowFunction))) {
                            needTerminator = true;
                        }
                        ast = fnOrVar;
                        break;

                    }
                    case TypeScript.TokenID.For: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("syntax error: for statement does not take modifiers");
                        }
                        minChar = this.scanner.startPos;
                        this.checkNextToken(TypeScript.TokenID.OpenParen, errorRecoverySet | TypeScript.ErrorRecoverySet.ExprStart | TypeScript.ErrorRecoverySet.Var);
                        this.state = ParseState.ForInit;
                        forInOk = true;
                        switch(this.currentToken.tokenId) {
                            case TypeScript.TokenID.Var: {
                                temp = this.parseVariableDeclaration(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon | TypeScript.ErrorRecoverySet.In, TypeScript.Modifiers.None, false, false);
                                break;

                            }
                            case TypeScript.TokenID.Semicolon: {
                                temp = null;
                                this.state = ParseState.ForCondStart;
                                break;

                            }
                            default: {
                                temp = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon | TypeScript.ErrorRecoverySet.In, TypeScript.OperatorPrecedence.None, false, TypeContext.NoTypes);
                                break;

                            }
                        }
                        this.state = ParseState.ForInitAfterVar;
                        if(this.currentToken.tokenId == TypeScript.TokenID.In) {
                            if((temp == null) || (!forInOk)) {
                                this.reportParseError("malformed for statement");
                                if(this.errorRecovery) {
                                    this.skip(errorRecoverySet | TypeScript.ErrorRecoverySet.StmtStart);
                                    ast = new TypeScript.AST(TypeScript.NodeType.Empty);
                                    ast.flags |= TypeScript.ASTFlags.Error;
                                }
                            } else {
                                this.currentToken = this.scanner.scan();
                                var forInStmt = new TypeScript.ForInStatement(temp, this.parseExpr(TypeScript.ErrorRecoverySet.RParen | errorRecoverySet, TypeScript.OperatorPrecedence.Comma, false, TypeContext.NoTypes));
                                forInStmt.limChar = this.scanner.pos;
                                forInStmt.statement.minChar = minChar;
                                forInStmt.statement.limChar = this.scanner.pos;
                                this.checkCurrentToken(TypeScript.TokenID.CloseParen, TypeScript.ErrorRecoverySet.StmtStart | errorRecoverySet);
                                this.pushStmt(forInStmt, labelList);
                                forInStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);
                                this.popStmt();
                                forInStmt.minChar = minChar;
                                ast = forInStmt;
                            }
                        } else {
                            var forStmt = new TypeScript.ForStatement(temp);
                            forStmt.minChar = minChar;
                            this.checkCurrentToken(TypeScript.TokenID.Semicolon, errorRecoverySet);
                            if(this.currentToken.tokenId == TypeScript.TokenID.Semicolon) {
                                forStmt.cond = null;
                            } else {
                                forStmt.cond = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon | TypeScript.ErrorRecoverySet.RParen, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes);
                                if(this.currentToken.tokenId != TypeScript.TokenID.Semicolon) {
                                    this.skip(errorRecoverySet | TypeScript.ErrorRecoverySet.StmtStart);
                                    ast = forStmt;
                                    ast.flags |= TypeScript.ASTFlags.Error;
                                }
                            }
                            this.currentToken = this.scanner.scan();
                            if(this.currentToken.tokenId == TypeScript.TokenID.CloseParen) {
                                forStmt.incr = null;
                            } else {
                                forStmt.incr = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon | TypeScript.ErrorRecoverySet.RParen, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes);
                            }
                            this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet | TypeScript.ErrorRecoverySet.LCurly);
                            this.pushStmt(forStmt, labelList);
                            forStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);
                            this.popStmt();
                            forStmt.limChar = forStmt.body.limChar;
                            ast = forStmt;
                        }
                        break;

                    }
                    case TypeScript.TokenID.With: {
 {
                            if(TypeScript.codeGenTarget < TypeScript.CodeGenTarget.ES5) {
                                this.reportParseError("'with' statements are only available in ES5 codegen mode or better");
                            }
                            if(this.strictMode) {
                                this.reportParseError("'with' statements are not available in strict mode");
                            }
                            mayNotBeExported();
                            if(modifiers != TypeScript.Modifiers.None) {
                                this.reportParseError("'with' statement does not take modifiers");
                            }
                            minChar = this.scanner.startPos;
                            this.checkNextToken(TypeScript.TokenID.OpenParen, errorRecoverySet | TypeScript.ErrorRecoverySet.ExprStart | TypeScript.ErrorRecoverySet.Var);
                            var expr = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.Colon, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes);
                            this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet | TypeScript.ErrorRecoverySet.LCurly);
                            var withStmt = new TypeScript.WithStatement(expr);
                            withStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);
                            withStmt.minChar = minChar;
                            withStmt.limChar = withStmt.body.limChar;
                            ast = withStmt;
                        }
                        break;

                    }
                    case TypeScript.TokenID.Switch: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("'switch' statement does not take modifiers");
                        }
                        this.checkNextToken(TypeScript.TokenID.OpenParen, errorRecoverySet | TypeScript.ErrorRecoverySet.ExprStart);
                        var switchStmt = new TypeScript.SwitchStatement(this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.RParen, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes));
                        switchStmt.statement.minChar = minChar;
                        switchStmt.statement.limChar = this.scanner.pos;
                        this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet | TypeScript.ErrorRecoverySet.LCurly);
                        var caseListMinChar = this.scanner.startPos;
                        this.checkCurrentToken(TypeScript.TokenID.OpenBrace, errorRecoverySet | TypeScript.ErrorRecoverySet.SCase);
                        switchStmt.defaultCase = null;
                        switchStmt.caseList = new TypeScript.ASTList();
                        var caseStmt = null;
                        this.pushStmt(switchStmt, labelList);
                        for(; ; ) {
                            if((this.currentToken.tokenId == TypeScript.TokenID.Case) || (this.currentToken.tokenId == TypeScript.TokenID.Default)) {
                                var isDefault = (this.currentToken.tokenId == TypeScript.TokenID.Default);
                                caseStmt = new TypeScript.CaseStatement();
                                caseStmt.minChar = this.scanner.startPos;
                                this.currentToken = this.scanner.scan();
                                if(isDefault) {
                                    switchStmt.defaultCase = caseStmt;
                                } else {
                                    caseStmt.expr = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.Colon, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes);
                                }
                                this.checkCurrentToken(TypeScript.TokenID.Colon, errorRecoverySet | TypeScript.ErrorRecoverySet.StmtStart);
                                caseStmt.body = new TypeScript.ASTList();
                                this.parseStatementList(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly, caseStmt.body, false, true, allowedElements, modifiers);
                                caseStmt.limChar = caseStmt.body.limChar;
                                switchStmt.caseList.append(caseStmt);
                            } else {
                                break;
                            }
                        }
                        switchStmt.caseList.minChar = caseListMinChar;
                        switchStmt.caseList.limChar = this.scanner.pos;
                        switchStmt.limChar = switchStmt.caseList.limChar;
                        this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
                        this.popStmt();
                        ast = switchStmt;
                        break;
                    }

                    case TypeScript.TokenID.While: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("'while' statement does not take modifiers");
                        }
                        minChar = this.scanner.startPos;
                        this.checkNextToken(TypeScript.TokenID.OpenParen, TypeScript.ErrorRecoverySet.ExprStart | errorRecoverySet);
                        var whileStmt = new TypeScript.WhileStatement(this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.RParen, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes));
                        whileStmt.minChar = minChar;
                        this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet | TypeScript.ErrorRecoverySet.StmtStart);
                        this.pushStmt(whileStmt, labelList);
                        whileStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);
                        whileStmt.limChar = whileStmt.body.limChar;
                        this.popStmt();
                        ast = whileStmt;
                        break;
                    }

                    case TypeScript.TokenID.Do: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("'do' statement does not take modifiers");
                        }
                        minChar = this.scanner.startPos;
                        this.currentToken = this.scanner.scan();
                        var doStmt = new TypeScript.DoWhileStatement();
                        doStmt.minChar = minChar;
                        this.pushStmt(doStmt, labelList);
                        doStmt.body = this.parseStatement(errorRecoverySet | TypeScript.ErrorRecoverySet.While, allowedElements, parentModifiers);
                        this.popStmt();
                        doStmt.whileAST = new TypeScript.Identifier("while");
                        doStmt.whileAST.minChar = this.scanner.startPos;
                        this.checkCurrentToken(TypeScript.TokenID.While, errorRecoverySet | TypeScript.ErrorRecoverySet.LParen);
                        doStmt.whileAST.limChar = doStmt.whileAST.minChar + 5;
                        this.checkCurrentToken(TypeScript.TokenID.OpenParen, errorRecoverySet | TypeScript.ErrorRecoverySet.ExprStart);
                        doStmt.cond = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.RParen, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes);
                        doStmt.limChar = this.scanner.pos;
                        this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet);
                        ast = doStmt;
                        if(this.currentToken.tokenId == TypeScript.TokenID.Semicolon) {
                            this.currentToken = this.scanner.scan();
                        }
                        break;
                    }

                    case TypeScript.TokenID.If: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("if statement does not take modifiers");
                        }
                        minChar = this.scanner.startPos;
                        this.checkNextToken(TypeScript.TokenID.OpenParen, errorRecoverySet | TypeScript.ErrorRecoverySet.ExprStart);
                        var ifStmt = new TypeScript.IfStatement(this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.LParen, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes));
                        ifStmt.minChar = minChar;
                        ifStmt.statement.minChar = minChar;
                        ifStmt.statement.limChar = this.scanner.pos;
                        this.checkCurrentToken(TypeScript.TokenID.CloseParen, errorRecoverySet | TypeScript.ErrorRecoverySet.StmtStart);
                        this.pushStmt(ifStmt, labelList);
                        ifStmt.thenBod = this.parseStatement(TypeScript.ErrorRecoverySet.Else | errorRecoverySet, allowedElements, parentModifiers);
                        ifStmt.limChar = ifStmt.thenBod.limChar;
                        if(this.currentToken.tokenId == TypeScript.TokenID.Else) {
                            this.currentToken = this.scanner.scan();
                            ifStmt.elseBod = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);
                            ifStmt.limChar = ifStmt.elseBod.limChar;
                        }
                        this.popStmt();
                        ast = ifStmt;
                        break;
                    }

                    case TypeScript.TokenID.Try: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("try statement does not take modifiers");
                        }
                        minChar = this.scanner.startPos;
                        ast = this.parseTryCatchFinally(errorRecoverySet, parentModifiers, labelList);
                        break;
                    }

                    case TypeScript.TokenID.OpenBrace: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("block does not take modifiers");
                        }
                        minChar = this.scanner.startPos;
                        this.currentToken = this.scanner.scan();
                        var block = new TypeScript.Block(new TypeScript.ASTList(), true);
                        this.pushStmt(block, labelList);
                        this.parseStatementList(errorRecoverySet | TypeScript.ErrorRecoverySet.RCurly, block.statements, false, false, TypeScript.AllowedElements.None, modifiers);
                        this.popStmt();
                        block.statements.minChar = minChar;
                        block.statements.limChar = this.scanner.pos;
                        block.minChar = block.statements.minChar;
                        block.limChar = block.statements.limChar;
                        this.checkCurrentToken(TypeScript.TokenID.CloseBrace, errorRecoverySet);
                        ast = block;
                        break;
                    }

                    case TypeScript.TokenID.Semicolon: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("modifier can not appear here");
                        }
                        ast = new TypeScript.AST(TypeScript.NodeType.Empty);
                        this.currentToken = this.scanner.scan();
                        break;

                    }
                    case TypeScript.TokenID.Break:
                    case TypeScript.TokenID.Continue: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("modifiers can not appear before jump statement");
                        }
                        var jump = new TypeScript.Jump((this.currentToken.tokenId == TypeScript.TokenID.Break) ? TypeScript.NodeType.Break : TypeScript.NodeType.Continue);
                        this.currentToken = this.scanner.scan();
                        if((this.currentToken.tokenId == TypeScript.TokenID.Identifier) && (!this.scanner.lastTokenHadNewline())) {
                            jump.target = this.currentToken.getText();
                            this.currentToken = this.scanner.scan();
                        }
                        this.resolveJumpTarget(jump);
                        ast = jump;
                        needTerminator = true;
                        break;
                    }

                    case TypeScript.TokenID.Return: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("modifiers can not appear before return statement");
                        }
                        if(!this.inFunction) {
                            this.reportParseError("return statement outside of function body");
                        }
                        minChar = this.scanner.startPos;
                        this.currentToken = this.scanner.scan();
                        var retStmt = new TypeScript.ReturnStatement();
                        retStmt.minChar = minChar;
                        if((this.currentToken.tokenId != TypeScript.TokenID.Semicolon) && (this.currentToken.tokenId != TypeScript.TokenID.CloseBrace) && (!(this.scanner.lastTokenHadNewline()))) {
                            retStmt.returnExpression = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes);
                        }
                        needTerminator = true;
                        retStmt.limChar = this.scanner.lastTokenLimChar();
                        ast = retStmt;
                        break;
                    }

                    case TypeScript.TokenID.Throw: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("modifiers can not appear before a throw statement");
                        }
                        minChar = this.scanner.startPos;
                        this.currentToken = this.scanner.scan();
                        if((this.currentToken.tokenId != TypeScript.TokenID.Semicolon) && (this.currentToken.tokenId != TypeScript.TokenID.CloseBrace) && (!(this.scanner.lastTokenHadNewline()))) {
                            temp = this.parseExpr(errorRecoverySet | TypeScript.ErrorRecoverySet.SColon, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes);
                        } else {
                            this.reportParseError("throw with no target");
                            temp = null;
                        }
                        ast = new TypeScript.UnaryExpression(TypeScript.NodeType.Throw, temp);
                        ast.limChar = this.scanner.lastTokenLimChar();
                        needTerminator = true;
                        break;

                    }
                    case TypeScript.TokenID.Enum: {
                        this.currentToken = this.scanner.scan();
                        ast = this.parseEnumDecl(errorRecoverySet, modifiers);
                        ast.minChar = minChar;
                        ast.limChar = this.scanner.lastTokenLimChar();
                        if(this.parsingDeclareFile || this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Ambient)) {
                            (ast).modFlags |= TypeScript.ModuleFlags.Ambient;
                        }
                        if(this.parsingDeclareFile || this.ambientModule || TypeScript.hasFlag(modifiers, TypeScript.Modifiers.Exported)) {
                            (ast).modFlags |= TypeScript.ModuleFlags.Exported;
                        }
                        break;

                    }
                    case TypeScript.TokenID.Debugger: {
                        mayNotBeExported();
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("modifiers can not appear before debugger statement");
                        }
                        minChar = this.scanner.startPos;
                        this.currentToken = this.scanner.scan();
                        var debuggerStmt = new TypeScript.DebuggerStatement();
                        debuggerStmt.minChar = minChar;
                        needTerminator = true;
                        debuggerStmt.limChar = this.scanner.lastTokenLimChar();
                        ast = debuggerStmt;
                        break;

                    }
                    default: {
                        if(modifiers != TypeScript.Modifiers.None) {
                            this.reportParseError("modifiers can not appear before an expression statement or label");
                        }
                        minChar = this.scanner.startPos;
                        var svPos = this.scanner.pos;
                        temp = this.parseExpr(TypeScript.ErrorRecoverySet.Colon | TypeScript.ErrorRecoverySet.StmtStart | errorRecoverySet, TypeScript.OperatorPrecedence.None, true, TypeContext.NoTypes);
                        if(this.scanner.pos == svPos) {
                            this.currentToken = this.scanner.scan();
                            ast = temp;
                        } else {
                            if((this.currentToken.tokenId == TypeScript.TokenID.Colon) && (!this.scanner.lastTokenHadNewline()) && temp && (temp.nodeType == TypeScript.NodeType.Name)) {
                                if(labelList == null) {
                                    labelList = new TypeScript.ASTList();
                                }
                                labelList.append(new TypeScript.Label(temp));
                                this.currentToken = this.scanner.scan();
                            } else {
                                ast = temp;
                                needTerminator = true;
                            }
                        }

                    }
                }
                if(ast) {
                    break;
                }
            }
            if(needTerminator) {
                switch(this.currentToken.tokenId) {
                    case TypeScript.TokenID.Semicolon: {
                        this.currentToken = this.scanner.scan();
                        ast.flags |= TypeScript.ASTFlags.ExplicitSemicolon;
                        break;

                    }
                    case TypeScript.TokenID.EndOfFile: {
                        ast.limChar = this.scanner.pos;

                    }
                    case TypeScript.TokenID.CloseBrace: {
                        ast.flags |= TypeScript.ASTFlags.AutomaticSemicolon;
                        if(this.style_requireSemi) {
                            this.reportParseStyleError("no automatic semicolon");
                        }
                        break;

                    }
                    default: {
                        if(!this.scanner.lastTokenHadNewline()) {
                            this.reportParseError("Expected ';'");
                        } else {
                            ast.flags |= TypeScript.ASTFlags.AutomaticSemicolon;
                            if(this.style_requireSemi) {
                                this.reportParseStyleError("no automatic semicolon");
                            }
                        }
                        break;

                    }
                }
            }
            if(labelList) {
                ast = new TypeScript.LabeledStatement(labelList, ast);
            }
            ast.minChar = minChar;
            ast.limChar = TypeScript.max(ast.limChar, this.scanner.lastTokenLimChar());
            if(preComments) {
                ast.preComments = preComments;
            }
            if(this.ambientModule && (!this.okAmbientModuleMember(ast))) {
                this.reportParseError("statement not permitted within ambient module");
            }
            ast.flags |= TypeScript.ASTFlags.IsStatement;
            return ast;
        };
        Parser.prototype.okAmbientModuleMember = function (ast) {
            var nt = ast.nodeType;
            return (nt == TypeScript.NodeType.ClassDeclaration) || (nt == TypeScript.NodeType.ImportDeclaration) || (nt == TypeScript.NodeType.InterfaceDeclaration) || (nt == TypeScript.NodeType.ModuleDeclaration) || (nt == TypeScript.NodeType.Empty) || (nt == TypeScript.NodeType.VarDecl) || ((nt == TypeScript.NodeType.Block) && !(ast).isStatementBlock) || ((nt == TypeScript.NodeType.FuncDecl) && ((ast).isMethod()));
        };
        Parser.prototype.parseStatementList = function (errorRecoverySet, statements, sourceElms, noLeadingCase, allowedElements, parentModifiers) {
            var directivePrologue = sourceElms;
            statements.minChar = this.scanner.startPos;
            var limChar = this.scanner.pos;
            var innerStmts = (allowedElements & TypeScript.AllowedElements.ModuleDeclarations) == TypeScript.AllowedElements.None;
            var classNope = (allowedElements & TypeScript.AllowedElements.ClassDeclarations) == TypeScript.AllowedElements.None;
            errorRecoverySet |= TypeScript.ErrorRecoverySet.TypeScriptS | TypeScript.ErrorRecoverySet.RCurly;
            this.state = ParseState.StartStatementList;
            var oldStrictMode = this.strictMode;
            this.nestingLevel++;
            for(; ; ) {
                if((this.currentToken.tokenId == TypeScript.TokenID.CloseBrace) || (noLeadingCase && ((this.currentToken.tokenId == TypeScript.TokenID.Case) || (this.currentToken.tokenId == TypeScript.TokenID.Default))) || (innerStmts && (this.currentToken.tokenId == TypeScript.TokenID.Export)) || (classNope && (this.currentToken.tokenId == TypeScript.TokenID.Class)) || (this.currentToken.tokenId == TypeScript.TokenID.EndOfFile)) {
                    this.state = ParseState.EndStmtList;
                    statements.limChar = limChar;
                    if(statements.members.length == 0) {
                        statements.preComments = this.parseComments();
                    } else {
                        statements.postComments = this.parseComments();
                    }
                    this.strictMode = oldStrictMode;
                    this.nestingLevel--;
                    return;
                }
                var stmt = this.parseStatement(errorRecoverySet & (~(TypeScript.ErrorRecoverySet.Else | TypeScript.ErrorRecoverySet.RParen | TypeScript.ErrorRecoverySet.Catch | TypeScript.ErrorRecoverySet.Colon)), allowedElements, parentModifiers);
                if(stmt) {
                    stmt.postComments = this.combineComments(stmt.postComments, this.parseCommentsForLine(this.scanner.prevLine));
                    statements.append(stmt);
                    limChar = stmt.limChar;
                    if(directivePrologue) {
                        if(stmt.nodeType == TypeScript.NodeType.QString) {
                            var qstring = stmt;
                            if(qstring.text == "\"use strict\"") {
                                statements.flags |= TypeScript.ASTFlags.StrictMode;
                                this.strictMode = true;
                            } else {
                                directivePrologue = false;
                            }
                        } else {
                            directivePrologue = false;
                        }
                    }
                }
            }
        };
        Parser.prototype.quickParse = function (sourceText, filename, unitIndex) {
            var svGenTarget = TypeScript.moduleGenTarget;
            try  {
                TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Local;
                var script = this.parse(sourceText, filename, unitIndex, TypeScript.AllowedElements.QuickParse);
                return new QuickParseResult(script, this.scanner.lexState);
            }finally {
                TypeScript.moduleGenTarget = svGenTarget;
            }
        };
        Parser.prototype.parse = function (sourceText, filename, unitIndex, allowedElements) {
            if (typeof allowedElements === "undefined") { allowedElements = TypeScript.AllowedElements.Global; }
            var _this = this;
            this.ambientModule = false;
            this.topLevel = true;
            this.hasTopLevelImportOrExport = false;
            this.requiresExtendsBlock = false;
            this.fname = filename;
            this.currentUnitIndex = unitIndex;
            this.amdDependencies = [];
            this.scanner.resetComments();
            this.scanner.setErrorHandler(function (message) {
                return _this.reportParseError(message);
            });
            this.scanner.setSourceText(sourceText, TypeScript.LexMode.File);
            var leftCurlyCount = this.scanner.leftCurlyCount;
            var rightCurlyCount = this.scanner.rightCurlyCount;
            var minChar = this.scanner.pos;
            this.currentToken = this.scanner.scan();
            this.pushDeclLists();
            var bod = new TypeScript.ASTList();
            bod.minChar = minChar;
            this.state = ParseState.StartScript;
            this.parsingDeclareFile = TypeScript.isDSTRFile(filename) || TypeScript.isDTSFile(filename);
            while(true) {
                this.parseStatementList(TypeScript.ErrorRecoverySet.EOF | TypeScript.ErrorRecoverySet.Func, bod, true, false, allowedElements, TypeScript.Modifiers.None);
                if(this.currentToken.tokenId === TypeScript.TokenID.EndOfFile) {
                    break;
                }
                var badToken = TypeScript.tokenTable[this.currentToken.tokenId];
                this.reportParseError("Unexpected statement block terminator '" + badToken.text + "'");
                this.currentToken = this.scanner.scan();
            }
            this.state = ParseState.EndScript;
            bod.limChar = this.scanner.pos;
            var topLevelMod = null;
            if(TypeScript.moduleGenTarget != TypeScript.ModuleGenTarget.Local && this.hasTopLevelImportOrExport) {
                var correctedFileName = TypeScript.switchToForwardSlashes(filename);
                var id = new TypeScript.Identifier(correctedFileName);
                topLevelMod = new TypeScript.ModuleDeclaration(id, bod, this.topVarList(), this.topScopeList(), null);
                topLevelMod.modFlags |= TypeScript.ModuleFlags.IsDynamic;
                topLevelMod.modFlags |= TypeScript.ModuleFlags.IsWholeFile;
                topLevelMod.modFlags |= TypeScript.ModuleFlags.Exported;
                if(this.parsingDeclareFile) {
                    topLevelMod.modFlags |= TypeScript.ModuleFlags.Ambient;
                }
                topLevelMod.minChar = minChar;
                topLevelMod.limChar = this.scanner.pos;
                topLevelMod.prettyName = TypeScript.getPrettyName(correctedFileName);
                topLevelMod.containsUnicodeChar = this.scanner.seenUnicodeChar;
                topLevelMod.containsUnicodeCharInComment = this.scanner.seenUnicodeCharInComment;
                topLevelMod.amdDependencies = this.amdDependencies;
                bod = new TypeScript.ASTList();
                bod.minChar = topLevelMod.minChar;
                bod.limChar = topLevelMod.limChar;
                bod.append(topLevelMod);
            }
            var script = new TypeScript.Script(this.topVarList(), this.topScopeList());
            script.bod = bod;
            this.popDeclLists();
            script.minChar = minChar;
            script.limChar = this.scanner.pos;
            script.locationInfo = new TypeScript.LocationInfo(filename, this.scanner.lineMap, unitIndex);
            script.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;
            script.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;
            script.isDeclareFile = this.parsingDeclareFile;
            script.topLevelMod = topLevelMod;
            script.containsUnicodeChar = this.scanner.seenUnicodeChar;
            script.containsUnicodeCharInComment = this.scanner.seenUnicodeCharInComment;
            script.requiresExtendsBlock = this.requiresExtendsBlock;
            return script;
        };
        return Parser;
    })();
    TypeScript.Parser = Parser;    
    function quickParse(logger, scopeStartAST, sourceText, minChar, limChar, errorCapture) {
        var fragment = sourceText.getText(minChar, limChar);
        logger.log("Quick parse range (" + minChar + "," + limChar + "): \"" + TypeScript.stringToLiteral(fragment, 100) + "\"");
        var quickParser = new Parser();
        quickParser.setErrorRecovery(null);
        quickParser.errorCallback = errorCapture;
        var quickClassDecl = new TypeScript.ClassDeclaration(null, null, null, null);
        quickParser.currentClassDecl = quickClassDecl;
        var result = quickParser.quickParse(new TypeScript.StringSourceText(fragment), "", 0);
        return result;
    }
    TypeScript.quickParse = quickParse;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var PrintContext = (function () {
        function PrintContext(outfile, parser) {
            this.outfile = outfile;
            this.parser = parser;
            this.builder = "";
            this.indent1 = "  ";
            this.indentStrings = [];
            this.indentAmt = 0;
        }
        PrintContext.prototype.increaseIndent = function () {
            this.indentAmt++;
        };
        PrintContext.prototype.decreaseIndent = function () {
            this.indentAmt--;
        };
        PrintContext.prototype.startLine = function () {
            if(this.builder.length > 0) {
                TypeScript.CompilerDiagnostics.Alert(this.builder);
            }
            var indentString = this.indentStrings[this.indentAmt];
            if(indentString === undefined) {
                indentString = "";
                for(var i = 0; i < this.indentAmt; i++) {
                    indentString += this.indent1;
                }
                this.indentStrings[this.indentAmt] = indentString;
            }
            this.builder += indentString;
        };
        PrintContext.prototype.write = function (s) {
            this.builder += s;
        };
        PrintContext.prototype.writeLine = function (s) {
            this.builder += s;
            this.outfile.WriteLine(this.builder);
            this.builder = "";
        };
        return PrintContext;
    })();
    TypeScript.PrintContext = PrintContext;    
    function prePrintAST(ast, parent, walker) {
        var pc = walker.state;
        ast.print(pc);
        pc.increaseIndent();
        return ast;
    }
    TypeScript.prePrintAST = prePrintAST;
    function postPrintAST(ast, parent, walker) {
        var pc = walker.state;
        pc.decreaseIndent();
        return ast;
    }
    TypeScript.postPrintAST = postPrintAST;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    TypeScript.LexEOF = (-1);
    TypeScript.LexCodeNWL = 10;
    TypeScript.LexCodeRET = 13;
    TypeScript.LexCodeLS = 8232;
    TypeScript.LexCodePS = 8233;
    TypeScript.LexCodeTAB = 9;
    TypeScript.LexCodeVTAB = 11;
    TypeScript.LexCode_e = 'e'.charCodeAt(0);
    TypeScript.LexCode_E = 'E'.charCodeAt(0);
    TypeScript.LexCode_x = 'x'.charCodeAt(0);
    TypeScript.LexCode_X = 'X'.charCodeAt(0);
    TypeScript.LexCode_a = 'a'.charCodeAt(0);
    TypeScript.LexCode_A = 'A'.charCodeAt(0);
    TypeScript.LexCode_f = 'f'.charCodeAt(0);
    TypeScript.LexCode_F = 'F'.charCodeAt(0);
    TypeScript.LexCode_g = 'g'.charCodeAt(0);
    TypeScript.LexCode_m = 'm'.charCodeAt(0);
    TypeScript.LexCode_i = 'i'.charCodeAt(0);
    TypeScript.LexCode_u = 'u'.charCodeAt(0);
    TypeScript.LexCode_0 = '0'.charCodeAt(0);
    TypeScript.LexCode_9 = '9'.charCodeAt(0);
    TypeScript.LexCode_8 = '8'.charCodeAt(0);
    TypeScript.LexCode_7 = '7'.charCodeAt(0);
    TypeScript.LexCodeBSL = '\\'.charCodeAt(0);
    TypeScript.LexCodeSHP = '#'.charCodeAt(0);
    TypeScript.LexCodeBNG = '!'.charCodeAt(0);
    TypeScript.LexCodeQUO = '"'.charCodeAt(0);
    TypeScript.LexCodeAPO = '\''.charCodeAt(0);
    TypeScript.LexCodePCT = '%'.charCodeAt(0);
    TypeScript.LexCodeAMP = '&'.charCodeAt(0);
    TypeScript.LexCodeLPR = '('.charCodeAt(0);
    TypeScript.LexCodeRPR = ')'.charCodeAt(0);
    TypeScript.LexCodePLS = '+'.charCodeAt(0);
    TypeScript.LexCodeMIN = '-'.charCodeAt(0);
    TypeScript.LexCodeMUL = '*'.charCodeAt(0);
    TypeScript.LexCodeSLH = '/'.charCodeAt(0);
    TypeScript.LexCodeXOR = '^'.charCodeAt(0);
    TypeScript.LexCodeCMA = ','.charCodeAt(0);
    TypeScript.LexCodeDOT = '.'.charCodeAt(0);
    TypeScript.LexCodeLT = '<'.charCodeAt(0);
    TypeScript.LexCodeEQ = '='.charCodeAt(0);
    TypeScript.LexCodeGT = '>'.charCodeAt(0);
    TypeScript.LexCodeQUE = '?'.charCodeAt(0);
    TypeScript.LexCodeLBR = '['.charCodeAt(0);
    TypeScript.LexCodeRBR = ']'.charCodeAt(0);
    TypeScript.LexCodeUSC = '_'.charCodeAt(0);
    TypeScript.LexCodeLC = '{'.charCodeAt(0);
    TypeScript.LexCodeRC = '}'.charCodeAt(0);
    TypeScript.LexCodeBAR = '|'.charCodeAt(0);
    TypeScript.LexCodeTIL = '~'.charCodeAt(0);
    TypeScript.LexCodeCOL = ':'.charCodeAt(0);
    TypeScript.LexCodeSMC = ';'.charCodeAt(0);
    TypeScript.LexCodeUnderscore = '_'.charCodeAt(0);
    TypeScript.LexCodeDollar = '$'.charCodeAt(0);
    TypeScript.LexCodeSpace = 32;
    TypeScript.LexCodeAtSign = '@'.charCodeAt(0);
    TypeScript.LexCodeASCIIChars = 128;
    TypeScript.LexKeywordTable = undefined;
    var autoToken = new Array(TypeScript.LexCodeASCIIChars);
    var lexIdStartTable = new Array(TypeScript.LexCodeASCIIChars);
    var unicodeES3IdStart = [
        170, 
        170, 
        181, 
        181, 
        186, 
        186, 
        192, 
        214, 
        216, 
        246, 
        248, 
        543, 
        546, 
        563, 
        592, 
        685, 
        688, 
        696, 
        699, 
        705, 
        720, 
        721, 
        736, 
        740, 
        750, 
        750, 
        890, 
        890, 
        902, 
        902, 
        904, 
        906, 
        908, 
        908, 
        910, 
        929, 
        931, 
        974, 
        976, 
        983, 
        986, 
        1011, 
        1024, 
        1153, 
        1164, 
        1220, 
        1223, 
        1224, 
        1227, 
        1228, 
        1232, 
        1269, 
        1272, 
        1273, 
        1329, 
        1366, 
        1369, 
        1369, 
        1377, 
        1415, 
        1488, 
        1514, 
        1520, 
        1522, 
        1569, 
        1594, 
        1600, 
        1610, 
        1649, 
        1747, 
        1749, 
        1749, 
        1765, 
        1766, 
        1786, 
        1788, 
        1808, 
        1808, 
        1810, 
        1836, 
        1920, 
        1957, 
        2309, 
        2361, 
        2365, 
        2365, 
        2384, 
        2384, 
        2392, 
        2401, 
        2437, 
        2444, 
        2447, 
        2448, 
        2451, 
        2472, 
        2474, 
        2480, 
        2482, 
        2482, 
        2486, 
        2489, 
        2524, 
        2525, 
        2527, 
        2529, 
        2544, 
        2545, 
        2565, 
        2570, 
        2575, 
        2576, 
        2579, 
        2600, 
        2602, 
        2608, 
        2610, 
        2611, 
        2613, 
        2614, 
        2616, 
        2617, 
        2649, 
        2652, 
        2654, 
        2654, 
        2674, 
        2676, 
        2693, 
        2699, 
        2701, 
        2701, 
        2703, 
        2705, 
        2707, 
        2728, 
        2730, 
        2736, 
        2738, 
        2739, 
        2741, 
        2745, 
        2749, 
        2749, 
        2768, 
        2768, 
        2784, 
        2784, 
        2821, 
        2828, 
        2831, 
        2832, 
        2835, 
        2856, 
        2858, 
        2864, 
        2866, 
        2867, 
        2870, 
        2873, 
        2877, 
        2877, 
        2908, 
        2909, 
        2911, 
        2913, 
        2949, 
        2954, 
        2958, 
        2960, 
        2962, 
        2965, 
        2969, 
        2970, 
        2972, 
        2972, 
        2974, 
        2975, 
        2979, 
        2980, 
        2984, 
        2986, 
        2990, 
        2997, 
        2999, 
        3001, 
        3077, 
        3084, 
        3086, 
        3088, 
        3090, 
        3112, 
        3114, 
        3123, 
        3125, 
        3129, 
        3168, 
        3169, 
        3205, 
        3212, 
        3214, 
        3216, 
        3218, 
        3240, 
        3242, 
        3251, 
        3253, 
        3257, 
        3294, 
        3294, 
        3296, 
        3297, 
        3333, 
        3340, 
        3342, 
        3344, 
        3346, 
        3368, 
        3370, 
        3385, 
        3424, 
        3425, 
        3461, 
        3478, 
        3482, 
        3505, 
        3507, 
        3515, 
        3517, 
        3517, 
        3520, 
        3526, 
        3585, 
        3632, 
        3634, 
        3635, 
        3648, 
        3654, 
        3713, 
        3714, 
        3716, 
        3716, 
        3719, 
        3720, 
        3722, 
        3722, 
        3725, 
        3725, 
        3732, 
        3735, 
        3737, 
        3743, 
        3745, 
        3747, 
        3749, 
        3749, 
        3751, 
        3751, 
        3754, 
        3755, 
        3757, 
        3760, 
        3762, 
        3763, 
        3773, 
        3773, 
        3776, 
        3780, 
        3782, 
        3782, 
        3804, 
        3805, 
        3840, 
        3840, 
        3904, 
        3911, 
        3913, 
        3946, 
        3976, 
        3979, 
        4096, 
        4129, 
        4131, 
        4135, 
        4137, 
        4138, 
        4176, 
        4181, 
        4256, 
        4293, 
        4304, 
        4342, 
        4352, 
        4441, 
        4447, 
        4514, 
        4520, 
        4601, 
        4608, 
        4614, 
        4616, 
        4678, 
        4680, 
        4680, 
        4682, 
        4685, 
        4688, 
        4694, 
        4696, 
        4696, 
        4698, 
        4701, 
        4704, 
        4742, 
        4744, 
        4744, 
        4746, 
        4749, 
        4752, 
        4782, 
        4784, 
        4784, 
        4786, 
        4789, 
        4792, 
        4798, 
        4800, 
        4800, 
        4802, 
        4805, 
        4808, 
        4814, 
        4816, 
        4822, 
        4824, 
        4846, 
        4848, 
        4878, 
        4880, 
        4880, 
        4882, 
        4885, 
        4888, 
        4894, 
        4896, 
        4934, 
        4936, 
        4954, 
        5024, 
        5108, 
        5121, 
        5740, 
        5743, 
        5750, 
        5761, 
        5786, 
        5792, 
        5866, 
        6016, 
        6067, 
        6176, 
        6263, 
        6272, 
        6312, 
        7680, 
        7835, 
        7840, 
        7929, 
        7936, 
        7957, 
        7960, 
        7965, 
        7968, 
        8005, 
        8008, 
        8013, 
        8016, 
        8023, 
        8025, 
        8025, 
        8027, 
        8027, 
        8029, 
        8029, 
        8031, 
        8061, 
        8064, 
        8116, 
        8118, 
        8124, 
        8126, 
        8126, 
        8130, 
        8132, 
        8134, 
        8140, 
        8144, 
        8147, 
        8150, 
        8155, 
        8160, 
        8172, 
        8178, 
        8180, 
        8182, 
        8188, 
        8319, 
        8319, 
        8450, 
        8450, 
        8455, 
        8455, 
        8458, 
        8467, 
        8469, 
        8469, 
        8473, 
        8477, 
        8484, 
        8484, 
        8486, 
        8486, 
        8488, 
        8488, 
        8490, 
        8493, 
        8495, 
        8497, 
        8499, 
        8505, 
        8544, 
        8579, 
        12293, 
        12295, 
        12321, 
        12329, 
        12337, 
        12341, 
        12344, 
        12346, 
        12353, 
        12436, 
        12445, 
        12446, 
        12449, 
        12538, 
        12540, 
        12542, 
        12549, 
        12588, 
        12593, 
        12686, 
        12704, 
        12727, 
        13312, 
        13312, 
        19893, 
        19893, 
        19968, 
        19968, 
        40869, 
        40869, 
        40960, 
        42124, 
        44032, 
        44032, 
        55203, 
        55203, 
        63744, 
        64045, 
        64256, 
        64262, 
        64275, 
        64279, 
        64285, 
        64285, 
        64287, 
        64296, 
        64298, 
        64310, 
        64312, 
        64316, 
        64318, 
        64318, 
        64320, 
        64321, 
        64323, 
        64324, 
        64326, 
        64433, 
        64467, 
        64829, 
        64848, 
        64911, 
        64914, 
        64967, 
        65008, 
        65019, 
        65136, 
        65138, 
        65140, 
        65140, 
        65142, 
        65276, 
        65313, 
        65338, 
        65345, 
        65370, 
        65382, 
        65470, 
        65474, 
        65479, 
        65482, 
        65487, 
        65490, 
        65495, 
        65498, 
        65500
    ];
    var unicodeES3IdCont = [
        768, 
        846, 
        864, 
        866, 
        1155, 
        1158, 
        1425, 
        1441, 
        1443, 
        1465, 
        1467, 
        1469, 
        1471, 
        1471, 
        1473, 
        1474, 
        1476, 
        1476, 
        1611, 
        1621, 
        1632, 
        1641, 
        1648, 
        1648, 
        1750, 
        1756, 
        1759, 
        1764, 
        1767, 
        1768, 
        1770, 
        1773, 
        1776, 
        1785, 
        1809, 
        1809, 
        1840, 
        1866, 
        1958, 
        1968, 
        2305, 
        2307, 
        2364, 
        2364, 
        2366, 
        2381, 
        2385, 
        2388, 
        2402, 
        2403, 
        2406, 
        2415, 
        2433, 
        2435, 
        2492, 
        2492, 
        2494, 
        2500, 
        2503, 
        2504, 
        2507, 
        2509, 
        2519, 
        2519, 
        2530, 
        2531, 
        2534, 
        2543, 
        2562, 
        2562, 
        2620, 
        2620, 
        2622, 
        2626, 
        2631, 
        2632, 
        2635, 
        2637, 
        2662, 
        2673, 
        2689, 
        2691, 
        2748, 
        2748, 
        2750, 
        2757, 
        2759, 
        2761, 
        2763, 
        2765, 
        2790, 
        2799, 
        2817, 
        2819, 
        2876, 
        2876, 
        2878, 
        2883, 
        2887, 
        2888, 
        2891, 
        2893, 
        2902, 
        2903, 
        2918, 
        2927, 
        2946, 
        2947, 
        3006, 
        3010, 
        3014, 
        3016, 
        3018, 
        3021, 
        3031, 
        3031, 
        3047, 
        3055, 
        3073, 
        3075, 
        3134, 
        3140, 
        3142, 
        3144, 
        3146, 
        3149, 
        3157, 
        3158, 
        3174, 
        3183, 
        3202, 
        3203, 
        3262, 
        3268, 
        3270, 
        3272, 
        3274, 
        3277, 
        3285, 
        3286, 
        3302, 
        3311, 
        3330, 
        3331, 
        3390, 
        3395, 
        3398, 
        3400, 
        3402, 
        3405, 
        3415, 
        3415, 
        3430, 
        3439, 
        3458, 
        3459, 
        3530, 
        3530, 
        3535, 
        3540, 
        3542, 
        3542, 
        3544, 
        3551, 
        3570, 
        3571, 
        3633, 
        3633, 
        3636, 
        3642, 
        3655, 
        3662, 
        3664, 
        3673, 
        3761, 
        3761, 
        3764, 
        3769, 
        3771, 
        3772, 
        3784, 
        3789, 
        3792, 
        3801, 
        3864, 
        3865, 
        3872, 
        3881, 
        3893, 
        3893, 
        3895, 
        3895, 
        3897, 
        3897, 
        3902, 
        3903, 
        3953, 
        3972, 
        3974, 
        3975, 
        3984, 
        3991, 
        3993, 
        4028, 
        4038, 
        4038, 
        4140, 
        4146, 
        4150, 
        4153, 
        4160, 
        4169, 
        4182, 
        4185, 
        4969, 
        4977, 
        6068, 
        6099, 
        6112, 
        6121, 
        6160, 
        6169, 
        6313, 
        6313, 
        8255, 
        8256, 
        8400, 
        8412, 
        8417, 
        8417, 
        12330, 
        12335, 
        12441, 
        12442, 
        12539, 
        12539, 
        64286, 
        64286, 
        65056, 
        65059, 
        65075, 
        65076, 
        65101, 
        65103, 
        65296, 
        65305, 
        65343, 
        65343, 
        65381, 
        65381
    ];
    var unicodeES5IdStart = [
        170, 
        170, 
        181, 
        181, 
        186, 
        186, 
        192, 
        214, 
        216, 
        246, 
        248, 
        705, 
        710, 
        721, 
        736, 
        740, 
        748, 
        748, 
        750, 
        750, 
        880, 
        884, 
        886, 
        887, 
        890, 
        893, 
        902, 
        902, 
        904, 
        906, 
        908, 
        908, 
        910, 
        929, 
        931, 
        1013, 
        1015, 
        1153, 
        1162, 
        1319, 
        1329, 
        1366, 
        1369, 
        1369, 
        1377, 
        1415, 
        1488, 
        1514, 
        1520, 
        1522, 
        1568, 
        1610, 
        1646, 
        1647, 
        1649, 
        1747, 
        1749, 
        1749, 
        1765, 
        1766, 
        1774, 
        1775, 
        1786, 
        1788, 
        1791, 
        1791, 
        1808, 
        1808, 
        1810, 
        1839, 
        1869, 
        1957, 
        1969, 
        1969, 
        1994, 
        2026, 
        2036, 
        2037, 
        2042, 
        2042, 
        2048, 
        2069, 
        2074, 
        2074, 
        2084, 
        2084, 
        2088, 
        2088, 
        2112, 
        2136, 
        2208, 
        2208, 
        2210, 
        2220, 
        2308, 
        2361, 
        2365, 
        2365, 
        2384, 
        2384, 
        2392, 
        2401, 
        2417, 
        2423, 
        2425, 
        2431, 
        2437, 
        2444, 
        2447, 
        2448, 
        2451, 
        2472, 
        2474, 
        2480, 
        2482, 
        2482, 
        2486, 
        2489, 
        2493, 
        2493, 
        2510, 
        2510, 
        2524, 
        2525, 
        2527, 
        2529, 
        2544, 
        2545, 
        2565, 
        2570, 
        2575, 
        2576, 
        2579, 
        2600, 
        2602, 
        2608, 
        2610, 
        2611, 
        2613, 
        2614, 
        2616, 
        2617, 
        2649, 
        2652, 
        2654, 
        2654, 
        2674, 
        2676, 
        2693, 
        2701, 
        2703, 
        2705, 
        2707, 
        2728, 
        2730, 
        2736, 
        2738, 
        2739, 
        2741, 
        2745, 
        2749, 
        2749, 
        2768, 
        2768, 
        2784, 
        2785, 
        2821, 
        2828, 
        2831, 
        2832, 
        2835, 
        2856, 
        2858, 
        2864, 
        2866, 
        2867, 
        2869, 
        2873, 
        2877, 
        2877, 
        2908, 
        2909, 
        2911, 
        2913, 
        2929, 
        2929, 
        2947, 
        2947, 
        2949, 
        2954, 
        2958, 
        2960, 
        2962, 
        2965, 
        2969, 
        2970, 
        2972, 
        2972, 
        2974, 
        2975, 
        2979, 
        2980, 
        2984, 
        2986, 
        2990, 
        3001, 
        3024, 
        3024, 
        3077, 
        3084, 
        3086, 
        3088, 
        3090, 
        3112, 
        3114, 
        3123, 
        3125, 
        3129, 
        3133, 
        3133, 
        3160, 
        3161, 
        3168, 
        3169, 
        3205, 
        3212, 
        3214, 
        3216, 
        3218, 
        3240, 
        3242, 
        3251, 
        3253, 
        3257, 
        3261, 
        3261, 
        3294, 
        3294, 
        3296, 
        3297, 
        3313, 
        3314, 
        3333, 
        3340, 
        3342, 
        3344, 
        3346, 
        3386, 
        3389, 
        3389, 
        3406, 
        3406, 
        3424, 
        3425, 
        3450, 
        3455, 
        3461, 
        3478, 
        3482, 
        3505, 
        3507, 
        3515, 
        3517, 
        3517, 
        3520, 
        3526, 
        3585, 
        3632, 
        3634, 
        3635, 
        3648, 
        3654, 
        3713, 
        3714, 
        3716, 
        3716, 
        3719, 
        3720, 
        3722, 
        3722, 
        3725, 
        3725, 
        3732, 
        3735, 
        3737, 
        3743, 
        3745, 
        3747, 
        3749, 
        3749, 
        3751, 
        3751, 
        3754, 
        3755, 
        3757, 
        3760, 
        3762, 
        3763, 
        3773, 
        3773, 
        3776, 
        3780, 
        3782, 
        3782, 
        3804, 
        3807, 
        3840, 
        3840, 
        3904, 
        3911, 
        3913, 
        3948, 
        3976, 
        3980, 
        4096, 
        4138, 
        4159, 
        4159, 
        4176, 
        4181, 
        4186, 
        4189, 
        4193, 
        4193, 
        4197, 
        4198, 
        4206, 
        4208, 
        4213, 
        4225, 
        4238, 
        4238, 
        4256, 
        4293, 
        4295, 
        4295, 
        4301, 
        4301, 
        4304, 
        4346, 
        4348, 
        4680, 
        4682, 
        4685, 
        4688, 
        4694, 
        4696, 
        4696, 
        4698, 
        4701, 
        4704, 
        4744, 
        4746, 
        4749, 
        4752, 
        4784, 
        4786, 
        4789, 
        4792, 
        4798, 
        4800, 
        4800, 
        4802, 
        4805, 
        4808, 
        4822, 
        4824, 
        4880, 
        4882, 
        4885, 
        4888, 
        4954, 
        4992, 
        5007, 
        5024, 
        5108, 
        5121, 
        5740, 
        5743, 
        5759, 
        5761, 
        5786, 
        5792, 
        5866, 
        5870, 
        5872, 
        5888, 
        5900, 
        5902, 
        5905, 
        5920, 
        5937, 
        5952, 
        5969, 
        5984, 
        5996, 
        5998, 
        6000, 
        6016, 
        6067, 
        6103, 
        6103, 
        6108, 
        6108, 
        6176, 
        6263, 
        6272, 
        6312, 
        6314, 
        6314, 
        6320, 
        6389, 
        6400, 
        6428, 
        6480, 
        6509, 
        6512, 
        6516, 
        6528, 
        6571, 
        6593, 
        6599, 
        6656, 
        6678, 
        6688, 
        6740, 
        6823, 
        6823, 
        6917, 
        6963, 
        6981, 
        6987, 
        7043, 
        7072, 
        7086, 
        7087, 
        7098, 
        7141, 
        7168, 
        7203, 
        7245, 
        7247, 
        7258, 
        7293, 
        7401, 
        7404, 
        7406, 
        7409, 
        7413, 
        7414, 
        7424, 
        7615, 
        7680, 
        7957, 
        7960, 
        7965, 
        7968, 
        8005, 
        8008, 
        8013, 
        8016, 
        8023, 
        8025, 
        8025, 
        8027, 
        8027, 
        8029, 
        8029, 
        8031, 
        8061, 
        8064, 
        8116, 
        8118, 
        8124, 
        8126, 
        8126, 
        8130, 
        8132, 
        8134, 
        8140, 
        8144, 
        8147, 
        8150, 
        8155, 
        8160, 
        8172, 
        8178, 
        8180, 
        8182, 
        8188, 
        8305, 
        8305, 
        8319, 
        8319, 
        8336, 
        8348, 
        8450, 
        8450, 
        8455, 
        8455, 
        8458, 
        8467, 
        8469, 
        8469, 
        8473, 
        8477, 
        8484, 
        8484, 
        8486, 
        8486, 
        8488, 
        8488, 
        8490, 
        8493, 
        8495, 
        8505, 
        8508, 
        8511, 
        8517, 
        8521, 
        8526, 
        8526, 
        8544, 
        8584, 
        11264, 
        11310, 
        11312, 
        11358, 
        11360, 
        11492, 
        11499, 
        11502, 
        11506, 
        11507, 
        11520, 
        11557, 
        11559, 
        11559, 
        11565, 
        11565, 
        11568, 
        11623, 
        11631, 
        11631, 
        11648, 
        11670, 
        11680, 
        11686, 
        11688, 
        11694, 
        11696, 
        11702, 
        11704, 
        11710, 
        11712, 
        11718, 
        11720, 
        11726, 
        11728, 
        11734, 
        11736, 
        11742, 
        11823, 
        11823, 
        12293, 
        12295, 
        12321, 
        12329, 
        12337, 
        12341, 
        12344, 
        12348, 
        12353, 
        12438, 
        12445, 
        12447, 
        12449, 
        12538, 
        12540, 
        12543, 
        12549, 
        12589, 
        12593, 
        12686, 
        12704, 
        12730, 
        12784, 
        12799, 
        13312, 
        13312, 
        19893, 
        19893, 
        19968, 
        19968, 
        40908, 
        40908, 
        40960, 
        42124, 
        42192, 
        42237, 
        42240, 
        42508, 
        42512, 
        42527, 
        42538, 
        42539, 
        42560, 
        42606, 
        42623, 
        42647, 
        42656, 
        42735, 
        42775, 
        42783, 
        42786, 
        42888, 
        42891, 
        42894, 
        42896, 
        42899, 
        42912, 
        42922, 
        43000, 
        43009, 
        43011, 
        43013, 
        43015, 
        43018, 
        43020, 
        43042, 
        43072, 
        43123, 
        43138, 
        43187, 
        43250, 
        43255, 
        43259, 
        43259, 
        43274, 
        43301, 
        43312, 
        43334, 
        43360, 
        43388, 
        43396, 
        43442, 
        43471, 
        43471, 
        43520, 
        43560, 
        43584, 
        43586, 
        43588, 
        43595, 
        43616, 
        43638, 
        43642, 
        43642, 
        43648, 
        43695, 
        43697, 
        43697, 
        43701, 
        43702, 
        43705, 
        43709, 
        43712, 
        43712, 
        43714, 
        43714, 
        43739, 
        43741, 
        43744, 
        43754, 
        43762, 
        43764, 
        43777, 
        43782, 
        43785, 
        43790, 
        43793, 
        43798, 
        43808, 
        43814, 
        43816, 
        43822, 
        43968, 
        44002, 
        44032, 
        44032, 
        55203, 
        55203, 
        55216, 
        55238, 
        55243, 
        55291, 
        63744, 
        64109, 
        64112, 
        64217, 
        64256, 
        64262, 
        64275, 
        64279, 
        64285, 
        64285, 
        64287, 
        64296, 
        64298, 
        64310, 
        64312, 
        64316, 
        64318, 
        64318, 
        64320, 
        64321, 
        64323, 
        64324, 
        64326, 
        64433, 
        64467, 
        64829, 
        64848, 
        64911, 
        64914, 
        64967, 
        65008, 
        65019, 
        65136, 
        65140, 
        65142, 
        65276, 
        65313, 
        65338, 
        65345, 
        65370, 
        65382, 
        65470, 
        65474, 
        65479, 
        65482, 
        65487, 
        65490, 
        65495, 
        65498, 
        65500
    ];
    var unicodeES5IdCont = [
        768, 
        879, 
        1155, 
        1159, 
        1425, 
        1469, 
        1471, 
        1471, 
        1473, 
        1474, 
        1476, 
        1477, 
        1479, 
        1479, 
        1552, 
        1562, 
        1611, 
        1641, 
        1648, 
        1648, 
        1750, 
        1756, 
        1759, 
        1764, 
        1767, 
        1768, 
        1770, 
        1773, 
        1776, 
        1785, 
        1809, 
        1809, 
        1840, 
        1866, 
        1958, 
        1968, 
        1984, 
        1993, 
        2027, 
        2035, 
        2070, 
        2073, 
        2075, 
        2083, 
        2085, 
        2087, 
        2089, 
        2093, 
        2137, 
        2139, 
        2276, 
        2302, 
        2304, 
        2307, 
        2362, 
        2364, 
        2366, 
        2383, 
        2385, 
        2391, 
        2402, 
        2403, 
        2406, 
        2415, 
        2433, 
        2435, 
        2492, 
        2492, 
        2494, 
        2500, 
        2503, 
        2504, 
        2507, 
        2509, 
        2519, 
        2519, 
        2530, 
        2531, 
        2534, 
        2543, 
        2561, 
        2563, 
        2620, 
        2620, 
        2622, 
        2626, 
        2631, 
        2632, 
        2635, 
        2637, 
        2641, 
        2641, 
        2662, 
        2673, 
        2677, 
        2677, 
        2689, 
        2691, 
        2748, 
        2748, 
        2750, 
        2757, 
        2759, 
        2761, 
        2763, 
        2765, 
        2786, 
        2787, 
        2790, 
        2799, 
        2817, 
        2819, 
        2876, 
        2876, 
        2878, 
        2884, 
        2887, 
        2888, 
        2891, 
        2893, 
        2902, 
        2903, 
        2914, 
        2915, 
        2918, 
        2927, 
        2946, 
        2946, 
        3006, 
        3010, 
        3014, 
        3016, 
        3018, 
        3021, 
        3031, 
        3031, 
        3046, 
        3055, 
        3073, 
        3075, 
        3134, 
        3140, 
        3142, 
        3144, 
        3146, 
        3149, 
        3157, 
        3158, 
        3170, 
        3171, 
        3174, 
        3183, 
        3202, 
        3203, 
        3260, 
        3260, 
        3262, 
        3268, 
        3270, 
        3272, 
        3274, 
        3277, 
        3285, 
        3286, 
        3298, 
        3299, 
        3302, 
        3311, 
        3330, 
        3331, 
        3390, 
        3396, 
        3398, 
        3400, 
        3402, 
        3405, 
        3415, 
        3415, 
        3426, 
        3427, 
        3430, 
        3439, 
        3458, 
        3459, 
        3530, 
        3530, 
        3535, 
        3540, 
        3542, 
        3542, 
        3544, 
        3551, 
        3570, 
        3571, 
        3633, 
        3633, 
        3636, 
        3642, 
        3655, 
        3662, 
        3664, 
        3673, 
        3761, 
        3761, 
        3764, 
        3769, 
        3771, 
        3772, 
        3784, 
        3789, 
        3792, 
        3801, 
        3864, 
        3865, 
        3872, 
        3881, 
        3893, 
        3893, 
        3895, 
        3895, 
        3897, 
        3897, 
        3902, 
        3903, 
        3953, 
        3972, 
        3974, 
        3975, 
        3981, 
        3991, 
        3993, 
        4028, 
        4038, 
        4038, 
        4139, 
        4158, 
        4160, 
        4169, 
        4182, 
        4185, 
        4190, 
        4192, 
        4194, 
        4196, 
        4199, 
        4205, 
        4209, 
        4212, 
        4226, 
        4237, 
        4239, 
        4253, 
        4957, 
        4959, 
        5906, 
        5908, 
        5938, 
        5940, 
        5970, 
        5971, 
        6002, 
        6003, 
        6068, 
        6099, 
        6109, 
        6109, 
        6112, 
        6121, 
        6155, 
        6157, 
        6160, 
        6169, 
        6313, 
        6313, 
        6432, 
        6443, 
        6448, 
        6459, 
        6470, 
        6479, 
        6576, 
        6592, 
        6600, 
        6601, 
        6608, 
        6617, 
        6679, 
        6683, 
        6741, 
        6750, 
        6752, 
        6780, 
        6783, 
        6793, 
        6800, 
        6809, 
        6912, 
        6916, 
        6964, 
        6980, 
        6992, 
        7001, 
        7019, 
        7027, 
        7040, 
        7042, 
        7073, 
        7085, 
        7088, 
        7097, 
        7142, 
        7155, 
        7204, 
        7223, 
        7232, 
        7241, 
        7248, 
        7257, 
        7376, 
        7378, 
        7380, 
        7400, 
        7405, 
        7405, 
        7410, 
        7412, 
        7616, 
        7654, 
        7676, 
        7679, 
        8204, 
        8205, 
        8255, 
        8256, 
        8276, 
        8276, 
        8400, 
        8412, 
        8417, 
        8417, 
        8421, 
        8432, 
        11503, 
        11505, 
        11647, 
        11647, 
        11744, 
        11775, 
        12330, 
        12335, 
        12441, 
        12442, 
        42528, 
        42537, 
        42607, 
        42607, 
        42612, 
        42621, 
        42655, 
        42655, 
        42736, 
        42737, 
        43010, 
        43010, 
        43014, 
        43014, 
        43019, 
        43019, 
        43043, 
        43047, 
        43136, 
        43137, 
        43188, 
        43204, 
        43216, 
        43225, 
        43232, 
        43249, 
        43264, 
        43273, 
        43302, 
        43309, 
        43335, 
        43347, 
        43392, 
        43395, 
        43443, 
        43456, 
        43472, 
        43481, 
        43561, 
        43574, 
        43587, 
        43587, 
        43596, 
        43597, 
        43600, 
        43609, 
        43643, 
        43643, 
        43696, 
        43696, 
        43698, 
        43700, 
        43703, 
        43704, 
        43710, 
        43711, 
        43713, 
        43713, 
        43755, 
        43759, 
        43765, 
        43766, 
        44003, 
        44010, 
        44012, 
        44013, 
        44016, 
        44025, 
        64286, 
        64286, 
        65024, 
        65039, 
        65056, 
        65062, 
        65075, 
        65076, 
        65101, 
        65103, 
        65296, 
        65305, 
        65343, 
        65343
    ];
    function LexLookUpUnicodeMap(code, map) {
        var lo = 0;
        var hi = map.length;
        var mid;
        while(lo + 1 < hi) {
            mid = lo + (hi - lo) / 2;
            mid -= mid % 2;
            if(map[mid] <= code && code <= map[mid + 1]) {
                return true;
            }
            if(code < map[mid]) {
                hi = mid;
            } else {
                lo = mid + 2;
            }
        }
        return false;
    }
    TypeScript.LexLookUpUnicodeMap = LexLookUpUnicodeMap;
    function LexIsUnicodeDigit(code) {
        if(TypeScript.codeGenTarget == TypeScript.CodeGenTarget.ES3) {
            return LexLookUpUnicodeMap(code, unicodeES3IdCont);
        } else {
            return LexLookUpUnicodeMap(code, unicodeES5IdCont);
        }
    }
    TypeScript.LexIsUnicodeDigit = LexIsUnicodeDigit;
    function LexIsUnicodeIdStart(code) {
        if(TypeScript.codeGenTarget == TypeScript.CodeGenTarget.ES3) {
            return LexLookUpUnicodeMap(code, unicodeES3IdStart);
        } else {
            return LexLookUpUnicodeMap(code, unicodeES5IdStart);
        }
    }
    TypeScript.LexIsUnicodeIdStart = LexIsUnicodeIdStart;
    function LexInitialize() {
        TypeScript.initializeStaticTokens();
        autoToken[TypeScript.LexCodeLPR] = TypeScript.staticTokens[TypeScript.TokenID.OpenParen];
        autoToken[TypeScript.LexCodeRPR] = TypeScript.staticTokens[TypeScript.TokenID.CloseParen];
        autoToken[TypeScript.LexCodeCMA] = TypeScript.staticTokens[TypeScript.TokenID.Comma];
        autoToken[TypeScript.LexCodeSMC] = TypeScript.staticTokens[TypeScript.TokenID.Semicolon];
        autoToken[TypeScript.LexCodeLBR] = TypeScript.staticTokens[TypeScript.TokenID.OpenBracket];
        autoToken[TypeScript.LexCodeRBR] = TypeScript.staticTokens[TypeScript.TokenID.CloseBracket];
        autoToken[TypeScript.LexCodeTIL] = TypeScript.staticTokens[TypeScript.TokenID.Tilde];
        autoToken[TypeScript.LexCodeQUE] = TypeScript.staticTokens[TypeScript.TokenID.Question];
        autoToken[TypeScript.LexCodeLC] = TypeScript.staticTokens[TypeScript.TokenID.OpenBrace];
        autoToken[TypeScript.LexCodeRC] = TypeScript.staticTokens[TypeScript.TokenID.CloseBrace];
        autoToken[TypeScript.LexCodeCOL] = TypeScript.staticTokens[TypeScript.TokenID.Colon];
        TypeScript.LexKeywordTable = new TypeScript.StringHashTable();
        for(var i in (TypeScript.TokenID)._map) {
            if((i) <= TypeScript.TokenID.LimKeyword) {
                TypeScript.LexKeywordTable.add((TypeScript.TokenID)._map[i].toLowerCase(), i);
            }
        }
        for(var j = 0; j < TypeScript.LexCodeASCIIChars; j++) {
            if(LexIsIdentifierStartChar(j)) {
                lexIdStartTable[j] = true;
            } else {
                lexIdStartTable[j] = false;
            }
        }
    }
    TypeScript.LexInitialize = LexInitialize;
    function LexAdjustIndent(code, indentAmt) {
        if((code == TypeScript.LexCodeLBR) || (code == TypeScript.LexCodeLC) || (code == TypeScript.LexCodeLPR)) {
            return indentAmt + 1;
        } else {
            if((code == TypeScript.LexCodeRBR) || (code == TypeScript.LexCodeRC) || (code == TypeScript.LexCodeRPR)) {
                return indentAmt - 1;
            } else {
                return indentAmt;
            }
        }
    }
    TypeScript.LexAdjustIndent = LexAdjustIndent;
    function LexIsIdentifierStartChar(code) {
        return (((code >= 97) && (code <= 122)) || ((code >= 65) && (code <= 90)) || (code == TypeScript.LexCodeDollar) || (code == TypeScript.LexCodeUnderscore));
    }
    TypeScript.LexIsIdentifierStartChar = LexIsIdentifierStartChar;
    function LexIsDigit(code) {
        return ((code >= 48) && (code <= 57));
    }
    TypeScript.LexIsDigit = LexIsDigit;
    function LexIsIdentifierChar(code) {
        return lexIdStartTable[code] || LexIsDigit(code);
    }
    TypeScript.LexIsIdentifierChar = LexIsIdentifierChar;
    function LexMatchingOpen(code) {
        if(code == TypeScript.LexCodeRBR) {
            return TypeScript.LexCodeLBR;
        } else {
            if(code == TypeScript.LexCodeRC) {
                return TypeScript.LexCodeLC;
            } else {
                if(code == TypeScript.LexCodeRPR) {
                    return TypeScript.LexCodeLPR;
                } else {
                    return 0;
                }
            }
        }
    }
    TypeScript.LexMatchingOpen = LexMatchingOpen;
    (function (NumberScanState) {
        NumberScanState._map = [];
        NumberScanState._map[0] = "Start";
        NumberScanState.Start = 0;
        NumberScanState._map[1] = "InFraction";
        NumberScanState.InFraction = 1;
        NumberScanState._map[2] = "InEmptyFraction";
        NumberScanState.InEmptyFraction = 2;
        NumberScanState._map[3] = "InExponent";
        NumberScanState.InExponent = 3;
    })(TypeScript.NumberScanState || (TypeScript.NumberScanState = {}));
    var NumberScanState = TypeScript.NumberScanState;
    (function (LexState) {
        LexState._map = [];
        LexState._map[0] = "Start";
        LexState.Start = 0;
        LexState._map[1] = "InMultilineComment";
        LexState.InMultilineComment = 1;
        LexState._map[2] = "InMultilineSingleQuoteString";
        LexState.InMultilineSingleQuoteString = 2;
        LexState._map[3] = "InMultilineDoubleQuoteString";
        LexState.InMultilineDoubleQuoteString = 3;
    })(TypeScript.LexState || (TypeScript.LexState = {}));
    var LexState = TypeScript.LexState;
    (function (LexMode) {
        LexMode._map = [];
        LexMode._map[0] = "Line";
        LexMode.Line = 0;
        LexMode._map[1] = "File";
        LexMode.File = 1;
    })(TypeScript.LexMode || (TypeScript.LexMode = {}));
    var LexMode = TypeScript.LexMode;
    (function (CommentStyle) {
        CommentStyle._map = [];
        CommentStyle._map[0] = "Line";
        CommentStyle.Line = 0;
        CommentStyle._map[1] = "Block";
        CommentStyle.Block = 1;
    })(TypeScript.CommentStyle || (TypeScript.CommentStyle = {}));
    var CommentStyle = TypeScript.CommentStyle;
    var StringSourceText = (function () {
        function StringSourceText(text) {
            this.text = text;
        }
        StringSourceText.prototype.getText = function (start, end) {
            return this.text.substring(start, end);
        };
        StringSourceText.prototype.getLength = function () {
            return this.text.length;
        };
        return StringSourceText;
    })();
    TypeScript.StringSourceText = StringSourceText;    
    var SourceTextSegment = (function () {
        function SourceTextSegment(segmentStart, segmentEnd, segment) {
            this.segmentStart = segmentStart;
            this.segmentEnd = segmentEnd;
            this.segment = segment;
        }
        SourceTextSegment.prototype.charCodeAt = function (index) {
            return this.segment.charCodeAt(index - this.segmentStart);
        };
        SourceTextSegment.prototype.substring = function (start, end) {
            return this.segment.substring(start - this.segmentStart, end - this.segmentStart);
        };
        return SourceTextSegment;
    })();
    TypeScript.SourceTextSegment = SourceTextSegment;    
    var AggerateSourceTextSegment = (function () {
        function AggerateSourceTextSegment(seg1, seg2) {
            this.seg1 = seg1;
            this.seg2 = seg2;
        }
        AggerateSourceTextSegment.prototype.charCodeAt = function (index) {
            if(this.seg1.segmentStart <= index && index < this.seg1.segmentEnd) {
                return this.seg1.segment.charCodeAt(index - this.seg1.segmentStart);
            }
            return this.seg2.segment.charCodeAt(index - this.seg2.segmentStart);
        };
        AggerateSourceTextSegment.prototype.substring = function (start, end) {
            if(this.seg1.segmentStart <= start && end <= this.seg1.segmentEnd) {
                return this.seg1.segment.substring(start - this.seg1.segmentStart, end - this.seg1.segmentStart);
            }
            return this.seg2.segment.substring(start - this.seg2.segmentStart) + this.seg1.segment.substring(0, end - this.seg1.segmentStart);
        };
        return AggerateSourceTextSegment;
    })();
    TypeScript.AggerateSourceTextSegment = AggerateSourceTextSegment;    
    var ScannerTextStream = (function () {
        function ScannerTextStream(sourceText) {
            this.sourceText = sourceText;
            this.agg = new AggerateSourceTextSegment(ScannerTextStream.emptySegment, ScannerTextStream.emptySegment);
            this.len = this.sourceText.getLength();
        }
        ScannerTextStream.emptySegment = new SourceTextSegment(0, 0, "");
        ScannerTextStream.prototype.max = function (a, b) {
            return a >= b ? a : b;
        };
        ScannerTextStream.prototype.min = function (a, b) {
            return a <= b ? a : b;
        };
        ScannerTextStream.prototype.fetchSegment = function (start, end) {
            if(this.agg.seg1.segmentStart <= start && end <= this.agg.seg1.segmentEnd) {
                return this.agg.seg1;
            }
            if(this.agg.seg2.segmentStart <= start && end <= this.agg.seg1.segmentEnd) {
                return this.agg;
            }
            var prev = this.agg.seg1;
            var s = prev.segmentEnd;
            var e = TypeScript.max(s + 512, end);
            e = TypeScript.min(e, this.len);
            var src = this.sourceText.getText(s, e);
            var newSeg = new SourceTextSegment(s, e, src);
            this.agg.seg2 = prev;
            this.agg.seg1 = newSeg;
            return this.agg;
        };
        ScannerTextStream.prototype.charCodeAt = function (index) {
            return this.fetchSegment(index, index + 1).charCodeAt(index);
        };
        ScannerTextStream.prototype.substring = function (start, end) {
            return this.fetchSegment(start, end).substring(start, end);
        };
        return ScannerTextStream;
    })();
    TypeScript.ScannerTextStream = ScannerTextStream;    
    var SavedTokens = (function () {
        function SavedTokens() {
            this.prevToken = null;
            this.curSavedToken = null;
            this.prevSavedToken = null;
            this.prevToken = null;
            this.currentToken = 0;
            this.tokens = new Array();
            this.seenUnicodeChar = false;
            this.seenUnicodeCharInComment = false;
            this.prevLine = 1;
            this.line = 1;
            this.col = 0;
            this.lexState = LexState.Start;
            this.commentStack = new Array();
            this.lineMap = [];
        }
        SavedTokens.prototype.previousToken = function () {
            return this.prevToken;
        };
        SavedTokens.prototype.close = function () {
            this.currentToken = 0;
        };
        SavedTokens.prototype.addToken = function (tok, scanner) {
            this.tokens[this.currentToken++] = new TypeScript.SavedToken(tok, scanner.startPos, scanner.pos);
        };
        SavedTokens.prototype.scan = function () {
            this.startLine = this.line;
            this.startPos = this.col;
            if(this.currentTokenIndex == this.currentTokens.length) {
                if(this.line < this.lineMap.length) {
                    this.line++;
                    this.col = 0;
                    this.currentTokenIndex = 0;
                    this.currentTokens = this.tokensByLine[this.line];
                } else {
                    return TypeScript.staticTokens[TypeScript.TokenID.EndOfFile];
                }
            }
            if(this.currentTokenIndex < this.currentTokens.length) {
                this.prevToken = this.curSavedToken.tok;
                this.prevSavedToken = this.curSavedToken;
                this.curSavedToken = this.currentTokens[this.currentTokenIndex++];
                var curToken = this.curSavedToken.tok;
                this.pos = this.curSavedToken.limChar;
                this.col += (this.curSavedToken.limChar - this.curSavedToken.minChar);
                this.startPos = this.curSavedToken.minChar;
                this.prevLine = this.line;
                return curToken;
            } else {
                return TypeScript.staticTokens[TypeScript.TokenID.EndOfFile];
            }
        };
        SavedTokens.prototype.syncToTok = function (offset) {
            this.line = getLineNumberFromPosition(this.lineMap, offset);
            this.currentTokenIndex = 0;
            var tmpCol = offset - this.lineMap[this.line];
            while((this.lexStateByLine[this.line] == LexState.InMultilineComment) && (this.line > 0)) {
                this.line--;
                tmpCol = 0;
            }
            var lenMin1 = this.lineMap.length - 1;
            this.currentTokens = this.tokensByLine[this.line];
            while((this.currentTokens.length == 0) && (this.line < lenMin1)) {
                this.line++;
                this.currentTokens = this.tokensByLine[this.line];
                tmpCol = 0;
            }
            if(this.line <= lenMin1) {
                while((this.currentTokenIndex < this.currentTokens.length) && (tmpCol > this.currentTokens[this.currentTokenIndex].limChar)) {
                    this.currentTokenIndex++;
                }
                if(this.currentTokenIndex < this.currentTokens.length) {
                    this.col = this.currentTokens[this.currentTokenIndex].minChar;
                    return this.col + this.lineMap[this.line];
                }
            }
            return -1;
        };
        SavedTokens.prototype.lastTokenLimChar = function () {
            if(this.prevSavedToken !== null) {
                return this.prevSavedToken.limChar;
            } else {
                return 0;
            }
        };
        SavedTokens.prototype.lastTokenHadNewline = function () {
            return this.prevLine != this.startLine;
        };
        SavedTokens.prototype.pushComment = function (comment) {
            this.commentStack.push(comment);
        };
        SavedTokens.prototype.getComments = function () {
            var stack = this.commentStack;
            this.commentStack = [];
            return stack;
        };
        SavedTokens.prototype.getCommentsForLine = function (line) {
            var comments = null;
            while((this.commentStack.length > 0) && (this.commentStack[0].line == line)) {
                if(comments == null) {
                    comments = [
                        this.commentStack.shift()
                    ];
                } else {
                    comments = comments.concat([
                        this.commentStack.shift()
                    ]);
                }
            }
            return comments;
        };
        SavedTokens.prototype.resetComments = function () {
            this.commentStack = [];
        };
        SavedTokens.prototype.setSourceText = function (newSrc, textMode) {
        };
        SavedTokens.prototype.setErrorHandler = function (reportError) {
        };
        SavedTokens.prototype.getLookAheadToken = function () {
            throw new Error("Invalid operation.");
        };
        return SavedTokens;
    })();
    TypeScript.SavedTokens = SavedTokens;    
    var Scanner = (function () {
        function Scanner() {
            this.prevLine = 1;
            this.line = 1;
            this.col = 0;
            this.pos = 0;
            this.startPos = 0;
            this.len = 0;
            this.lineMap = [];
            this.ch = TypeScript.LexEOF;
            this.lexState = LexState.Start;
            this.mode = LexMode.File;
            this.scanComments = true;
            this.interveningWhitespace = false;
            this.interveningWhitespacePos = 0;
            this.leftCurlyCount = 0;
            this.rightCurlyCount = 0;
            this.commentStack = new Array();
            this.saveScan = null;
            this.seenUnicodeChar = false;
            this.seenUnicodeCharInComment = false;
            this.prevTok = TypeScript.staticTokens[TypeScript.TokenID.EndOfFile];
            this.startCol = this.col;
            this.startLine = this.line;
            this.lineMap[1] = 0;
            if(!TypeScript.LexKeywordTable) {
                LexInitialize();
            }
        }
        Scanner.prototype.previousToken = function () {
            return this.prevTok;
        };
        Scanner.prototype.setSourceText = function (newSrc, textMode) {
            this.mode = textMode;
            this.scanComments = (this.mode === LexMode.Line);
            this.pos = 0;
            this.interveningWhitespacePos = 0;
            this.startPos = 0;
            this.line = 1;
            this.col = 0;
            this.startCol = this.col;
            this.startLine = this.line;
            this.len = 0;
            this.src = newSrc.getText(0, newSrc.getLength());
            this.len = this.src.length;
            this.lineMap = [];
            this.lineMap[1] = 0;
            this.commentStack = [];
            this.leftCurlyCount = 0;
            this.rightCurlyCount = 0;
            this.seenUnicodeChar = false;
            this.seenUnicodeCharInComment = false;
        };
        Scanner.prototype.setErrorHandler = function (reportError) {
            this.reportError = reportError;
        };
        Scanner.prototype.setSaveScan = function (savedTokens) {
            this.saveScan = savedTokens;
        };
        Scanner.prototype.setText = function (newSrc, textMode) {
            this.setSourceText(new StringSourceText(newSrc), textMode);
        };
        Scanner.prototype.setScanComments = function (value) {
            this.scanComments = value;
        };
        Scanner.prototype.getLexState = function () {
            return this.lexState;
        };
        Scanner.prototype.tokenStart = function () {
            this.startPos = this.pos;
            this.startLine = this.line;
            this.startCol = this.col;
            this.interveningWhitespace = false;
        };
        Scanner.prototype.peekChar = function () {
            if(this.pos < this.len) {
                return this.src.charCodeAt(this.pos);
            } else {
                return TypeScript.LexEOF;
            }
        };
        Scanner.prototype.peekCharAt = function (index) {
            if(index < this.len) {
                return this.src.charCodeAt(index);
            } else {
                return TypeScript.LexEOF;
            }
        };
        Scanner.prototype.IsHexDigit = function (c) {
            return ((c >= TypeScript.LexCode_0) && (c <= TypeScript.LexCode_9)) || ((c >= TypeScript.LexCode_A) && (c <= TypeScript.LexCode_F)) || ((c >= TypeScript.LexCode_a) && (c <= TypeScript.LexCode_f));
        };
        Scanner.prototype.IsOctalDigit = function (c) {
            return ((c >= TypeScript.LexCode_0) && (c <= TypeScript.LexCode_7)) || ((c >= TypeScript.LexCode_a) && (c <= TypeScript.LexCode_f));
        };
        Scanner.prototype.scanHexDigits = function () {
            var atLeastOneDigit = false;
            for(; ; ) {
                if(this.IsHexDigit(this.ch)) {
                    this.nextChar();
                    atLeastOneDigit = true;
                } else {
                    if(atLeastOneDigit) {
                        return new TypeScript.NumberLiteralToken(parseInt(this.src.substring(this.startPos, this.pos)));
                    } else {
                        return null;
                    }
                }
            }
        };
        Scanner.prototype.scanOctalDigits = function () {
            var atLeastOneDigit = false;
            for(; ; ) {
                if(this.IsOctalDigit(this.ch)) {
                    this.nextChar();
                    atLeastOneDigit = true;
                } else {
                    if(atLeastOneDigit) {
                        return new TypeScript.NumberLiteralToken(parseInt(this.src.substring(this.startPos, this.pos)));
                    } else {
                        return null;
                    }
                }
            }
        };
        Scanner.prototype.scanDecimalNumber = function (state) {
            var atLeastOneDigit = false;
            var svPos = this.pos;
            var svCol = this.col;
            for(; ; ) {
                if(LexIsDigit(this.ch)) {
                    atLeastOneDigit = true;
                    if(this.ch != TypeScript.LexCode_0 && state == NumberScanState.InEmptyFraction) {
                        state = NumberScanState.InFraction;
                    }
                    this.nextChar();
                } else {
                    if(this.ch == TypeScript.LexCodeDOT) {
                        if(state == NumberScanState.Start) {
                            this.nextChar();
                            state = NumberScanState.InEmptyFraction;
                        } else {
                            if(atLeastOneDigit) {
                                return new TypeScript.NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);
                            } else {
                                this.pos = svPos;
                                this.col = svCol;
                                return null;
                            }
                        }
                    } else {
                        if((this.ch == TypeScript.LexCode_e) || (this.ch == TypeScript.LexCode_E)) {
                            if(state == NumberScanState.Start) {
                                if(atLeastOneDigit) {
                                    atLeastOneDigit = false;
                                    this.nextChar();
                                    state = NumberScanState.InExponent;
                                } else {
                                    this.pos = svPos;
                                    this.col = svCol;
                                    return null;
                                }
                            } else {
                                if(state == NumberScanState.InFraction || state == NumberScanState.InEmptyFraction) {
                                    this.nextChar();
                                    state = NumberScanState.InExponent;
                                    atLeastOneDigit = false;
                                } else {
                                    if(atLeastOneDigit) {
                                        return new TypeScript.NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)));
                                    } else {
                                        this.pos = svPos;
                                        this.col = svCol;
                                        return null;
                                    }
                                }
                            }
                        } else {
                            if((this.ch == TypeScript.LexCodePLS) || (this.ch == TypeScript.LexCodeMIN)) {
                                if(state == NumberScanState.InExponent) {
                                    if(!atLeastOneDigit) {
                                        this.nextChar();
                                    } else {
                                        this.pos = svPos;
                                        this.col = svCol;
                                        return null;
                                    }
                                } else {
                                    if(state == NumberScanState.InEmptyFraction || state == NumberScanState.InFraction) {
                                        return new TypeScript.NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);
                                    } else {
                                        if(!atLeastOneDigit) {
                                            this.pos = svPos;
                                            this.col = svCol;
                                            return null;
                                        } else {
                                            return new TypeScript.NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)));
                                        }
                                    }
                                }
                            } else {
                                if(!atLeastOneDigit) {
                                    this.pos = svPos;
                                    this.col = svCol;
                                    return null;
                                } else {
                                    return new TypeScript.NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);
                                }
                            }
                        }
                    }
                }
            }
        };
        Scanner.prototype.scanNumber = function () {
            if(this.peekChar() == TypeScript.LexCode_0) {
                switch(this.peekCharAt(this.pos + 1)) {
                    case TypeScript.LexCode_x:
                    case TypeScript.LexCode_X: {
                        this.advanceChar(2);
                        return this.scanHexDigits();

                    }
                    case TypeScript.LexCode_8:
                    case TypeScript.LexCode_9:
                    case TypeScript.LexCodeDOT: {
                        return this.scanDecimalNumber(NumberScanState.Start);

                    }
                    default: {
                        return this.scanOctalDigits();

                    }
                }
            } else {
                return this.scanDecimalNumber(NumberScanState.Start);
            }
        };
        Scanner.prototype.scanFraction = function () {
            return this.scanDecimalNumber(NumberScanState.InFraction);
        };
        Scanner.prototype.newLine = function () {
            this.col = 0;
            if(this.mode == LexMode.File) {
                this.line++;
                this.lineMap[this.line] = this.pos + 1;
            }
        };
        Scanner.prototype.finishMultilineComment = function () {
            var ch2;
            this.lexState = LexState.InMultilineComment;
            while(this.pos < this.len) {
                if(this.ch == TypeScript.LexCodeMUL) {
                    ch2 = this.peekCharAt(this.pos + 1);
                    if(ch2 == TypeScript.LexCodeSLH) {
                        this.advanceChar(2);
                        if(this.mode == LexMode.File) {
                            this.tokenStart();
                        }
                        this.lexState = LexState.Start;
                        return true;
                    }
                } else {
                    if(this.ch == TypeScript.LexCodeNWL) {
                        this.newLine();
                        if(this.mode == LexMode.Line) {
                            this.nextChar();
                            return false;
                        }
                    } else {
                        if(this.ch >= TypeScript.LexCodeASCIIChars) {
                            this.seenUnicodeCharInComment = true;
                        }
                    }
                }
                this.nextChar();
            }
            return false;
        };
        Scanner.prototype.pushComment = function (comment) {
            this.commentStack.push(comment);
        };
        Scanner.prototype.getComments = function () {
            var stack = this.commentStack;
            this.commentStack = [];
            return stack;
        };
        Scanner.prototype.getCommentsForLine = function (line) {
            var comments = null;
            while((this.commentStack.length > 0) && (this.commentStack[0].line == line)) {
                if(comments == null) {
                    comments = [
                        this.commentStack.shift()
                    ];
                } else {
                    comments = comments.concat([
                        this.commentStack.shift()
                    ]);
                }
            }
            return comments;
        };
        Scanner.prototype.resetComments = function () {
            this.commentStack = [];
        };
        Scanner.prototype.endsLine = function (c) {
            return (c == TypeScript.LexCodeNWL) || (c == TypeScript.LexCodeRET) || (c == TypeScript.LexCodeLS) || (c == TypeScript.LexCodePS);
        };
        Scanner.prototype.finishSinglelineComment = function () {
            while(this.pos < this.len) {
                if(this.endsLine(this.ch)) {
                    break;
                }
                if(this.ch >= TypeScript.LexCodeASCIIChars) {
                    this.seenUnicodeCharInComment = true;
                }
                this.nextChar();
            }
            if(this.mode == LexMode.File) {
                this.tokenStart();
            }
        };
        Scanner.prototype.tokenText = function () {
            return this.src.substring(this.startPos, this.pos);
        };
        Scanner.prototype.findClosingSLH = function () {
            var index = this.pos;
            var ch2 = this.src.charCodeAt(index);
            var prevCh = 0;
            var liveEsc = false;
            while(!this.endsLine(ch2) && (index < this.len)) {
                if((ch2 == TypeScript.LexCodeSLH) && (!liveEsc)) {
                    return index;
                }
                prevCh = ch2;
                index++;
                if(liveEsc) {
                    liveEsc = false;
                } else {
                    liveEsc = (prevCh == TypeScript.LexCodeBSL);
                }
                ch2 = this.src.charCodeAt(index);
            }
            return -1;
        };
        Scanner.prototype.speculateRegex = function () {
            if(TypeScript.noRegexTable[this.prevTok.tokenId] != undefined) {
                return null;
            }
            var svPos = this.pos;
            var svCol = this.col;
            var index = this.findClosingSLH();
            if(index > 0) {
                var pattern = this.src.substring(svPos, index);
                var flags = "";
                this.pos = index + 1;
                this.ch = this.peekChar();
                var flagsStart = this.pos;
                while((this.ch == TypeScript.LexCode_i) || (this.ch == TypeScript.LexCode_g) || (this.ch == TypeScript.LexCode_m)) {
                    this.nextChar();
                }
                if((this.pos - flagsStart) > 3) {
                    return null;
                } else {
                    flags = this.src.substring(flagsStart, this.pos);
                }
                var regex = undefined;
                try  {
                    regex = new RegExp(pattern, flags);
                } catch (regexException) {
                }
                if(regex) {
                    this.col = svCol + (this.pos - this.startPos);
                    return new TypeScript.RegularExpressionLiteralToken(regex);
                }
            }
            this.pos = svPos;
            this.col = svCol;
            return null;
        };
        Scanner.prototype.lastTokenHadNewline = function () {
            return this.prevLine != this.startLine;
        };
        Scanner.prototype.lastTokenLimChar = function () {
            return this.interveningWhitespace ? this.interveningWhitespacePos : this.startPos;
        };
        Scanner.prototype.advanceChar = function (amt) {
            this.pos += amt;
            this.col += amt;
            this.ch = this.peekChar();
        };
        Scanner.prototype.nextChar = function () {
            this.pos++;
            this.col++;
            this.ch = this.peekChar();
        };
        Scanner.prototype.getLookAheadToken = function () {
            var prevLine = this.prevLine;
            var line = this.line;
            var col = this.col;
            var pos = this.pos;
            var startPos = this.startPos;
            var startCol = this.startCol;
            var startLine = this.startLine;
            var ch = this.ch;
            var prevTok = this.prevTok;
            var lexState = this.lexState;
            var interveningWhitespace = this.interveningWhitespace;
            var interveningWhitespacePos = this.interveningWhitespacePos;
            var leftCurlyCount = this.leftCurlyCount;
            var rightCurlyCount = this.rightCurlyCount;
            var seenUnicodeChar = this.seenUnicodeChar;
            var seenUnicodeCharInComment = this.seenUnicodeCharInComment;
            var commentStackLength = this.commentStack.length;
            var lookAheadToken = this.scan();
            this.prevLine = prevLine;
            this.line = line;
            this.col = col;
            this.pos = pos;
            this.startPos = startPos;
            this.startCol = startCol;
            this.startLine = startLine;
            this.ch = ch;
            this.prevTok = prevTok;
            this.lexState = lexState;
            this.interveningWhitespace = interveningWhitespace;
            this.interveningWhitespacePos = interveningWhitespacePos;
            this.leftCurlyCount = leftCurlyCount;
            this.rightCurlyCount = rightCurlyCount;
            this.seenUnicodeChar = seenUnicodeChar;
            this.seenUnicodeCharInComment = seenUnicodeCharInComment;
            this.commentStack.length = commentStackLength;
            return lookAheadToken;
        };
        Scanner.prototype.scanInLine = function () {
            if((this.lexState == LexState.InMultilineComment) && (this.scanComments)) {
                this.ch = this.peekChar();
                var commentLine = this.line;
                this.finishMultilineComment();
                if(this.startPos < this.pos) {
                    var commentText = this.src.substring(this.startPos, this.pos);
                    this.tokenStart();
                    return new TypeScript.CommentToken(TypeScript.TokenID.Comment, commentText, true, this.startPos, commentLine, true);
                } else {
                    return TypeScript.staticTokens[TypeScript.TokenID.EndOfFile];
                }
            } else {
                if(this.lexState == LexState.InMultilineSingleQuoteString && this.pos < this.len) {
                    this.ch = TypeScript.LexCodeAPO;
                    this.lexState = LexState.Start;
                    return this.scanStringConstant();
                } else {
                    if(this.lexState == LexState.InMultilineDoubleQuoteString && this.pos < this.len) {
                        this.ch = TypeScript.LexCodeQUO;
                        this.lexState = LexState.Start;
                        return this.scanStringConstant();
                    }
                }
            }
            this.prevLine = this.line;
            var prevTok = this.innerScan();
            if(prevTok.tokenId != TypeScript.TokenID.Whitespace) {
                this.prevTok = prevTok;
            }
            return prevTok;
        };
        Scanner.prototype.scan = function () {
            this.prevLine = this.line;
            this.prevTok = this.innerScan();
            if(this.saveScan) {
                this.saveScan.addToken(this.prevTok, this);
            }
            return this.prevTok;
        };
        Scanner.prototype.isValidUnicodeIdentifierChar = function () {
            var valid = LexIsUnicodeIdStart(this.ch) || LexIsUnicodeDigit(this.ch);
            this.seenUnicodeChar = this.seenUnicodeChar || valid;
            return valid;
        };
        Scanner.prototype.scanStringConstant = function () {
            var endCode = this.ch;
            this.nextChar();
            scanStringConstantLoop:
for(; ; ) {
                switch(this.ch) {
                    case TypeScript.LexEOF: {
                        this.reportScannerError("Unterminated string constant");
                        break scanStringConstantLoop;

                    }
                    case TypeScript.LexCodeLS:
                    case TypeScript.LexCodePS: {
                        this.seenUnicodeChar = true;

                    }
                    case TypeScript.LexCodeRET:
                    case TypeScript.LexCodeNWL: {
                        this.reportScannerError("Unterminated string constant");
                        break scanStringConstantLoop;

                    }
                    case TypeScript.LexCodeAPO:
                    case TypeScript.LexCodeQUO: {
                        if(this.ch == endCode) {
                            this.nextChar();
                            break scanStringConstantLoop;
                        }
                        break;

                    }
                    case TypeScript.LexCodeBSL: {
                        this.nextChar();
                        switch(this.ch) {
                            case TypeScript.LexCodeAPO:
                            case TypeScript.LexCodeQUO:
                            case TypeScript.LexCodeBSL: {
                                this.nextChar();
                                continue scanStringConstantLoop;

                            }
                            case TypeScript.LexCodeLS:
                            case TypeScript.LexCodePS: {
                                this.seenUnicodeChar = true;

                            }
                            case TypeScript.LexCodeRET:
                            case TypeScript.LexCodeNWL: {
                                if(this.ch == TypeScript.LexCodeRET && this.peekCharAt(this.pos + 1) == TypeScript.LexCodeNWL) {
                                    this.nextChar();
                                }
                                this.nextChar();
                                this.newLine();
                                if(this.mode == LexMode.Line) {
                                    this.lexState = endCode == TypeScript.LexCodeAPO ? LexState.InMultilineSingleQuoteString : LexState.InMultilineDoubleQuoteString;
                                    break scanStringConstantLoop;
                                }
                                break;

                            }
                            case TypeScript.LexCode_x:
                            case TypeScript.LexCode_u: {
                                var expectedHexDigits = this.ch == TypeScript.LexCode_x ? 2 : 4;
                                this.nextChar();
                                for(var i = 0; i < expectedHexDigits; i++) {
                                    if(this.IsHexDigit(this.ch)) {
                                        this.nextChar();
                                    } else {
                                        this.reportScannerError("Invalid Unicode escape sequence");
                                        break;
                                    }
                                }
                                continue scanStringConstantLoop;

                            }
                        }
                        break;

                    }
                }
                if(this.ch >= TypeScript.LexCodeASCIIChars) {
                    this.seenUnicodeChar = true;
                }
                this.nextChar();
            }
            return new TypeScript.StringLiteralToken(this.src.substring(this.startPos, this.pos));
        };
        Scanner.prototype.scanIdentifier = function () {
            var hasEscape = false;
            var isFirstChar = (this.ch == TypeScript.LexCodeBSL);
            var hasUnicode = false;
            for(; ; ) {
                while(lexIdStartTable[this.ch] || LexIsDigit(this.ch) || (this.ch >= TypeScript.LexCodeASCIIChars && this.isValidUnicodeIdentifierChar())) {
                    this.nextChar();
                }
                if(this.ch == TypeScript.LexCodeBSL) {
                    this.nextChar();
                    if(this.ch == TypeScript.LexCode_u) {
                        this.nextChar();
                        for(var h = 0; h < 4; h++) {
                            if(this.IsHexDigit(this.ch)) {
                                this.nextChar();
                            } else {
                                this.reportScannerError("Invalid Unicode escape sequence");
                                return TypeScript.staticTokens[TypeScript.TokenID.Error];
                            }
                        }
                        var hexChar = parseInt(this.src.substring(this.pos - 4, this.pos), 16);
                        if(lexIdStartTable[hexChar] || (!isFirstChar && LexIsDigit(hexChar)) || (hexChar >= TypeScript.LexCodeASCIIChars && (LexIsUnicodeIdStart(hexChar) || (!isFirstChar && LexIsUnicodeDigit(hexChar))))) {
                        } else {
                            this.reportScannerError("Invalid identifier character");
                            return TypeScript.staticTokens[TypeScript.TokenID.Error];
                        }
                        hasEscape = true;
                        isFirstChar = false;
                        continue;
                    }
                    this.reportScannerError("Invalid Unicode escape sequence");
                    return TypeScript.staticTokens[TypeScript.TokenID.Error];
                }
                break;
            }
            var id;
            var text = this.src.substring(this.startPos, this.pos);
            if(!hasEscape && (id = TypeScript.LexKeywordTable.lookup(text)) != null) {
                return TypeScript.staticTokens[id];
            } else {
                return new TypeScript.IdentifierToken(text, hasEscape);
            }
        };
        Scanner.prototype.innerScan = function () {
            var rtok;
            this.tokenStart();
            this.ch = this.peekChar();
            start:
while(this.pos < this.len) {
                if(lexIdStartTable[this.ch] || this.ch == TypeScript.LexCodeBSL || (this.ch >= TypeScript.LexCodeASCIIChars && LexIsUnicodeIdStart(this.ch))) {
                    return this.scanIdentifier();
                } else {
                    if(this.ch == TypeScript.LexCodeSpace) {
                        if(!this.interveningWhitespace) {
                            this.interveningWhitespacePos = this.pos;
                        }
                        do {
                            this.nextChar();
                        }while(this.ch == TypeScript.LexCodeSpace)
                        if(this.mode == LexMode.Line) {
                            var whitespaceText = this.src.substring(this.startPos, this.pos);
                            return new TypeScript.WhitespaceToken(TypeScript.TokenID.Whitespace, whitespaceText);
                        } else {
                            this.tokenStart();
                            this.interveningWhitespace = true;
                        }
                    } else {
                        if(this.ch == TypeScript.LexCodeSLH) {
                            this.nextChar();
                            var commentText;
                            if(this.ch == TypeScript.LexCodeSLH) {
                                if(!this.interveningWhitespace) {
                                    this.interveningWhitespacePos = this.pos - 1;
                                }
                                var commentStartPos = this.pos - 1;
                                var commentStartLine = this.line;
                                this.finishSinglelineComment();
                                var commentText = this.src.substring(commentStartPos, this.pos);
                                var commentToken = new TypeScript.CommentToken(TypeScript.TokenID.Comment, commentText, false, commentStartPos, commentStartLine, false);
                                if(this.scanComments) {
                                    this.startPos = commentStartPos;
                                    return commentToken;
                                } else {
                                    this.pushComment(commentToken);
                                }
                                this.interveningWhitespace = true;
                            } else {
                                if(this.ch == TypeScript.LexCodeMUL) {
                                    if(!this.interveningWhitespace) {
                                        this.interveningWhitespacePos = this.pos - 1;
                                    }
                                    var commentStartPos = this.pos - 1;
                                    var commentStartLine = this.line;
                                    this.nextChar();
                                    this.finishMultilineComment();
                                    var commentText = this.src.substring(commentStartPos, this.pos);
                                    var endsLine = this.endsLine(this.peekChar());
                                    var commentToken = new TypeScript.CommentToken(TypeScript.TokenID.Comment, commentText, true, commentStartPos, commentStartLine, endsLine);
                                    if(this.scanComments) {
                                        this.startPos = commentStartPos;
                                        return commentToken;
                                    } else {
                                        this.pushComment(commentToken);
                                    }
                                    this.interveningWhitespace = true;
                                } else {
                                    var regexTok = this.speculateRegex();
                                    if(regexTok) {
                                        return regexTok;
                                    } else {
                                        if(this.peekCharAt(this.pos) == TypeScript.LexCodeEQ) {
                                            this.nextChar();
                                            return TypeScript.staticTokens[TypeScript.TokenID.SlashEquals];
                                        } else {
                                            return TypeScript.staticTokens[TypeScript.TokenID.Slash];
                                        }
                                    }
                                }
                            }
                        } else {
                            if(this.ch == TypeScript.LexCodeSMC) {
                                this.nextChar();
                                return TypeScript.staticTokens[TypeScript.TokenID.Semicolon];
                            } else {
                                if((this.ch == TypeScript.LexCodeAPO) || (this.ch == TypeScript.LexCodeQUO)) {
                                    return this.scanStringConstant();
                                } else {
                                    if(autoToken[this.ch]) {
                                        var atok = autoToken[this.ch];
                                        if(atok.tokenId == TypeScript.TokenID.OpenBrace) {
                                            this.leftCurlyCount++;
                                        } else {
                                            if(atok.tokenId == TypeScript.TokenID.CloseBrace) {
                                                this.rightCurlyCount++;
                                            }
                                        }
                                        this.nextChar();
                                        return atok;
                                    } else {
                                        if((this.ch >= TypeScript.LexCode_0) && (this.ch <= TypeScript.LexCode_9)) {
                                            rtok = this.scanNumber();
                                            if(rtok) {
                                                return rtok;
                                            } else {
                                                this.nextChar();
                                                return TypeScript.staticTokens[TypeScript.TokenID.Error];
                                            }
                                        } else {
                                            switch(this.ch) {
                                                case TypeScript.LexCodeTAB:
                                                case TypeScript.LexCodeVTAB: {
                                                    if(!this.interveningWhitespace) {
                                                        this.interveningWhitespacePos = this.pos;
                                                    }
                                                    if(this.mode == LexMode.Line) {
                                                        do {
                                                            this.nextChar();
                                                        }while((this.ch == TypeScript.LexCodeSpace) || (this.ch == 9))
                                                        var wsText = this.src.substring(this.startPos, this.pos);
                                                        return new TypeScript.WhitespaceToken(TypeScript.TokenID.Whitespace, wsText);
                                                    } else {
                                                        this.interveningWhitespace = true;
                                                    }

                                                }
                                                case 255:
                                                case 254:
                                                case 239:
                                                case 187:
                                                case 191:
                                                case TypeScript.LexCodeLS:
                                                case TypeScript.LexCodePS:
                                                case TypeScript.LexCodeNWL:
                                                case TypeScript.LexCodeRET: {
                                                    if(this.ch == TypeScript.LexCodeNWL) {
                                                        this.newLine();
                                                        if(this.mode == LexMode.Line) {
                                                            return TypeScript.staticTokens[TypeScript.TokenID.EndOfFile];
                                                        }
                                                    }
                                                    if(!this.interveningWhitespace) {
                                                        this.interveningWhitespacePos = this.pos;
                                                    }
                                                    this.nextChar();
                                                    this.tokenStart();
                                                    this.interveningWhitespace = true;
                                                    break;

                                                }
                                                case TypeScript.LexCodeDOT: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeDOT) {
                                                        if(this.peekCharAt(this.pos + 2) == TypeScript.LexCodeDOT) {
                                                            this.advanceChar(3);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.DotDotDot];
                                                        } else {
                                                            this.nextChar();
                                                            return TypeScript.staticTokens[TypeScript.TokenID.Dot];
                                                        }
                                                    } else {
                                                        this.nextChar();
                                                        rtok = this.scanFraction();
                                                        if(rtok) {
                                                            return rtok;
                                                        } else {
                                                            return TypeScript.staticTokens[TypeScript.TokenID.Dot];
                                                        }
                                                    }
                                                }

                                                case TypeScript.LexCodeEQ: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        if(this.peekCharAt(this.pos + 2) == TypeScript.LexCodeEQ) {
                                                            this.advanceChar(3);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.EqualsEqualsEquals];
                                                        } else {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.EqualsEquals];
                                                        }
                                                    } else {
                                                        if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeGT) {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.EqualsGreaterThan];
                                                        } else {
                                                            this.nextChar();
                                                            return TypeScript.staticTokens[TypeScript.TokenID.Equals];
                                                        }
                                                    }

                                                }
                                                case TypeScript.LexCodeBNG: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        if(this.peekCharAt(this.pos + 2) == TypeScript.LexCodeEQ) {
                                                            this.advanceChar(3);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.ExclamationEqualsEquals];
                                                        } else {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.ExclamationEquals];
                                                        }
                                                    } else {
                                                        this.nextChar();
                                                        return TypeScript.staticTokens[TypeScript.TokenID.Exclamation];
                                                    }

                                                }
                                                case TypeScript.LexCodePLS: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        this.advanceChar(2);
                                                        return TypeScript.staticTokens[TypeScript.TokenID.PlusEquals];
                                                    } else {
                                                        if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodePLS) {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.PlusPlus];
                                                        } else {
                                                            this.nextChar();
                                                            return TypeScript.staticTokens[TypeScript.TokenID.Plus];
                                                        }
                                                    }

                                                }
                                                case TypeScript.LexCodeMIN: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        this.advanceChar(2);
                                                        return TypeScript.staticTokens[TypeScript.TokenID.MinusEquals];
                                                    } else {
                                                        if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeMIN) {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.MinusMinus];
                                                        } else {
                                                            this.nextChar();
                                                            return TypeScript.staticTokens[TypeScript.TokenID.Minus];
                                                        }
                                                    }

                                                }
                                                case TypeScript.LexCodeMUL: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        this.advanceChar(2);
                                                        return TypeScript.staticTokens[TypeScript.TokenID.AsteriskEquals];
                                                    } else {
                                                        this.nextChar();
                                                        return TypeScript.staticTokens[TypeScript.TokenID.Asterisk];
                                                    }

                                                }
                                                case TypeScript.LexCodePCT: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        this.advanceChar(2);
                                                        return TypeScript.staticTokens[TypeScript.TokenID.PercentEquals];
                                                    } else {
                                                        this.nextChar();
                                                        return TypeScript.staticTokens[TypeScript.TokenID.Percent];
                                                    }

                                                }
                                                case TypeScript.LexCodeLT: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeLT) {
                                                        if(this.peekCharAt(this.pos + 2) == TypeScript.LexCodeEQ) {
                                                            this.advanceChar(3);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.LessThanLessThanEquals];
                                                        } else {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.LessThanLessThan];
                                                        }
                                                    } else {
                                                        if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.LessThanEquals];
                                                        } else {
                                                            this.nextChar();
                                                            return TypeScript.staticTokens[TypeScript.TokenID.LessThan];
                                                        }
                                                    }

                                                }
                                                case TypeScript.LexCodeGT: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeGT) {
                                                        if(this.peekCharAt(this.pos + 2) == TypeScript.LexCodeEQ) {
                                                            this.advanceChar(3);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.GreaterThanGreaterThanEquals];
                                                        } else {
                                                            if(this.peekCharAt(this.pos + 2) == TypeScript.LexCodeGT) {
                                                                if(this.peekCharAt(this.pos + 3) == TypeScript.LexCodeEQ) {
                                                                    this.advanceChar(4);
                                                                    return TypeScript.staticTokens[TypeScript.TokenID.GreaterThanGreaterThanGreaterThanEquals];
                                                                } else {
                                                                    this.advanceChar(3);
                                                                    return TypeScript.staticTokens[TypeScript.TokenID.GreaterThanGreaterThanGreaterThan];
                                                                }
                                                            } else {
                                                                this.advanceChar(2);
                                                                return TypeScript.staticTokens[TypeScript.TokenID.GreaterThanGreaterThan];
                                                            }
                                                        }
                                                    } else {
                                                        if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.GreaterThanEquals];
                                                        } else {
                                                            this.nextChar();
                                                            return TypeScript.staticTokens[TypeScript.TokenID.GreaterThan];
                                                        }
                                                    }

                                                }
                                                case TypeScript.LexCodeXOR: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        this.advanceChar(2);
                                                        return TypeScript.staticTokens[TypeScript.TokenID.CaretEquals];
                                                    } else {
                                                        this.nextChar();
                                                        return TypeScript.staticTokens[TypeScript.TokenID.Caret];
                                                    }

                                                }
                                                case TypeScript.LexCodeBAR: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        this.advanceChar(2);
                                                        return TypeScript.staticTokens[TypeScript.TokenID.BarEquals];
                                                    } else {
                                                        if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeBAR) {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.BarBar];
                                                        } else {
                                                            this.nextChar();
                                                            return TypeScript.staticTokens[TypeScript.TokenID.Bar];
                                                        }
                                                    }

                                                }
                                                case TypeScript.LexCodeAMP: {
                                                    if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeEQ) {
                                                        this.advanceChar(2);
                                                        return TypeScript.staticTokens[TypeScript.TokenID.AmpersandEquals];
                                                    } else {
                                                        if(this.peekCharAt(this.pos + 1) == TypeScript.LexCodeAMP) {
                                                            this.advanceChar(2);
                                                            return TypeScript.staticTokens[TypeScript.TokenID.AmpersandAmpersand];
                                                        } else {
                                                            this.nextChar();
                                                            return TypeScript.staticTokens[TypeScript.TokenID.And];
                                                        }
                                                    }

                                                }
                                                default: {
                                                    this.reportScannerError("Invalid character");
                                                    this.nextChar();
                                                    continue start;

                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return TypeScript.staticTokens[TypeScript.TokenID.EndOfFile];
        };
        Scanner.prototype.reportScannerError = function (message) {
            if(this.reportError) {
                this.reportError(message);
            }
        };
        return Scanner;
    })();
    TypeScript.Scanner = Scanner;    
    function convertTokToIDName(tok) {
        return convertTokToIDBase(tok, true, false);
    }
    TypeScript.convertTokToIDName = convertTokToIDName;
    function convertTokToID(tok, strictMode) {
        return convertTokToIDBase(tok, false, strictMode);
    }
    TypeScript.convertTokToID = convertTokToID;
    function convertTokToIDBase(tok, identifierName, strictMode) {
        if(tok.tokenId <= TypeScript.TokenID.LimKeyword) {
            var tokInfo = TypeScript.lookupToken(tok.tokenId);
            if(tokInfo != undefined) {
                var resFlags = TypeScript.Reservation.Javascript | TypeScript.Reservation.JavascriptFuture;
                if(strictMode) {
                    resFlags |= TypeScript.Reservation.JavascriptFutureStrict;
                }
                if(identifierName || !TypeScript.hasFlag(tokInfo.reservation, resFlags)) {
                    return true;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    function getLineNumberFromPosition(lineMap, position) {
        if(position === -1) {
            return 0;
        }
        var min = 0;
        var max = lineMap.length - 1;
        while(min < max) {
            var med = (min + max) >> 1;
            if(position < lineMap[med]) {
                max = med - 1;
            } else {
                if(position < lineMap[med + 1]) {
                    min = max = med;
                } else {
                    min = med + 1;
                }
            }
        }
        return min;
    }
    TypeScript.getLineNumberFromPosition = getLineNumberFromPosition;
    function getSourceLineColFromMap(lineCol, minChar, lineMap) {
        var line = getLineNumberFromPosition(lineMap, minChar);
        if(line > 0) {
            lineCol.line = line;
            lineCol.col = (minChar - lineMap[line]);
        }
    }
    TypeScript.getSourceLineColFromMap = getSourceLineColFromMap;
    function getLineColumnFromPosition(script, position) {
        var result = {
            line: -1,
            col: -1
        };
        getSourceLineColFromMap(result, position, script.locationInfo.lineMap);
        if(result.col >= 0) {
            result.col++;
        }
        return result;
    }
    TypeScript.getLineColumnFromPosition = getLineColumnFromPosition;
    function getPositionFromLineColumn(script, line, column) {
        return script.locationInfo.lineMap[line] + (column - 1);
    }
    TypeScript.getPositionFromLineColumn = getPositionFromLineColumn;
    function isPrimitiveTypeToken(token) {
        switch(token.tokenId) {
            case TypeScript.TokenID.Any:
            case TypeScript.TokenID.Bool:
            case TypeScript.TokenID.Number:
            case TypeScript.TokenID.String: {
                return true;

            }
        }
        return false;
    }
    TypeScript.isPrimitiveTypeToken = isPrimitiveTypeToken;
    function isModifier(token) {
        switch(token.tokenId) {
            case TypeScript.TokenID.Public:
            case TypeScript.TokenID.Private:
            case TypeScript.TokenID.Static: {
                return true;

            }
        }
        return false;
    }
    TypeScript.isModifier = isModifier;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var AssignScopeContext = (function () {
        function AssignScopeContext(scopeChain, typeFlow, modDeclChain) {
            this.scopeChain = scopeChain;
            this.typeFlow = typeFlow;
            this.modDeclChain = modDeclChain;
        }
        return AssignScopeContext;
    })();
    TypeScript.AssignScopeContext = AssignScopeContext;    
    function pushAssignScope(scope, context, type, classType, fnc) {
        var chain = new TypeScript.ScopeChain(null, context.scopeChain, scope);
        chain.thisType = type;
        chain.classType = classType;
        chain.fnc = fnc;
        context.scopeChain = chain;
    }
    TypeScript.pushAssignScope = pushAssignScope;
    function popAssignScope(context) {
        context.scopeChain = context.scopeChain.previous;
    }
    TypeScript.popAssignScope = popAssignScope;
    function instanceCompare(a, b) {
        if(((a == null) || (!a.isInstanceProperty()))) {
            return b;
        } else {
            return a;
        }
    }
    TypeScript.instanceCompare = instanceCompare;
    function instanceFilterStop(s) {
        return s.isInstanceProperty();
    }
    TypeScript.instanceFilterStop = instanceFilterStop;
    var ScopeSearchFilter = (function () {
        function ScopeSearchFilter(select, stop) {
            this.select = select;
            this.stop = stop;
            this.result = null;
        }
        ScopeSearchFilter.prototype.reset = function () {
            this.result = null;
        };
        ScopeSearchFilter.prototype.update = function (b) {
            this.result = this.select(this.result, b);
            if(this.result) {
                return this.stop(this.result);
            } else {
                return false;
            }
        };
        return ScopeSearchFilter;
    })();
    TypeScript.ScopeSearchFilter = ScopeSearchFilter;    
    TypeScript.instanceFilter = new ScopeSearchFilter(instanceCompare, instanceFilterStop);
    function preAssignModuleScopes(ast, context) {
        var moduleDecl = ast;
        var memberScope = null;
        var aggScope = null;
        if(moduleDecl.name && moduleDecl.mod) {
            moduleDecl.name.sym = moduleDecl.mod.symbol;
        }
        var mod = moduleDecl.mod;
        if(!mod) {
            return;
        }
        memberScope = new TypeScript.SymbolTableScope(mod.members, mod.ambientMembers, mod.enclosedTypes, mod.ambientEnclosedTypes, mod.symbol);
        mod.memberScope = memberScope;
        context.modDeclChain.push(moduleDecl);
        context.typeFlow.checker.currentModDecl = moduleDecl;
        aggScope = new TypeScript.SymbolAggregateScope(mod.symbol);
        aggScope.addParentScope(memberScope);
        aggScope.addParentScope(context.scopeChain.scope);
        pushAssignScope(aggScope, context, null, null, null);
        mod.containedScope = aggScope;
        if(mod.symbol) {
            context.typeFlow.addLocalsFromScope(mod.containedScope, mod.symbol, moduleDecl.vars, mod.members.privateMembers, true);
        }
    }
    TypeScript.preAssignModuleScopes = preAssignModuleScopes;
    function preAssignClassScopes(ast, context) {
        var classDecl = ast;
        var memberScope = null;
        var aggScope = null;
        if(classDecl.name && classDecl.type) {
            classDecl.name.sym = classDecl.type.symbol;
        }
        var classType = ast.type;
        if(classType) {
            var classSym = classType.symbol;
            memberScope = context.typeFlow.checker.scopeOf(classType);
            aggScope = new TypeScript.SymbolAggregateScope(classType.symbol);
            aggScope.addParentScope(memberScope);
            aggScope.addParentScope(context.scopeChain.scope);
            classType.containedScope = aggScope;
            classType.memberScope = memberScope;
            var instanceType = classType.instanceType;
            memberScope = context.typeFlow.checker.scopeOf(instanceType);
            instanceType.memberScope = memberScope;
            aggScope = new TypeScript.SymbolAggregateScope(instanceType.symbol);
            aggScope.addParentScope(context.scopeChain.scope);
            pushAssignScope(aggScope, context, instanceType, classType, null);
            instanceType.containedScope = aggScope;
        } else {
            ast.type = context.typeFlow.anyType;
        }
    }
    TypeScript.preAssignClassScopes = preAssignClassScopes;
    function preAssignInterfaceScopes(ast, context) {
        var interfaceDecl = ast;
        var memberScope = null;
        var aggScope = null;
        if(interfaceDecl.name && interfaceDecl.type) {
            interfaceDecl.name.sym = interfaceDecl.type.symbol;
        }
        var interfaceType = ast.type;
        memberScope = context.typeFlow.checker.scopeOf(interfaceType);
        interfaceType.memberScope = memberScope;
        aggScope = new TypeScript.SymbolAggregateScope(interfaceType.symbol);
        aggScope.addParentScope(memberScope);
        aggScope.addParentScope(context.scopeChain.scope);
        pushAssignScope(aggScope, context, null, null, null);
        interfaceType.containedScope = aggScope;
    }
    TypeScript.preAssignInterfaceScopes = preAssignInterfaceScopes;
    function preAssignWithScopes(ast, context) {
        var withStmt = ast;
        var withType = withStmt.type;
        var members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
        var ambientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
        var withType = new TypeScript.Type();
        var withSymbol = new TypeScript.WithSymbol(withStmt.minChar, context.typeFlow.checker.locationInfo.unitIndex, withType);
        withType.members = members;
        withType.ambientMembers = ambientMembers;
        withType.symbol = withSymbol;
        withType.setHasImplementation();
        withStmt.type = withType;
        var withScope = new TypeScript.SymbolScopeBuilder(withType.members, withType.ambientMembers, null, null, context.scopeChain.scope, withType.symbol);
        pushAssignScope(withScope, context, null, null, null);
        withType.containedScope = withScope;
    }
    TypeScript.preAssignWithScopes = preAssignWithScopes;
    function preAssignFuncDeclScopes(ast, context) {
        var funcDecl = ast;
        var container = null;
        var localContainer = null;
        if(funcDecl.type) {
            localContainer = ast.type.symbol;
        }
        var isStatic = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Static);
        var isInnerStatic = isStatic && context.scopeChain.fnc != null;
        var parentScope = isInnerStatic ? context.scopeChain.fnc.type.memberScope : context.scopeChain.scope;
        if(context.scopeChain.thisType && (!funcDecl.isConstructor || TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod))) {
            var instType = context.scopeChain.thisType;
            if(!(instType.typeFlags & TypeScript.TypeFlags.IsClass) && !TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod)) {
                if(!funcDecl.isMethod() || isStatic) {
                    parentScope = instType.constructorScope;
                } else {
                    parentScope = instType.containedScope;
                }
            } else {
                if(context.scopeChain.previous.scope.container && context.scopeChain.previous.scope.container.declAST && context.scopeChain.previous.scope.container.declAST.nodeType == TypeScript.NodeType.FuncDecl && (context.scopeChain.previous.scope.container.declAST).isConstructor) {
                    parentScope = instType.constructorScope;
                } else {
                    if(isStatic && context.scopeChain.classType) {
                        parentScope = context.scopeChain.classType.containedScope;
                    } else {
                        parentScope = instType.containedScope;
                    }
                }
            }
            container = instType.symbol;
        } else {
            if(funcDecl.isConstructor && context.scopeChain.thisType) {
                container = context.scopeChain.thisType.symbol;
            }
        }
        if(funcDecl.type == null || TypeScript.hasFlag(funcDecl.type.symbol.flags, TypeScript.SymbolFlags.TypeSetDuringScopeAssignment)) {
            if(context.scopeChain.fnc && context.scopeChain.fnc.type) {
                container = context.scopeChain.fnc.type.symbol;
            }
            var funcScope = null;
            var outerFnc = context.scopeChain.fnc;
            var nameText = funcDecl.name ? funcDecl.name.actualText : null;
            var fgSym = null;
            if(isStatic) {
                if(outerFnc.type.members == null && container.getType().memberScope) {
                    outerFnc.type.members = ((container).type.memberScope).valueMembers;
                }
                funcScope = context.scopeChain.fnc.type.memberScope;
                outerFnc.innerStaticFuncs[outerFnc.innerStaticFuncs.length] = funcDecl;
            } else {
                funcScope = context.scopeChain.scope;
            }
            if(nameText && nameText != "__missing" && !funcDecl.isAccessor()) {
                if(isStatic) {
                    fgSym = funcScope.findLocal(nameText, false, false);
                } else {
                    fgSym = funcScope.findLocal(nameText, false, false);
                }
            }
            context.typeFlow.checker.createFunctionSignature(funcDecl, container, funcScope, fgSym, fgSym == null);
            if(!funcDecl.accessorSymbol && (funcDecl.fncFlags & TypeScript.FncFlags.ClassMethod) && container && ((!fgSym || fgSym.declAST.nodeType != TypeScript.NodeType.FuncDecl) && funcDecl.isAccessor()) || (fgSym && fgSym.isAccessor())) {
                funcDecl.accessorSymbol = context.typeFlow.checker.createAccessorSymbol(funcDecl, fgSym, container.getType(), (funcDecl.isMethod() && isStatic), true, funcScope, container);
            }
            funcDecl.type.symbol.flags |= TypeScript.SymbolFlags.TypeSetDuringScopeAssignment;
        }
        if(funcDecl.name && funcDecl.type) {
            funcDecl.name.sym = funcDecl.type.symbol;
        }
        funcDecl.scopeType = funcDecl.type;
        if(funcDecl.isOverload) {
            return;
        }
        var funcTable = new TypeScript.StringHashTable();
        var funcMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(funcTable, new TypeScript.StringHashTable()));
        var ambientFuncTable = new TypeScript.StringHashTable();
        var ambientFuncMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(ambientFuncTable, new TypeScript.StringHashTable()));
        var funcStaticTable = new TypeScript.StringHashTable();
        var funcStaticMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(funcStaticTable, new TypeScript.StringHashTable()));
        var ambientFuncStaticTable = new TypeScript.StringHashTable();
        var ambientFuncStaticMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(ambientFuncStaticTable, new TypeScript.StringHashTable()));
        funcDecl.unitIndex = context.typeFlow.checker.locationInfo.unitIndex;
        var locals = new TypeScript.SymbolScopeBuilder(funcMembers, ambientFuncMembers, null, null, parentScope, localContainer);
        var statics = new TypeScript.SymbolScopeBuilder(funcStaticMembers, ambientFuncStaticMembers, null, null, parentScope, null);
        if(funcDecl.isConstructor && context.scopeChain.thisType) {
            context.scopeChain.thisType.constructorScope = locals;
        }
        funcDecl.symbols = funcTable;
        if(!funcDecl.isSpecialFn()) {
            var group = funcDecl.type;
            var signature = funcDecl.signature;
            if(!funcDecl.isConstructor) {
                group.containedScope = locals;
                locals.container = group.symbol;
                group.memberScope = statics;
                statics.container = group.symbol;
            }
            funcDecl.enclosingFnc = context.scopeChain.fnc;
            group.enclosingType = isStatic ? context.scopeChain.classType : context.scopeChain.thisType;
            var fgSym = ast.type.symbol;
            if(((funcDecl.fncFlags & TypeScript.FncFlags.Signature) == TypeScript.FncFlags.None) && funcDecl.vars) {
                context.typeFlow.addLocalsFromScope(locals, fgSym, funcDecl.vars, funcTable, false);
                context.typeFlow.addLocalsFromScope(statics, fgSym, funcDecl.statics, funcStaticTable, false);
            }
            if(signature.parameters) {
                var len = signature.parameters.length;
                for(var i = 0; i < len; i++) {
                    var paramSym = signature.parameters[i];
                    context.typeFlow.checker.resolveTypeLink(locals, paramSym.parameter.typeLink, true);
                }
            }
            context.typeFlow.checker.resolveTypeLink(locals, signature.returnType, funcDecl.isSignature());
        }
        if(!funcDecl.isConstructor || TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod)) {
            var thisType = (funcDecl.isConstructor && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod)) ? context.scopeChain.thisType : null;
            pushAssignScope(locals, context, thisType, null, funcDecl);
        }
        if(funcDecl.name && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.IsFunctionExpression)) {
            if(funcDecl.name.sym) {
                funcTable.add(funcDecl.name.actualText, funcDecl.name.sym);
            }
        }
    }
    TypeScript.preAssignFuncDeclScopes = preAssignFuncDeclScopes;
    function preAssignCatchScopes(ast, context) {
        var catchBlock = ast;
        if(catchBlock.param) {
            var catchTable = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            var catchLocals = new TypeScript.SymbolScopeBuilder(catchTable, null, null, null, context.scopeChain.scope, context.scopeChain.scope.container);
            catchBlock.containedScope = catchLocals;
            pushAssignScope(catchLocals, context, context.scopeChain.thisType, context.scopeChain.classType, context.scopeChain.fnc);
        }
    }
    TypeScript.preAssignCatchScopes = preAssignCatchScopes;
    function preAssignScopes(ast, parent, walker) {
        var context = walker.state;
        var go = true;
        if(ast) {
            if(ast.nodeType == TypeScript.NodeType.List) {
                var list = ast;
                list.enclosingScope = context.scopeChain.scope;
            } else {
                if(ast.nodeType == TypeScript.NodeType.ModuleDeclaration) {
                    preAssignModuleScopes(ast, context);
                } else {
                    if(ast.nodeType == TypeScript.NodeType.ClassDeclaration) {
                        preAssignClassScopes(ast, context);
                    } else {
                        if(ast.nodeType == TypeScript.NodeType.InterfaceDeclaration) {
                            preAssignInterfaceScopes(ast, context);
                        } else {
                            if(ast.nodeType == TypeScript.NodeType.With) {
                                preAssignWithScopes(ast, context);
                            } else {
                                if(ast.nodeType == TypeScript.NodeType.FuncDecl) {
                                    preAssignFuncDeclScopes(ast, context);
                                } else {
                                    if(ast.nodeType == TypeScript.NodeType.Catch) {
                                        preAssignCatchScopes(ast, context);
                                    } else {
                                        if(ast.nodeType == TypeScript.NodeType.TypeRef) {
                                            go = false;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        walker.options.goChildren = go;
        return ast;
    }
    TypeScript.preAssignScopes = preAssignScopes;
    function postAssignScopes(ast, parent, walker) {
        var context = walker.state;
        var go = true;
        if(ast) {
            if(ast.nodeType == TypeScript.NodeType.ModuleDeclaration) {
                var prevModDecl = ast;
                popAssignScope(context);
                context.modDeclChain.pop();
                if(context.modDeclChain.length >= 1) {
                    context.typeFlow.checker.currentModDecl = context.modDeclChain[context.modDeclChain.length - 1];
                }
            } else {
                if(ast.nodeType == TypeScript.NodeType.ClassDeclaration) {
                    popAssignScope(context);
                } else {
                    if(ast.nodeType == TypeScript.NodeType.InterfaceDeclaration) {
                        popAssignScope(context);
                    } else {
                        if(ast.nodeType == TypeScript.NodeType.With) {
                            popAssignScope(context);
                        } else {
                            if(ast.nodeType == TypeScript.NodeType.FuncDecl) {
                                var funcDecl = ast;
                                if((!funcDecl.isConstructor || TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod)) && !funcDecl.isOverload) {
                                    popAssignScope(context);
                                }
                            } else {
                                if(ast.nodeType == TypeScript.NodeType.Catch) {
                                    var catchBlock = ast;
                                    if(catchBlock.param) {
                                        popAssignScope(context);
                                    }
                                } else {
                                    go = false;
                                }
                            }
                        }
                    }
                }
            }
        }
        walker.options.goChildren = go;
        return ast;
    }
    TypeScript.postAssignScopes = postAssignScopes;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var TypeCollectionContext = (function () {
        function TypeCollectionContext(scopeChain, checker) {
            this.scopeChain = scopeChain;
            this.checker = checker;
            this.script = null;
        }
        return TypeCollectionContext;
    })();
    TypeScript.TypeCollectionContext = TypeCollectionContext;    
    var MemberScopeContext = (function () {
        function MemberScopeContext(flow, pos, matchFlag) {
            this.flow = flow;
            this.pos = pos;
            this.matchFlag = matchFlag;
            this.type = null;
            this.ast = null;
            this.options = new TypeScript.AstWalkOptions();
        }
        return MemberScopeContext;
    })();
    TypeScript.MemberScopeContext = MemberScopeContext;    
    var EnclosingScopeContext = (function () {
        function EnclosingScopeContext(logger, script, text, pos, isMemberCompletion) {
            this.logger = logger;
            this.script = script;
            this.text = text;
            this.pos = pos;
            this.isMemberCompletion = isMemberCompletion;
            this.scopeGetter = null;
            this.objectLiteralScopeGetter = null;
            this.scopeStartAST = null;
            this.skipNextFuncDeclForClass = false;
            this.deepestModuleDecl = null;
            this.enclosingClassDecl = null;
            this.enclosingObjectLit = null;
            this.publicsOnly = true;
            this.useFullAst = false;
        }
        EnclosingScopeContext.prototype.getScope = function () {
            return this.scopeGetter();
        };
        EnclosingScopeContext.prototype.getObjectLiteralScope = function () {
            return this.objectLiteralScopeGetter();
        };
        EnclosingScopeContext.prototype.getScopeAST = function () {
            return this.scopeStartAST;
        };
        EnclosingScopeContext.prototype.getScopePosition = function () {
            return this.scopeStartAST.minChar;
        };
        EnclosingScopeContext.prototype.getScriptFragmentStartAST = function () {
            return this.scopeStartAST;
        };
        EnclosingScopeContext.prototype.getScriptFragmentPosition = function () {
            return this.getScriptFragmentStartAST().minChar;
        };
        EnclosingScopeContext.prototype.getScriptFragment = function () {
            if(this.scriptFragment == null) {
                var ast = this.getScriptFragmentStartAST();
                var minChar = ast.minChar;
                var limChar = (this.isMemberCompletion ? this.pos : this.pos + 1);
                this.scriptFragment = TypeScript.quickParse(this.logger, ast, this.text, minChar, limChar, null).Script;
            }
            return this.scriptFragment;
        };
        return EnclosingScopeContext;
    })();
    TypeScript.EnclosingScopeContext = EnclosingScopeContext;    
    function preFindMemberScope(ast, parent, walker) {
        var memScope = walker.state;
        if(TypeScript.hasFlag(ast.flags, memScope.matchFlag) && ((memScope.pos < 0) || (memScope.pos == ast.limChar))) {
            memScope.ast = ast;
            if((ast.type == null) && (memScope.pos >= 0)) {
                memScope.flow.inScopeTypeCheck(ast, memScope.scope);
            }
            memScope.type = ast.type;
            memScope.options.stopWalk();
        }
        return ast;
    }
    TypeScript.preFindMemberScope = preFindMemberScope;
    function pushTypeCollectionScope(container, valueMembers, ambientValueMembers, enclosedTypes, ambientEnclosedTypes, context, thisType, classType, moduleDecl) {
        var builder = new TypeScript.SymbolScopeBuilder(valueMembers, ambientValueMembers, enclosedTypes, ambientEnclosedTypes, null, container);
        var chain = new TypeScript.ScopeChain(container, context.scopeChain, builder);
        chain.thisType = thisType;
        chain.classType = classType;
        chain.moduleDecl = moduleDecl;
        context.scopeChain = chain;
    }
    TypeScript.pushTypeCollectionScope = pushTypeCollectionScope;
    function popTypeCollectionScope(context) {
        context.scopeChain = context.scopeChain.previous;
    }
    TypeScript.popTypeCollectionScope = popTypeCollectionScope;
    function preFindEnclosingScope(ast, parent, walker) {
        var context = walker.state;
        var minChar = ast.minChar;
        var limChar = ast.limChar;
        if(ast.nodeType == TypeScript.NodeType.Script && context.pos > limChar) {
            limChar = context.pos;
        }
        if((minChar <= context.pos) && (limChar >= context.pos)) {
            switch(ast.nodeType) {
                case TypeScript.NodeType.Script: {
                    var script = ast;
                    context.scopeGetter = function () {
                        return script.bod === null ? null : script.bod.enclosingScope;
                    };
                    context.scopeStartAST = script;
                    break;

                }
                case TypeScript.NodeType.ClassDeclaration: {
                    context.scopeGetter = function () {
                        return (ast.type === null || ast.type.instanceType.containedScope === null) ? null : ast.type.instanceType.containedScope;
                    };
                    context.scopeStartAST = ast;
                    context.enclosingClassDecl = ast;
                    break;

                }
                case TypeScript.NodeType.ObjectLit: {
                    var objectLit = ast;
                    if(objectLit.targetType) {
                        context.scopeGetter = function () {
                            return objectLit.targetType.containedScope;
                        };
                        context.objectLiteralScopeGetter = function () {
                            return objectLit.targetType.memberScope;
                        };
                        context.enclosingObjectLit = objectLit;
                    }
                    break;

                }
                case TypeScript.NodeType.ModuleDeclaration: {
                    context.deepestModuleDecl = ast;
                    context.scopeGetter = function () {
                        return ast.type === null ? null : ast.type.containedScope;
                    };
                    context.scopeStartAST = ast;
                    break;

                }
                case TypeScript.NodeType.InterfaceDeclaration: {
                    context.scopeGetter = function () {
                        return (ast.type === null) ? null : ast.type.containedScope;
                    };
                    context.scopeStartAST = ast;
                    break;

                }
                case TypeScript.NodeType.FuncDecl: {
 {
                        var funcDecl = ast;
                        if(context.skipNextFuncDeclForClass) {
                            context.skipNextFuncDeclForClass = false;
                        } else {
                            context.scopeGetter = function () {
                                if(funcDecl.isConstructor && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod)) {
                                    if(ast.type && ast.type.enclosingType) {
                                        return ast.type.enclosingType.constructorScope;
                                    }
                                }
                                if(funcDecl.scopeType) {
                                    return funcDecl.scopeType.containedScope;
                                }
                                if(funcDecl.type) {
                                    return funcDecl.type.containedScope;
                                }
                                return null;
                            };
                            context.scopeStartAST = ast;
                        }
                    }
                    break;

                }
            }
            walker.options.goChildren = true;
        } else {
            walker.options.goChildren = false;
        }
        return ast;
    }
    TypeScript.preFindEnclosingScope = preFindEnclosingScope;
    function findEnclosingScopeAt(logger, script, text, pos, isMemberCompletion) {
        var context = new EnclosingScopeContext(logger, script, text, pos, isMemberCompletion);
        TypeScript.getAstWalkerFactory().walk(script, preFindEnclosingScope, null, null, context);
        if(context.scopeStartAST === null) {
            return null;
        }
        return context;
    }
    TypeScript.findEnclosingScopeAt = findEnclosingScopeAt;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var Signature = (function () {
        function Signature() {
            this.hasVariableArgList = false;
            this.parameters = null;
            this.declAST = null;
            this.typeCheckStatus = TypeScript.TypeCheckStatus.NotStarted;
            this.nonOptionalParameterCount = 0;
        }
        Signature.prototype.specializeType = function (pattern, replacement, checker) {
            var result = new Signature();
            if(this.hasVariableArgList) {
                result.hasVariableArgList = true;
            }
            result.returnType = new TypeScript.TypeLink();
            if(this.returnType.type) {
                result.returnType.type = this.returnType.type.specializeType(pattern, replacement, checker, false);
            } else {
                result.returnType.type = checker.anyType;
            }
            if(this.parameters) {
                result.parameters = [];
                for(var i = 0, len = this.parameters.length; i < len; i++) {
                    var oldSym = this.parameters[i];
                    var paramDef = new TypeScript.ValueLocation();
                    var paramSym = new TypeScript.ParameterSymbol(oldSym.name, oldSym.location, checker.locationInfo.unitIndex, paramDef);
                    paramSym.declAST = this.declAST;
                    paramDef.symbol = paramSym;
                    paramDef.typeLink = new TypeScript.TypeLink();
                    result.parameters[i] = paramSym;
                    var oldType = oldSym.getType();
                    if(oldType) {
                        paramDef.typeLink.type = oldType.specializeType(pattern, replacement, checker, false);
                        paramSym.declAST.type = paramDef.typeLink.type;
                    } else {
                        paramDef.typeLink.type = checker.anyType;
                    }
                }
            }
            result.nonOptionalParameterCount = this.nonOptionalParameterCount;
            result.declAST = this.declAST;
            return result;
        };
        Signature.prototype.toString = function () {
            return this.toStringHelper(false, false, null);
        };
        Signature.prototype.toStringHelper = function (shortform, brackets, scope) {
            return this.toStringHelperEx(shortform, brackets, scope).toString();
        };
        Signature.prototype.toStringHelperEx = function (shortform, brackets, scope, prefix) {
            if (typeof prefix === "undefined") { prefix = ""; }
            var builder = new TypeScript.MemberNameArray();
            if(brackets) {
                builder.prefix = prefix + "[";
            } else {
                builder.prefix = prefix + "(";
            }
            var paramLen = this.parameters.length;
            var len = this.hasVariableArgList ? paramLen - 1 : paramLen;
            for(var i = 0; i < len; i++) {
                builder.add(TypeScript.MemberName.create(this.parameters[i].name + (this.parameters[i].isOptional() ? "?" : "") + ": "));
                builder.add(this.parameters[i].getType().getScopedTypeNameEx(scope));
                if(i < paramLen - 1) {
                    builder.add(TypeScript.MemberName.create(", "));
                }
            }
            if(this.hasVariableArgList) {
                builder.add(TypeScript.MemberName.create("..." + this.parameters[i].name + ": "));
                builder.add(this.parameters[i].getType().getScopedTypeNameEx(scope));
            }
            if(shortform) {
                if(brackets) {
                    builder.add(TypeScript.MemberName.create("] => "));
                } else {
                    builder.add(TypeScript.MemberName.create(") => "));
                }
            } else {
                if(brackets) {
                    builder.add(TypeScript.MemberName.create("]: "));
                } else {
                    builder.add(TypeScript.MemberName.create("): "));
                }
            }
            if(this.returnType.type) {
                builder.add(this.returnType.type.getScopedTypeNameEx(scope));
            } else {
                builder.add(TypeScript.MemberName.create("any"));
            }
            return builder;
        };
        return Signature;
    })();
    TypeScript.Signature = Signature;    
    var SignatureGroup = (function () {
        function SignatureGroup() {
            this.signatures = [];
            this.hasImplementation = true;
            this.definitionSignature = null;
            this.hasBeenTypechecked = false;
            this.flags = TypeScript.SignatureFlags.None;
        }
        SignatureGroup.prototype.addSignature = function (signature) {
            if(this.signatures == null) {
                this.signatures = new Array();
            }
            this.signatures[this.signatures.length] = signature;
            if(signature.declAST && !signature.declAST.isOverload && !signature.declAST.isSignature() && !TypeScript.hasFlag(signature.declAST.fncFlags, TypeScript.FncFlags.Ambient) && TypeScript.hasFlag(signature.declAST.fncFlags, TypeScript.FncFlags.Definition)) {
                this.definitionSignature = signature;
            }
        };
        SignatureGroup.prototype.toString = function () {
            return this.signatures.toString();
        };
        SignatureGroup.prototype.toStrings = function (prefix, shortform, scope) {
            var result = [];
            var len = this.signatures.length;
            if(len > 1) {
                shortform = false;
            }
            for(var i = 0; i < len; i++) {
                if(len > 1 && this.signatures[i] == this.definitionSignature) {
                    continue;
                }
                if(this.flags & TypeScript.SignatureFlags.IsIndexer) {
                    result.push(this.signatures[i].toStringHelperEx(shortform, true, scope));
                } else {
                    result.push(this.signatures[i].toStringHelperEx(shortform, false, scope, prefix));
                }
            }
            return result;
        };
        SignatureGroup.prototype.specializeType = function (pattern, replacement, checker) {
            var result = new SignatureGroup();
            if(this.signatures) {
                for(var i = 0, len = this.signatures.length; i < len; i++) {
                    result.addSignature(this.signatures[i].specializeType(pattern, replacement, checker));
                }
            }
            return result;
        };
        SignatureGroup.prototype.verifySignatures = function (checker) {
            var len = 0;
            if(this.signatures && ((len = this.signatures.length) > 0)) {
                for(var i = 0; i < len; i++) {
                    for(var j = i + 1; j < len; j++) {
                        if(this.signatures[i].declAST && this.signatures[j].declAST && (!TypeScript.hasFlag(this.signatures[i].declAST.fncFlags, TypeScript.FncFlags.Definition) && !TypeScript.hasFlag(this.signatures[j].declAST.fncFlags, TypeScript.FncFlags.Definition)) && checker.signaturesAreIdentical(this.signatures[i], this.signatures[j])) {
                            checker.errorReporter.simpleError(this.signatures[i].declAST, (this.signatures[i].declAST && this.signatures[i].declAST.name) ? "Signature for '" + this.signatures[i].declAST.name.actualText + "' is duplicated" : "Signature is duplicated");
                        }
                    }
                    if(this.definitionSignature) {
                        if(!checker.signatureIsAssignableToTarget(this.definitionSignature, this.signatures[i])) {
                            checker.errorReporter.simpleError(this.signatures[i].declAST, "Overload signature is not compatible with function definition");
                        }
                    }
                }
            }
        };
        SignatureGroup.prototype.typeCheck = function (checker, ast, hasConstruct) {
            if(this.hasBeenTypechecked) {
                return;
            }
            this.hasBeenTypechecked = true;
            var len = 0;
            if(this.signatures && ((len = this.signatures.length) > 0)) {
                for(var i = 0; i < len; i++) {
                    if(!hasConstruct && !this.definitionSignature && this.signatures[i].declAST && this.signatures[i].declAST.isOverload && !TypeScript.hasFlag(this.signatures[i].declAST.fncFlags, TypeScript.FncFlags.Ambient)) {
                        checker.errorReporter.simpleError(this.signatures[i].declAST, "Overload declaration lacks definition");
                    }
                    if(this.signatures[i].declAST && this.signatures[i].declAST.isConstructor && this.signatures[i].declAST.classDecl && this.signatures[i].declAST.classDecl.type.symbol.typeCheckStatus == TypeScript.TypeCheckStatus.NotStarted) {
                        checker.typeFlow.typeCheck(this.signatures[i].declAST.classDecl);
                    }
                    checker.typeFlow.typeCheck(this.signatures[i].declAST);
                }
                this.verifySignatures(checker);
            }
        };
        return SignatureGroup;
    })();
    TypeScript.SignatureGroup = SignatureGroup;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (TypeCheckStatus) {
        TypeCheckStatus._map = [];
        TypeCheckStatus._map[0] = "NotStarted";
        TypeCheckStatus.NotStarted = 0;
        TypeCheckStatus._map[1] = "Started";
        TypeCheckStatus.Started = 1;
        TypeCheckStatus._map[2] = "Finished";
        TypeCheckStatus.Finished = 2;
    })(TypeScript.TypeCheckStatus || (TypeScript.TypeCheckStatus = {}));
    var TypeCheckStatus = TypeScript.TypeCheckStatus;
    function aLexicallyEnclosesB(a, b) {
        if(a.declAST && b && b.declAST && a.declAST.nodeType == TypeScript.NodeType.FuncDecl) {
            return a.declAST.minChar <= b.declAST.minChar && a.declAST.limChar >= b.declAST.limChar;
        } else {
            return false;
        }
    }
    TypeScript.aLexicallyEnclosesB = aLexicallyEnclosesB;
    function aEnclosesB(a, b) {
        while(a.container) {
            if(a == b || aLexicallyEnclosesB(a.container, b)) {
                return true;
            }
            a = a.container;
        }
        return false;
    }
    TypeScript.aEnclosesB = aEnclosesB;
    var Symbol = (function () {
        function Symbol(name, location, length, unitIndex) {
            this.name = name;
            this.location = location;
            this.length = length;
            this.unitIndex = unitIndex;
            this.bound = false;
            this.flags = TypeScript.SymbolFlags.None;
            this.isObjectLitField = false;
            this.declAST = null;
            this.declModule = null;
            this.passSymbolCreated = TypeScript.CompilerDiagnostics.analysisPass;
        }
        Symbol.prototype.instanceScope = function () {
            return null;
        };
        Symbol.prototype.isVariable = function () {
            return false;
        };
        Symbol.prototype.isMember = function () {
            return false;
        };
        Symbol.prototype.isInferenceSymbol = function () {
            return false;
        };
        Symbol.prototype.isWith = function () {
            return false;
        };
        Symbol.prototype.writeable = function () {
            return false;
        };
        Symbol.prototype.isType = function () {
            return false;
        };
        Symbol.prototype.getType = function () {
            return null;
        };
        Symbol.prototype.isAccessor = function () {
            return false;
        };
        Symbol.prototype.isInstanceProperty = function () {
            return TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.Property) && (!TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.ModuleMember));
        };
        Symbol.prototype.getTypeName = function (scope) {
            return this.getTypeNameEx(scope).toString();
        };
        Symbol.prototype.getTypeNameEx = function (scope) {
            return TypeScript.MemberName.create(this.toString());
        };
        Symbol.prototype.getOptionalNameString = function () {
            return TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.Optional) ? "?" : "";
        };
        Symbol.prototype.pathToRoot = function () {
            var path = new Array();
            var node = this;
            while(node && (node.name != TypeScript.globalId)) {
                path[path.length] = node;
                node = node.container;
            }
            return path;
        };
        Symbol.prototype.findCommonAncestorPath = function (b) {
            if(this.container == null) {
                return new Array();
            }
            var aPath = this.container.pathToRoot();
            var bPath;
            if(b) {
                bPath = b.pathToRoot();
            } else {
                bPath = new Array();
            }
            var commonNodeIndex = -1;
            for(var i = 0, aLen = aPath.length; i < aLen; i++) {
                var aNode = aPath[i];
                for(var j = 0, bLen = bPath.length; j < bLen; j++) {
                    var bNode = bPath[j];
                    if(aNode == bNode) {
                        commonNodeIndex = i;
                        break;
                    }
                }
                if(commonNodeIndex >= 0) {
                    break;
                }
            }
            if(commonNodeIndex >= 0) {
                return aPath.slice(0, commonNodeIndex);
            } else {
                return aPath;
            }
        };
        Symbol.prototype.getPrettyName = function (scopeSymbol) {
            return this.name;
        };
        Symbol.prototype.scopeRelativeName = function (scope) {
            if(scope == null) {
                return this.getPrettyName(null) + this.getOptionalNameString();
            }
            var lca = this.findCommonAncestorPath(scope.container);
            var builder = "";
            for(var i = 0, len = lca.length; i < len; i++) {
                var prettyName = lca[i].getPrettyName(i == len - 1 ? scope.container : lca[i + 1]);
                builder = prettyName + "." + builder;
            }
            builder += this.getPrettyName(len == 0 ? scope.container : lca[0]) + this.getOptionalNameString();
            return builder;
        };
        Symbol.prototype.fullName = function () {
            var builder = this.name;
            var ancestor = this.container;
            while(ancestor && (ancestor.name != TypeScript.globalId)) {
                builder = ancestor.name + "." + builder;
                ancestor = ancestor.container;
            }
            return builder;
        };
        Symbol.prototype.isExternallyVisible = function (checker) {
            if(this == checker.gloMod) {
                return true;
            }
            if(TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.Private)) {
                return false;
            }
            if(!TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.Exported)) {
                return this.container == checker.gloMod;
            }
            return this.container.isExternallyVisible(checker);
        };
        Symbol.prototype.visible = function (scope, checker) {
            if(checker == null || this.container == checker.gloMod) {
                return true;
            }
            if(TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.ModuleMember)) {
                if(TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.Exported)) {
                    if(!TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.Private)) {
                        return true;
                    } else {
                        return aEnclosesB(this, scope.container);
                    }
                } else {
                    return checker && (checker.currentModDecl == this.declModule) || (checker.currentModDecl && checker.currentModDecl.mod && checker.currentModDecl.mod.symbol && this.declModule && this.declModule.mod && this.declModule.mod.symbol && aEnclosesB(checker.currentModDecl.mod.symbol, this.declModule.mod.symbol));
                }
            } else {
                var isFunction = this.declAST && this.declAST.nodeType == TypeScript.NodeType.FuncDecl;
                var isMethod = isFunction && (this.declAST).isMethod();
                var isStaticFunction = isFunction && TypeScript.hasFlag((this.declAST).fncFlags, TypeScript.FncFlags.Static);
                var isPrivateMethod = isMethod && TypeScript.hasFlag((this.declAST).fncFlags, TypeScript.FncFlags.Private);
                var isAlias = this.isType() && (this).aliasLink;
                if(this.isMember() || isMethod || isStaticFunction || isAlias) {
                    if(TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.Private) || isPrivateMethod) {
                        if(scope.container == null && this.container != scope.container) {
                            return false;
                        } else {
                            return this.container == null ? true : aEnclosesB(scope.container, this.container);
                        }
                    } else {
                        return true;
                    }
                } else {
                    if(this.container) {
                        return aEnclosesB(this, scope.container);
                    } else {
                        return true;
                    }
                }
            }
        };
        Symbol.prototype.addRef = function (identifier) {
            if(!this.refs) {
                this.refs = [];
            }
            this.refs[this.refs.length] = identifier;
        };
        Symbol.prototype.toString = function () {
            if(this.name) {
                return this.name;
            } else {
                return "_anonymous";
            }
        };
        Symbol.prototype.print = function (outfile) {
            outfile.Write(this.toString());
        };
        Symbol.prototype.specializeType = function (pattern, replacement, checker) {
            throw new Error("please implement in derived class");
        };
        Symbol.prototype.setType = function (type) {
            throw new Error("please implement in derived class");
        };
        Symbol.prototype.kind = function () {
            throw new Error("please implement in derived class");
        };
        Symbol.prototype.getInterfaceDeclFromSymbol = function (checker) {
            if(this.declAST != null) {
                if(this.declAST.nodeType == TypeScript.NodeType.InterfaceDeclaration) {
                    return this.declAST;
                } else {
                    if(this.container != null && this.container != checker.gloMod && this.container.declAST.nodeType == TypeScript.NodeType.InterfaceDeclaration) {
                        return this.container.declAST;
                    }
                }
            }
            return null;
        };
        Symbol.prototype.getVarDeclFromSymbol = function () {
            if(this.declAST != null && this.declAST.nodeType == TypeScript.NodeType.VarDecl) {
                return this.declAST;
            }
            return null;
        };
        Symbol.prototype.getDocComments = function () {
            if(this.declAST != null) {
                return this.declAST.getDocComments();
            }
            return [];
        };
        Symbol.prototype.isStatic = function () {
            return TypeScript.hasFlag(this.flags, TypeScript.SymbolFlags.Static);
        };
        return Symbol;
    })();
    TypeScript.Symbol = Symbol;    
    var ValueLocation = (function () {
        function ValueLocation() { }
        return ValueLocation;
    })();
    TypeScript.ValueLocation = ValueLocation;    
    var InferenceSymbol = (function (_super) {
        __extends(InferenceSymbol, _super);
        function InferenceSymbol(name, location, length, unitIndex) {
                _super.call(this, name, location, length, unitIndex);
            this.typeCheckStatus = TypeCheckStatus.NotStarted;
        }
        InferenceSymbol.prototype.isInferenceSymbol = function () {
            return true;
        };
        InferenceSymbol.prototype.transferVarFlags = function (varFlags) {
            if(TypeScript.hasFlag(varFlags, TypeScript.VarFlags.Ambient)) {
                this.flags |= TypeScript.SymbolFlags.Ambient;
            }
            if(TypeScript.hasFlag(varFlags, TypeScript.VarFlags.Constant)) {
                this.flags |= TypeScript.SymbolFlags.Constant;
            }
            if(TypeScript.hasFlag(varFlags, TypeScript.VarFlags.Static)) {
                this.flags |= TypeScript.SymbolFlags.Static;
            }
            if(TypeScript.hasFlag(varFlags, TypeScript.VarFlags.Property)) {
                this.flags |= TypeScript.SymbolFlags.Property;
            }
            if(TypeScript.hasFlag(varFlags, TypeScript.VarFlags.Private)) {
                this.flags |= TypeScript.SymbolFlags.Private;
            }
            if(TypeScript.hasFlag(varFlags, TypeScript.VarFlags.Public)) {
                this.flags |= TypeScript.SymbolFlags.Public;
            }
            if(TypeScript.hasFlag(varFlags, TypeScript.VarFlags.Readonly)) {
                this.flags |= TypeScript.SymbolFlags.Readonly;
            }
            if(TypeScript.hasFlag(varFlags, TypeScript.VarFlags.Exported)) {
                this.flags |= TypeScript.SymbolFlags.Exported;
            }
        };
        return InferenceSymbol;
    })(Symbol);
    TypeScript.InferenceSymbol = InferenceSymbol;    
    var TypeSymbol = (function (_super) {
        __extends(TypeSymbol, _super);
        function TypeSymbol(locName, location, length, unitIndex, type) {
                _super.call(this, locName, location, length, unitIndex);
            this.type = type;
            this.expansions = [];
            this.expansionsDeclAST = [];
            this.isDynamic = false;
            this.isMethod = false;
            this.aliasLink = null;
            this.onlyReferencedAsTypeRef = TypeScript.optimizeModuleCodeGen;
            this.prettyName = this.name;
        }
        TypeSymbol.prototype.addLocation = function (loc) {
            if(this.additionalLocations == null) {
                this.additionalLocations = [];
            }
            this.additionalLocations[this.additionalLocations.length] = loc;
        };
        TypeSymbol.prototype.kind = function () {
            return TypeScript.SymbolKind.Type;
        };
        TypeSymbol.prototype.isType = function () {
            return true;
        };
        TypeSymbol.prototype.getType = function () {
            return this.type;
        };
        TypeSymbol.prototype.getTypeNameEx = function (scope) {
            return this.type.getMemberTypeNameEx(this.name ? this.name + this.getOptionalNameString() : "", false, false, scope);
        };
        TypeSymbol.prototype.instanceScope = function () {
            if(!(this.type.typeFlags & TypeScript.TypeFlags.IsClass) && this.type.isClass()) {
                return this.type.instanceType.constructorScope;
            } else {
                return this.type.containedScope;
            }
        };
        TypeSymbol.prototype.toString = function () {
            var result = this.type.getTypeName();
            if(this.name) {
                result = this.name + ":" + result;
            }
            return result;
        };
        TypeSymbol.prototype.isClass = function () {
            return this.instanceType != null;
        };
        TypeSymbol.prototype.isFunction = function () {
            return this.declAST != null && this.declAST.nodeType == TypeScript.NodeType.FuncDecl;
        };
        TypeSymbol.prototype.specializeType = function (pattern, replacement, checker) {
            if(this.type == pattern) {
                return replacement.symbol;
            } else {
                var replType = this.type.specializeType(pattern, replacement, checker, false);
                if(replType != this.type) {
                    var result = new TypeSymbol(this.name, -1, 0, -1, replType);
                    return result;
                } else {
                    return this;
                }
            }
        };
        TypeSymbol.prototype.getPrettyName = function (scopeSymbol) {
            if(!!scopeSymbol && TypeScript.isQuoted(this.prettyName) && this.type.isModuleType()) {
                var symbolPath = scopeSymbol.pathToRoot();
                var prettyName = this.getPrettyNameOfDynamicModule(symbolPath);
                if(prettyName != null) {
                    return prettyName.name;
                }
            }
            return this.prettyName;
        };
        TypeSymbol.prototype.getPrettyNameOfDynamicModule = function (scopeSymbolPath) {
            var scopeSymbolPathLength = scopeSymbolPath.length;
            var externalSymbol = null;
            if(scopeSymbolPath.length > 0 && scopeSymbolPath[scopeSymbolPathLength - 1].getType().isModuleType() && (scopeSymbolPath[scopeSymbolPathLength - 1]).isDynamic) {
                if(scopeSymbolPathLength > 1 && scopeSymbolPath[scopeSymbolPathLength - 2].getType().isModuleType() && (scopeSymbolPath[scopeSymbolPathLength - 2]).isDynamic) {
                    var moduleType = scopeSymbolPath[scopeSymbolPathLength - 2].getType();
                    externalSymbol = moduleType.findDynamicModuleName(this.type);
                }
                if(externalSymbol == null) {
                    var moduleType = scopeSymbolPath[scopeSymbolPathLength - 1].getType();
                    externalSymbol = moduleType.findDynamicModuleName(this.type);
                }
            }
            return externalSymbol;
        };
        TypeSymbol.prototype.getDocComments = function () {
            var comments = [];
            if(this.declAST != null) {
                comments = comments.concat(this.declAST.getDocComments());
            }
            for(var i = 0; i < this.expansionsDeclAST.length; i++) {
                comments = comments.concat(this.expansionsDeclAST[i].getDocComments());
            }
            return comments;
        };
        return TypeSymbol;
    })(InferenceSymbol);
    TypeScript.TypeSymbol = TypeSymbol;    
    var WithSymbol = (function (_super) {
        __extends(WithSymbol, _super);
        function WithSymbol(location, unitIndex, withType) {
                _super.call(this, "with", location, 4, unitIndex, withType);
        }
        WithSymbol.prototype.isWith = function () {
            return true;
        };
        return WithSymbol;
    })(TypeSymbol);
    TypeScript.WithSymbol = WithSymbol;    
    var FieldSymbol = (function (_super) {
        __extends(FieldSymbol, _super);
        function FieldSymbol(name, location, unitIndex, canWrite, field) {
                _super.call(this, name, location, name.length, unitIndex);
            this.canWrite = canWrite;
            this.field = field;
            this.getter = null;
            this.setter = null;
            this.hasBeenEmitted = false;
            this.name = name;
            this.location = location;
        }
        FieldSymbol.prototype.kind = function () {
            return TypeScript.SymbolKind.Field;
        };
        FieldSymbol.prototype.writeable = function () {
            return this.isAccessor() ? this.setter != null : this.canWrite;
        };
        FieldSymbol.prototype.getType = function () {
            return this.field.typeLink.type;
        };
        FieldSymbol.prototype.getTypeNameEx = function (scope) {
            return TypeScript.MemberName.create(this.field.typeLink.type.getScopedTypeNameEx(scope), this.name + this.getOptionalNameString() + ": ", "");
        };
        FieldSymbol.prototype.isMember = function () {
            return true;
        };
        FieldSymbol.prototype.setType = function (type) {
            this.field.typeLink.type = type;
        };
        FieldSymbol.prototype.isAccessor = function () {
            return this.getter != null || this.setter != null;
        };
        FieldSymbol.prototype.isVariable = function () {
            return true;
        };
        FieldSymbol.prototype.toString = function () {
            return this.getTypeNameEx(null).toString();
        };
        FieldSymbol.prototype.specializeType = function (pattern, replacement, checker) {
            var rType = this.field.typeLink.type.specializeType(pattern, replacement, checker, false);
            if(rType != this.field.typeLink.type) {
                var fieldDef = new ValueLocation();
                var result = new FieldSymbol(this.name, 0, checker.locationInfo.unitIndex, this.canWrite, fieldDef);
                result.flags = this.flags;
                fieldDef.symbol = result;
                fieldDef.typeLink = new TypeScript.TypeLink();
                result.setType(rType);
                result.typeCheckStatus = TypeCheckStatus.Finished;
                return result;
            } else {
                return this;
            }
        };
        FieldSymbol.prototype.getDocComments = function () {
            if(this.getter != null || this.setter != null) {
                var comments = [];
                if(this.getter != null) {
                    comments = comments.concat(this.getter.getDocComments());
                }
                if(this.setter != null) {
                    comments = comments.concat(this.setter.getDocComments());
                }
                return comments;
            } else {
                if(this.declAST != null) {
                    return this.declAST.getDocComments();
                }
            }
            return [];
        };
        return FieldSymbol;
    })(InferenceSymbol);
    TypeScript.FieldSymbol = FieldSymbol;    
    var ParameterSymbol = (function (_super) {
        __extends(ParameterSymbol, _super);
        function ParameterSymbol(name, location, unitIndex, parameter) {
                _super.call(this, name, location, name.length, unitIndex);
            this.parameter = parameter;
            this.paramDocComment = null;
            this.funcDecl = null;
            this.argsOffset = (-1);
            this.name = name;
            this.location = location;
        }
        ParameterSymbol.prototype.kind = function () {
            return TypeScript.SymbolKind.Parameter;
        };
        ParameterSymbol.prototype.writeable = function () {
            return true;
        };
        ParameterSymbol.prototype.getType = function () {
            return this.parameter.typeLink.type;
        };
        ParameterSymbol.prototype.setType = function (type) {
            this.parameter.typeLink.type = type;
        };
        ParameterSymbol.prototype.isVariable = function () {
            return true;
        };
        ParameterSymbol.prototype.isOptional = function () {
            if(this.parameter && this.parameter.symbol && this.parameter.symbol.declAST) {
                return (this.parameter.symbol.declAST).isOptional;
            } else {
                return false;
            }
        };
        ParameterSymbol.prototype.getTypeNameEx = function (scope) {
            return TypeScript.MemberName.create(this.getType().getScopedTypeNameEx(scope), this.name + (this.isOptional() ? "?" : "") + ": ", "");
        };
        ParameterSymbol.prototype.toString = function () {
            return this.getTypeNameEx(null).toString();
        };
        ParameterSymbol.prototype.specializeType = function (pattern, replacement, checker) {
            var rType = this.parameter.typeLink.type.specializeType(pattern, replacement, checker, false);
            if(this.parameter.typeLink.type != rType) {
                var paramDef = new ValueLocation();
                var result = new ParameterSymbol(this.name, 0, checker.locationInfo.unitIndex, paramDef);
                paramDef.symbol = result;
                result.setType(rType);
                return result;
            } else {
                return this;
            }
        };
        ParameterSymbol.prototype.getParameterDocComments = function () {
            if(!this.paramDocComment) {
                var parameterComments = [];
                if(this.funcDecl) {
                    var fncDocComments = this.funcDecl.getDocComments();
                    var paramComment = TypeScript.Comment.getParameterDocCommentText(this.name, fncDocComments);
                    if(paramComment != "") {
                        parameterComments.push(paramComment);
                    }
                }
                var docComments = TypeScript.Comment.getDocCommentText(this.getDocComments());
                if(docComments != "") {
                    parameterComments.push(docComments);
                }
                this.paramDocComment = parameterComments.join("\n");
            }
            return this.paramDocComment;
        };
        return ParameterSymbol;
    })(InferenceSymbol);
    TypeScript.ParameterSymbol = ParameterSymbol;    
    var VariableSymbol = (function (_super) {
        __extends(VariableSymbol, _super);
        function VariableSymbol(name, location, unitIndex, variable) {
                _super.call(this, name, location, name.length, unitIndex);
            this.variable = variable;
        }
        VariableSymbol.prototype.kind = function () {
            return TypeScript.SymbolKind.Variable;
        };
        VariableSymbol.prototype.writeable = function () {
            return true;
        };
        VariableSymbol.prototype.getType = function () {
            return this.variable.typeLink.type;
        };
        VariableSymbol.prototype.getTypeNameEx = function (scope) {
            return TypeScript.MemberName.create(this.getType().getScopedTypeNameEx(scope), this.name + ": ", "");
        };
        VariableSymbol.prototype.setType = function (type) {
            this.variable.typeLink.type = type;
        };
        VariableSymbol.prototype.isVariable = function () {
            return true;
        };
        return VariableSymbol;
    })(InferenceSymbol);
    TypeScript.VariableSymbol = VariableSymbol;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var ScopedMembers = (function () {
        function ScopedMembers(dualMembers) {
            this.dualMembers = dualMembers;
            this.allMembers = this.dualMembers;
            this.publicMembers = this.dualMembers.primaryTable;
            this.privateMembers = this.dualMembers.secondaryTable;
        }
        ScopedMembers.prototype.addPublicMember = function (key, data) {
            return this.dualMembers.primaryTable.add(key, data);
        };
        ScopedMembers.prototype.addPrivateMember = function (key, data) {
            return this.dualMembers.secondaryTable.add(key, data);
        };
        return ScopedMembers;
    })();
    TypeScript.ScopedMembers = ScopedMembers;    
    (function (SymbolKind) {
        SymbolKind._map = [];
        SymbolKind._map[0] = "None";
        SymbolKind.None = 0;
        SymbolKind._map[1] = "Type";
        SymbolKind.Type = 1;
        SymbolKind._map[2] = "Field";
        SymbolKind.Field = 2;
        SymbolKind._map[3] = "Parameter";
        SymbolKind.Parameter = 3;
        SymbolKind._map[4] = "Variable";
        SymbolKind.Variable = 4;
    })(TypeScript.SymbolKind || (TypeScript.SymbolKind = {}));
    var SymbolKind = TypeScript.SymbolKind;
    var SymbolScope = (function () {
        function SymbolScope(container) {
            this.container = container;
        }
        SymbolScope.prototype.printLabel = function () {
            return "base";
        };
        SymbolScope.prototype.getAllSymbolNames = function (members) {
            return [
                "please", 
                "implement", 
                "in", 
                "derived", 
                "classes"
            ];
        };
        SymbolScope.prototype.getAllTypeSymbolNames = function (members) {
            return [
                "please", 
                "implement", 
                "in", 
                "derived", 
                "classes"
            ];
        };
        SymbolScope.prototype.getAllValueSymbolNames = function (members) {
            return [
                "please", 
                "implement", 
                "in", 
                "derived", 
                "classes"
            ];
        };
        SymbolScope.prototype.search = function (filter, name, publicOnly, typespace) {
            return null;
        };
        SymbolScope.prototype.findLocal = function (name, publicOnly, typespace) {
            return null;
        };
        SymbolScope.prototype.find = function (name, publicOnly, typespace) {
            return null;
        };
        SymbolScope.prototype.findImplementation = function (name, publicOnly, typespace) {
            return null;
        };
        SymbolScope.prototype.findAmbient = function (name, publicOnly, typespace) {
            return null;
        };
        SymbolScope.prototype.print = function (outfile) {
            if(this.container) {
                outfile.WriteLine(this.printLabel() + " scope with container: " + this.container.name + "...");
            } else {
                outfile.WriteLine(this.printLabel() + " scope...");
            }
        };
        SymbolScope.prototype.enter = function (container, ast, symbol, errorReporter, publicOnly, typespace, ambient) {
            throw new Error("please implement in derived class");
        };
        SymbolScope.prototype.getTable = function () {
            throw new Error("please implement in derived class");
        };
        return SymbolScope;
    })();
    TypeScript.SymbolScope = SymbolScope;    
    function symbolCanBeUsed(sym, publicOnly) {
        return publicOnly ? !(TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Private) || (sym.declAST && sym.declAST.nodeType == TypeScript.NodeType.FuncDecl && TypeScript.hasFlag((sym.declAST).fncFlags, TypeScript.FncFlags.Private))) : true;
    }
    var SymbolAggregateScope = (function (_super) {
        __extends(SymbolAggregateScope, _super);
        function SymbolAggregateScope(container) {
                _super.call(this, container);
            this.valueCache = null;
            this.valueImplCache = null;
            this.valueAmbientCache = null;
            this.typeCache = null;
            this.typeImplCache = null;
            this.typeAmbientCache = null;
            this.parents = null;
            this.container = container;
        }
        SymbolAggregateScope.prototype.printLabel = function () {
            return "agg";
        };
        SymbolAggregateScope.prototype.search = function (filter, name, publicOnly, typespace) {
            if(this.parents) {
                for(var i = 0; i < this.parents.length; i++) {
                    var sym = this.parents[i].search(filter, name, publicOnly, typespace);
                    if(sym) {
                        if(filter.update(sym)) {
                            return sym;
                        }
                    }
                }
            }
            return filter.result;
        };
        SymbolAggregateScope.prototype.getAllSymbolNames = function (members) {
            var result = [];
            if(this.parents) {
                for(var i = 0; i < this.parents.length; i++) {
                    var parentResult = this.parents[i].getAllSymbolNames(members);
                    if(parentResult) {
                        result = result.concat(parentResult);
                    }
                }
            }
            return result;
        };
        SymbolAggregateScope.prototype.getAllTypeSymbolNames = function (members) {
            var result = [];
            if(this.parents) {
                for(var i = 0; i < this.parents.length; i++) {
                    var parentResult = this.parents[i].getAllTypeSymbolNames(members);
                    if(parentResult) {
                        result = result.concat(parentResult);
                    }
                }
            }
            return result;
        };
        SymbolAggregateScope.prototype.getAllValueSymbolNames = function (members) {
            var result = [];
            if(this.parents) {
                for(var i = 0; i < this.parents.length; i++) {
                    var parentResult = this.parents[i].getAllValueSymbolNames(members);
                    if(parentResult) {
                        result = result.concat(parentResult);
                    }
                }
            }
            return result;
        };
        SymbolAggregateScope.prototype.print = function (outfile) {
            _super.prototype.print.call(this, outfile);
            if(this.parents) {
                for(var i = 0; i < this.parents.length; i++) {
                    this.parents[i].print(outfile);
                }
            }
        };
        SymbolAggregateScope.prototype.findImplementation = function (name, publicOnly, typespace) {
            var sym = null;
            var i = 0;
            var implCache = this.valueImplCache;
            if(typespace) {
                implCache = this.typeImplCache;
            }
            if(implCache && ((sym = implCache.lookup(name)) != null) && (publicOnly ? !(TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Private) || (sym.declAST && sym.declAST.nodeType == TypeScript.NodeType.FuncDecl && TypeScript.hasFlag((sym.declAST).fncFlags, TypeScript.FncFlags.Private))) : true)) {
                return sym;
            }
            if(this.parents) {
                for(i = 0; i < this.parents.length; i++) {
                    sym = this.parents[i].findImplementation(name, publicOnly, typespace);
                    if(sym) {
                        break;
                    }
                }
            }
            if(implCache) {
                if(typespace) {
                    this.typeImplCache = new TypeScript.StringHashTable();
                    implCache = this.typeImplCache;
                } else {
                    this.valueImplCache = new TypeScript.StringHashTable();
                    implCache = this.valueImplCache;
                }
            }
            implCache.add(name, sym);
            return sym;
        };
        SymbolAggregateScope.prototype.find = function (name, publicOnly, typespace) {
            var sym = null;
            var i = 0;
            var cache = this.valueCache;
            if(typespace) {
                cache = this.typeCache;
            }
            if(cache && ((sym = cache.lookup(name)) != null) && (publicOnly ? !(TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.Private) || (sym.declAST && sym.declAST.nodeType == TypeScript.NodeType.FuncDecl && TypeScript.hasFlag((sym.declAST).fncFlags, TypeScript.FncFlags.Private))) : true)) {
                return sym;
            }
            if(this.parents) {
                for(i = 0; i < this.parents.length; i++) {
                    sym = this.parents[i].find(name, publicOnly, typespace);
                    if(sym) {
                        break;
                    }
                }
            }
            if(cache == null) {
                if(typespace) {
                    this.typeCache = new TypeScript.StringHashTable();
                    cache = this.typeCache;
                } else {
                    this.valueCache = new TypeScript.StringHashTable();
                    cache = this.valueCache;
                }
            }
            cache.add(name, sym);
            return sym;
        };
        SymbolAggregateScope.prototype.findAmbient = function (name, publicOnly, typespace) {
            var sym = null;
            var i = 0;
            var cache = this.valueAmbientCache;
            if(typespace) {
                cache = this.typeAmbientCache;
            }
            if(cache && ((sym = cache.lookup(name)) != null)) {
                return sym;
            }
            if(this.parents) {
                for(i = 0; i < this.parents.length; i++) {
                    sym = this.parents[i].findAmbient(name, publicOnly, typespace);
                    if(sym) {
                        break;
                    }
                }
            }
            if(cache == null) {
                if(typespace) {
                    this.typeAmbientCache = new TypeScript.StringHashTable();
                    cache = this.typeAmbientCache;
                } else {
                    this.valueAmbientCache = new TypeScript.StringHashTable();
                    cache = this.valueAmbientCache;
                }
            }
            cache.add(name, sym);
            return sym;
        };
        SymbolAggregateScope.prototype.addParentScope = function (parent) {
            if(this.parents == null) {
                this.parents = new Array();
            }
            this.parents[this.parents.length] = parent;
        };
        return SymbolAggregateScope;
    })(SymbolScope);
    TypeScript.SymbolAggregateScope = SymbolAggregateScope;    
    var SymbolTableScope = (function (_super) {
        __extends(SymbolTableScope, _super);
        function SymbolTableScope(valueMembers, ambientValueMembers, enclosedTypes, ambientEnclosedTypes, container) {
                _super.call(this, container);
            this.valueMembers = valueMembers;
            this.ambientValueMembers = ambientValueMembers;
            this.enclosedTypes = enclosedTypes;
            this.ambientEnclosedTypes = ambientEnclosedTypes;
            this.container = container;
        }
        SymbolTableScope.prototype.printLabel = function () {
            return "table";
        };
        SymbolTableScope.prototype.getAllSymbolNames = function (members) {
            var result = this.getAllTypeSymbolNames(members);
            return result.concat(this.getAllValueSymbolNames(members));
        };
        SymbolTableScope.prototype.getAllTypeSymbolNames = function (members) {
            var result = [];
            if(this.ambientEnclosedTypes) {
                result = result.concat(this.ambientEnclosedTypes.allMembers.getAllKeys());
            }
            if(this.enclosedTypes) {
                result = result.concat(this.enclosedTypes.allMembers.getAllKeys());
            }
            return result;
        };
        SymbolTableScope.prototype.getAllValueSymbolNames = function (members) {
            var result = [];
            if(this.ambientValueMembers) {
                result = result.concat(this.ambientValueMembers.allMembers.getAllKeys());
            }
            if(this.valueMembers) {
                result = result.concat(this.valueMembers.allMembers.getAllKeys());
            }
            return result;
        };
        SymbolTableScope.prototype.search = function (filter, name, publicOnly, typespace) {
            var sym = this.find(name, publicOnly, typespace);
            filter.update(sym);
            return filter.result;
        };
        SymbolTableScope.prototype.find = function (name, publicOnly, typespace) {
            var table = null;
            var ambientTable = null;
            if(typespace) {
                table = (this.enclosedTypes == null) ? null : publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;
                ambientTable = (this.ambientEnclosedTypes == null) ? null : publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;
            } else {
                table = (this.valueMembers == null) ? null : publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;
                ambientTable = (this.ambientValueMembers == null) ? null : publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;
            }
            if(ambientTable) {
                var s = ambientTable.lookup(name);
                if(s) {
                    return s;
                }
            }
            if(table) {
                var s = table.lookup(name);
                if(s) {
                    return s;
                }
            }
            return null;
        };
        SymbolTableScope.prototype.findAmbient = function (name, publicOnly, typespace) {
            var ambientTable = (this.ambientValueMembers == null) ? null : publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;
            if(typespace) {
                ambientTable = (this.ambientEnclosedTypes == null) ? null : publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;
            }
            if(ambientTable) {
                var s = ambientTable.lookup(name);
                if(s) {
                    return s;
                }
            }
            return null;
        };
        SymbolTableScope.prototype.print = function (outfile) {
            _super.prototype.print.call(this, outfile);
            if(this.ambientValueMembers) {
                this.ambientValueMembers.allMembers.map(function (key, sym, context) {
                    outfile.WriteLine("  " + key);
                }, null);
            }
            if(this.valueMembers) {
                this.valueMembers.allMembers.map(function (key, sym, context) {
                    outfile.WriteLine("  " + key);
                }, null);
            }
            if(this.ambientEnclosedTypes) {
                this.ambientEnclosedTypes.allMembers.map(function (key, sym, context) {
                    outfile.WriteLine("  " + key);
                }, null);
            }
            if(this.enclosedTypes) {
                this.enclosedTypes.allMembers.map(function (key, sym, context) {
                    outfile.WriteLine("  " + key);
                }, null);
            }
        };
        SymbolTableScope.prototype.findImplementation = function (name, publicOnly, typespace) {
            var sym = this.find(name, publicOnly, typespace);
            if(sym) {
                if(sym.kind() == SymbolKind.Type) {
                    var typeSym = sym;
                    if(!typeSym.type.hasImplementation()) {
                        sym = null;
                    }
                } else {
                    if(sym.container) {
                        if(sym.container.kind() == SymbolKind.Type) {
                            var ctypeSym = sym.container;
                            if(!ctypeSym.type.hasImplementation()) {
                                sym = null;
                            }
                        }
                    }
                }
            }
            return sym;
        };
        SymbolTableScope.prototype.getTable = function () {
            return this.valueMembers.publicMembers;
        };
        return SymbolTableScope;
    })(SymbolScope);
    TypeScript.SymbolTableScope = SymbolTableScope;    
    var SymbolScopeBuilder = (function (_super) {
        __extends(SymbolScopeBuilder, _super);
        function SymbolScopeBuilder(valueMembers, ambientValueMembers, enclosedTypes, ambientEnclosedTypes, parent, container) {
                _super.call(this, container);
            this.valueMembers = valueMembers;
            this.ambientValueMembers = ambientValueMembers;
            this.enclosedTypes = enclosedTypes;
            this.ambientEnclosedTypes = ambientEnclosedTypes;
            this.parent = parent;
            this.container = container;
        }
        SymbolScopeBuilder.prototype.printLabel = function () {
            return "builder";
        };
        SymbolScopeBuilder.prototype.getAllSymbolNames = function (members) {
            var result = this.getAllTypeSymbolNames(members);
            return result.concat(this.getAllValueSymbolNames(members));
        };
        SymbolScopeBuilder.prototype.getAllTypeSymbolNames = function (members) {
            var result = [];
            if(this.ambientEnclosedTypes) {
                result = result.concat(this.ambientEnclosedTypes.allMembers.getAllKeys());
            }
            if(this.enclosedTypes) {
                result = result.concat(this.enclosedTypes.allMembers.getAllKeys());
            }
            if(!members && this.parent) {
                var parentResult = this.parent.getAllTypeSymbolNames(members);
                if(parentResult) {
                    result = result.concat(parentResult);
                }
            }
            return result;
        };
        SymbolScopeBuilder.prototype.getAllValueSymbolNames = function (members) {
            var result = [];
            if(this.ambientValueMembers) {
                result = result.concat(this.ambientValueMembers.allMembers.getAllKeys());
            }
            if(this.valueMembers) {
                result = result.concat(this.valueMembers.allMembers.getAllKeys());
            }
            if(!members && this.parent) {
                var parentResult = this.parent.getAllValueSymbolNames(members);
                if(parentResult) {
                    result = result.concat(parentResult);
                }
            }
            return result;
        };
        SymbolScopeBuilder.prototype.search = function (filter, name, publicOnly, typespace) {
            var sym = null;
            var table = (this.valueMembers == null) ? null : publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;
            var ambientTable = (this.ambientValueMembers == null) ? null : publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;
            if(typespace) {
                table = (this.enclosedTypes == null) ? null : publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;
                ambientTable = (this.ambientEnclosedTypes == null) ? null : publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;
            }
            if(ambientTable) {
                if((sym = ambientTable.lookup(name)) != null) {
                    if(filter.update(sym)) {
                        return sym;
                    }
                }
            }
            if(table) {
                if((sym = table.lookup(name)) != null) {
                    if(filter.update(sym)) {
                        return sym;
                    }
                }
            }
            if(this.parent) {
                sym = this.parent.search(filter, name, publicOnly, typespace);
                if(sym) {
                    if(filter.update(sym)) {
                        return sym;
                    }
                }
            }
            return filter.result;
        };
        SymbolScopeBuilder.prototype.print = function (outfile) {
            _super.prototype.print.call(this, outfile);
            if(this.ambientValueMembers) {
                this.ambientValueMembers.allMembers.map(function (key, s, context) {
                    var sym = s;
                    outfile.WriteLine("  " + key);
                }, null);
            }
            if(this.valueMembers) {
                this.valueMembers.allMembers.map(function (key, s, context) {
                    var sym = s;
                    outfile.WriteLine("  " + key);
                }, null);
            }
            if(this.ambientEnclosedTypes) {
                this.ambientEnclosedTypes.allMembers.map(function (key, s, context) {
                    var sym = s;
                    outfile.WriteLine("  " + key);
                }, null);
            }
            if(this.enclosedTypes) {
                this.enclosedTypes.allMembers.map(function (key, s, context) {
                    var sym = s;
                    outfile.WriteLine("  " + key);
                }, null);
            }
            if(this.parent) {
                this.parent.print(outfile);
            }
        };
        SymbolScopeBuilder.prototype.find = function (name, publicOnly, typespace) {
            var sym = null;
            var table = (this.valueMembers == null) ? null : publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;
            var ambientTable = (this.ambientValueMembers == null) ? null : publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;
            if(typespace) {
                table = (this.enclosedTypes == null) ? null : publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;
                ambientTable = (this.ambientEnclosedTypes == null) ? null : publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;
            }
            if(ambientTable && ((sym = ambientTable.lookup(name)) != null)) {
                return sym;
            }
            if(table && ((sym = table.lookup(name)) != null)) {
                return sym;
            }
            if(this.parent) {
                return this.parent.find(name, publicOnly, typespace);
            }
            return null;
        };
        SymbolScopeBuilder.prototype.findAmbient = function (name, publicOnly, typespace) {
            var sym = null;
            var ambientTable = (this.ambientValueMembers == null) ? null : publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;
            if(typespace) {
                ambientTable = (this.ambientEnclosedTypes == null) ? null : publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;
            }
            if(ambientTable && ((sym = ambientTable.lookup(name)) != null)) {
                return sym;
            }
            if(this.parent) {
                return this.parent.findAmbient(name, publicOnly, typespace);
            }
            return null;
        };
        SymbolScopeBuilder.prototype.findLocal = function (name, publicOnly, typespace) {
            var sym = null;
            var table = (this.valueMembers == null) ? null : publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;
            var ambientTable = (this.ambientValueMembers == null) ? null : publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;
            if(typespace) {
                table = (this.enclosedTypes == null) ? null : publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;
                ambientTable = (this.ambientEnclosedTypes == null) ? null : publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;
            }
            if(table) {
                if((sym = table.lookup(name)) != null) {
                    if(sym) {
                        return sym;
                    }
                }
            }
            if(ambientTable) {
                if((sym = ambientTable.lookup(name)) != null) {
                    if(sym) {
                        return sym;
                    }
                }
            }
            return null;
        };
        SymbolScopeBuilder.prototype.enter = function (container, ast, symbol, errorReporter, insertAsPublic, typespace, ambient) {
            var table = null;
            if(ambient) {
                if(typespace) {
                    table = (this.ambientEnclosedTypes == null) ? null : insertAsPublic ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.privateMembers;
                } else {
                    table = (this.ambientValueMembers == null) ? null : insertAsPublic ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.privateMembers;
                }
            } else {
                if(typespace) {
                    table = (this.enclosedTypes == null) ? null : insertAsPublic ? this.enclosedTypes.publicMembers : this.enclosedTypes.privateMembers;
                } else {
                    table = (this.valueMembers == null) ? null : insertAsPublic ? this.valueMembers.publicMembers : this.valueMembers.privateMembers;
                }
            }
            if(table) {
                if(!table.add(symbol.name, symbol)) {
                    errorReporter.duplicateIdentifier(ast, symbol.name);
                }
            } else {
                TypeScript.CompilerDiagnostics.Alert("YYYYY");
            }
            symbol.container = container;
        };
        SymbolScopeBuilder.prototype.getTable = function () {
            return this.valueMembers.allMembers;
        };
        return SymbolScopeBuilder;
    })(SymbolScope);
    TypeScript.SymbolScopeBuilder = SymbolScopeBuilder;    
    var FilteredSymbolScope = (function (_super) {
        __extends(FilteredSymbolScope, _super);
        function FilteredSymbolScope(scope, container, filter) {
                _super.call(this, container);
            this.scope = scope;
            this.filter = filter;
        }
        FilteredSymbolScope.prototype.print = function (outfile) {
            this.scope.print(outfile);
        };
        FilteredSymbolScope.prototype.find = function (name, publicOnly, typespace) {
            this.filter.reset();
            return this.scope.search(this.filter, name, publicOnly, typespace);
        };
        FilteredSymbolScope.prototype.findLocal = function (name, publicOnly, typespace) {
            return this.scope.findLocal(name, publicOnly, typespace);
        };
        return FilteredSymbolScope;
    })(SymbolScope);
    TypeScript.FilteredSymbolScope = FilteredSymbolScope;    
    var FilteredSymbolScopeBuilder = (function (_super) {
        __extends(FilteredSymbolScopeBuilder, _super);
        function FilteredSymbolScopeBuilder(valueMembers, parent, container, filter) {
                _super.call(this, valueMembers, null, null, null, parent, container);
            this.filter = filter;
        }
        FilteredSymbolScopeBuilder.prototype.findLocal = function (name, publicOnly, typespace) {
            var sym = _super.prototype.findLocal.call(this, name, publicOnly, typespace);
            if(sym) {
                if(!this.filter(sym)) {
                    return null;
                }
            }
            return sym;
        };
        FilteredSymbolScopeBuilder.prototype.search = function (filter, name, publicOnly, typespace) {
            throw new Error("please implement");
        };
        FilteredSymbolScopeBuilder.prototype.find = function (name, publicOnly, typespace) {
            var sym = _super.prototype.findLocal.call(this, name, publicOnly, typespace);
            if(sym) {
                if(!this.filter(sym)) {
                    return null;
                }
            }
            return _super.prototype.find.call(this, name, publicOnly, typespace);
        };
        return FilteredSymbolScopeBuilder;
    })(SymbolScopeBuilder);
    TypeScript.FilteredSymbolScopeBuilder = FilteredSymbolScopeBuilder;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (TokenID) {
        TokenID._map = [];
        TokenID._map[0] = "Any";
        TokenID.Any = 0;
        TokenID._map[1] = "Bool";
        TokenID.Bool = 1;
        TokenID._map[2] = "Break";
        TokenID.Break = 2;
        TokenID._map[3] = "Case";
        TokenID.Case = 3;
        TokenID._map[4] = "Catch";
        TokenID.Catch = 4;
        TokenID._map[5] = "Class";
        TokenID.Class = 5;
        TokenID._map[6] = "Const";
        TokenID.Const = 6;
        TokenID._map[7] = "Continue";
        TokenID.Continue = 7;
        TokenID._map[8] = "Debugger";
        TokenID.Debugger = 8;
        TokenID._map[9] = "Default";
        TokenID.Default = 9;
        TokenID._map[10] = "Delete";
        TokenID.Delete = 10;
        TokenID._map[11] = "Do";
        TokenID.Do = 11;
        TokenID._map[12] = "Else";
        TokenID.Else = 12;
        TokenID._map[13] = "Enum";
        TokenID.Enum = 13;
        TokenID._map[14] = "Export";
        TokenID.Export = 14;
        TokenID._map[15] = "Extends";
        TokenID.Extends = 15;
        TokenID._map[16] = "Declare";
        TokenID.Declare = 16;
        TokenID._map[17] = "False";
        TokenID.False = 17;
        TokenID._map[18] = "Finally";
        TokenID.Finally = 18;
        TokenID._map[19] = "For";
        TokenID.For = 19;
        TokenID._map[20] = "Function";
        TokenID.Function = 20;
        TokenID._map[21] = "Constructor";
        TokenID.Constructor = 21;
        TokenID._map[22] = "Get";
        TokenID.Get = 22;
        TokenID._map[23] = "If";
        TokenID.If = 23;
        TokenID._map[24] = "Implements";
        TokenID.Implements = 24;
        TokenID._map[25] = "Import";
        TokenID.Import = 25;
        TokenID._map[26] = "In";
        TokenID.In = 26;
        TokenID._map[27] = "InstanceOf";
        TokenID.InstanceOf = 27;
        TokenID._map[28] = "Interface";
        TokenID.Interface = 28;
        TokenID._map[29] = "Let";
        TokenID.Let = 29;
        TokenID._map[30] = "Module";
        TokenID.Module = 30;
        TokenID._map[31] = "New";
        TokenID.New = 31;
        TokenID._map[32] = "Number";
        TokenID.Number = 32;
        TokenID._map[33] = "Null";
        TokenID.Null = 33;
        TokenID._map[34] = "Package";
        TokenID.Package = 34;
        TokenID._map[35] = "Private";
        TokenID.Private = 35;
        TokenID._map[36] = "Protected";
        TokenID.Protected = 36;
        TokenID._map[37] = "Public";
        TokenID.Public = 37;
        TokenID._map[38] = "Return";
        TokenID.Return = 38;
        TokenID._map[39] = "Set";
        TokenID.Set = 39;
        TokenID._map[40] = "Static";
        TokenID.Static = 40;
        TokenID._map[41] = "String";
        TokenID.String = 41;
        TokenID._map[42] = "Super";
        TokenID.Super = 42;
        TokenID._map[43] = "Switch";
        TokenID.Switch = 43;
        TokenID._map[44] = "This";
        TokenID.This = 44;
        TokenID._map[45] = "Throw";
        TokenID.Throw = 45;
        TokenID._map[46] = "True";
        TokenID.True = 46;
        TokenID._map[47] = "Try";
        TokenID.Try = 47;
        TokenID._map[48] = "TypeOf";
        TokenID.TypeOf = 48;
        TokenID._map[49] = "Var";
        TokenID.Var = 49;
        TokenID._map[50] = "Void";
        TokenID.Void = 50;
        TokenID._map[51] = "With";
        TokenID.With = 51;
        TokenID._map[52] = "While";
        TokenID.While = 52;
        TokenID._map[53] = "Yield";
        TokenID.Yield = 53;
        TokenID._map[54] = "Semicolon";
        TokenID.Semicolon = 54;
        TokenID._map[55] = "OpenParen";
        TokenID.OpenParen = 55;
        TokenID._map[56] = "CloseParen";
        TokenID.CloseParen = 56;
        TokenID._map[57] = "OpenBracket";
        TokenID.OpenBracket = 57;
        TokenID._map[58] = "CloseBracket";
        TokenID.CloseBracket = 58;
        TokenID._map[59] = "OpenBrace";
        TokenID.OpenBrace = 59;
        TokenID._map[60] = "CloseBrace";
        TokenID.CloseBrace = 60;
        TokenID._map[61] = "Comma";
        TokenID.Comma = 61;
        TokenID._map[62] = "Equals";
        TokenID.Equals = 62;
        TokenID._map[63] = "PlusEquals";
        TokenID.PlusEquals = 63;
        TokenID._map[64] = "MinusEquals";
        TokenID.MinusEquals = 64;
        TokenID._map[65] = "AsteriskEquals";
        TokenID.AsteriskEquals = 65;
        TokenID._map[66] = "SlashEquals";
        TokenID.SlashEquals = 66;
        TokenID._map[67] = "PercentEquals";
        TokenID.PercentEquals = 67;
        TokenID._map[68] = "AmpersandEquals";
        TokenID.AmpersandEquals = 68;
        TokenID._map[69] = "CaretEquals";
        TokenID.CaretEquals = 69;
        TokenID._map[70] = "BarEquals";
        TokenID.BarEquals = 70;
        TokenID._map[71] = "LessThanLessThanEquals";
        TokenID.LessThanLessThanEquals = 71;
        TokenID._map[72] = "GreaterThanGreaterThanEquals";
        TokenID.GreaterThanGreaterThanEquals = 72;
        TokenID._map[73] = "GreaterThanGreaterThanGreaterThanEquals";
        TokenID.GreaterThanGreaterThanGreaterThanEquals = 73;
        TokenID._map[74] = "Question";
        TokenID.Question = 74;
        TokenID._map[75] = "Colon";
        TokenID.Colon = 75;
        TokenID._map[76] = "BarBar";
        TokenID.BarBar = 76;
        TokenID._map[77] = "AmpersandAmpersand";
        TokenID.AmpersandAmpersand = 77;
        TokenID._map[78] = "Bar";
        TokenID.Bar = 78;
        TokenID._map[79] = "Caret";
        TokenID.Caret = 79;
        TokenID._map[80] = "And";
        TokenID.And = 80;
        TokenID._map[81] = "EqualsEquals";
        TokenID.EqualsEquals = 81;
        TokenID._map[82] = "ExclamationEquals";
        TokenID.ExclamationEquals = 82;
        TokenID._map[83] = "EqualsEqualsEquals";
        TokenID.EqualsEqualsEquals = 83;
        TokenID._map[84] = "ExclamationEqualsEquals";
        TokenID.ExclamationEqualsEquals = 84;
        TokenID._map[85] = "LessThan";
        TokenID.LessThan = 85;
        TokenID._map[86] = "LessThanEquals";
        TokenID.LessThanEquals = 86;
        TokenID._map[87] = "GreaterThan";
        TokenID.GreaterThan = 87;
        TokenID._map[88] = "GreaterThanEquals";
        TokenID.GreaterThanEquals = 88;
        TokenID._map[89] = "LessThanLessThan";
        TokenID.LessThanLessThan = 89;
        TokenID._map[90] = "GreaterThanGreaterThan";
        TokenID.GreaterThanGreaterThan = 90;
        TokenID._map[91] = "GreaterThanGreaterThanGreaterThan";
        TokenID.GreaterThanGreaterThanGreaterThan = 91;
        TokenID._map[92] = "Plus";
        TokenID.Plus = 92;
        TokenID._map[93] = "Minus";
        TokenID.Minus = 93;
        TokenID._map[94] = "Asterisk";
        TokenID.Asterisk = 94;
        TokenID._map[95] = "Slash";
        TokenID.Slash = 95;
        TokenID._map[96] = "Percent";
        TokenID.Percent = 96;
        TokenID._map[97] = "Tilde";
        TokenID.Tilde = 97;
        TokenID._map[98] = "Exclamation";
        TokenID.Exclamation = 98;
        TokenID._map[99] = "PlusPlus";
        TokenID.PlusPlus = 99;
        TokenID._map[100] = "MinusMinus";
        TokenID.MinusMinus = 100;
        TokenID._map[101] = "Dot";
        TokenID.Dot = 101;
        TokenID._map[102] = "DotDotDot";
        TokenID.DotDotDot = 102;
        TokenID._map[103] = "Error";
        TokenID.Error = 103;
        TokenID._map[104] = "EndOfFile";
        TokenID.EndOfFile = 104;
        TokenID._map[105] = "EqualsGreaterThan";
        TokenID.EqualsGreaterThan = 105;
        TokenID._map[106] = "Identifier";
        TokenID.Identifier = 106;
        TokenID._map[107] = "StringLiteral";
        TokenID.StringLiteral = 107;
        TokenID._map[108] = "RegularExpressionLiteral";
        TokenID.RegularExpressionLiteral = 108;
        TokenID._map[109] = "NumberLiteral";
        TokenID.NumberLiteral = 109;
        TokenID._map[110] = "Whitespace";
        TokenID.Whitespace = 110;
        TokenID._map[111] = "Comment";
        TokenID.Comment = 111;
        TokenID._map[112] = "Lim";
        TokenID.Lim = 112;
        TokenID.LimFixed = TokenID.EqualsGreaterThan;
        TokenID.LimKeyword = TokenID.Yield;
    })(TypeScript.TokenID || (TypeScript.TokenID = {}));
    var TokenID = TypeScript.TokenID;
    TypeScript.tokenTable = new Array();
    TypeScript.nodeTypeTable = new Array();
    TypeScript.nodeTypeToTokTable = new Array();
    TypeScript.noRegexTable = new Array();
    TypeScript.noRegexTable[TokenID.Identifier] = true;
    TypeScript.noRegexTable[TokenID.StringLiteral] = true;
    TypeScript.noRegexTable[TokenID.NumberLiteral] = true;
    TypeScript.noRegexTable[TokenID.RegularExpressionLiteral] = true;
    TypeScript.noRegexTable[TokenID.This] = true;
    TypeScript.noRegexTable[TokenID.PlusPlus] = true;
    TypeScript.noRegexTable[TokenID.MinusMinus] = true;
    TypeScript.noRegexTable[TokenID.CloseParen] = true;
    TypeScript.noRegexTable[TokenID.CloseBracket] = true;
    TypeScript.noRegexTable[TokenID.CloseBrace] = true;
    TypeScript.noRegexTable[TokenID.True] = true;
    TypeScript.noRegexTable[TokenID.False] = true;
    (function (OperatorPrecedence) {
        OperatorPrecedence._map = [];
        OperatorPrecedence._map[0] = "None";
        OperatorPrecedence.None = 0;
        OperatorPrecedence._map[1] = "Comma";
        OperatorPrecedence.Comma = 1;
        OperatorPrecedence._map[2] = "Assignment";
        OperatorPrecedence.Assignment = 2;
        OperatorPrecedence._map[3] = "Conditional";
        OperatorPrecedence.Conditional = 3;
        OperatorPrecedence._map[4] = "LogicalOr";
        OperatorPrecedence.LogicalOr = 4;
        OperatorPrecedence._map[5] = "LogicalAnd";
        OperatorPrecedence.LogicalAnd = 5;
        OperatorPrecedence._map[6] = "BitwiseOr";
        OperatorPrecedence.BitwiseOr = 6;
        OperatorPrecedence._map[7] = "BitwiseExclusiveOr";
        OperatorPrecedence.BitwiseExclusiveOr = 7;
        OperatorPrecedence._map[8] = "BitwiseAnd";
        OperatorPrecedence.BitwiseAnd = 8;
        OperatorPrecedence._map[9] = "Equality";
        OperatorPrecedence.Equality = 9;
        OperatorPrecedence._map[10] = "Relational";
        OperatorPrecedence.Relational = 10;
        OperatorPrecedence._map[11] = "Shift";
        OperatorPrecedence.Shift = 11;
        OperatorPrecedence._map[12] = "Additive";
        OperatorPrecedence.Additive = 12;
        OperatorPrecedence._map[13] = "Multiplicative";
        OperatorPrecedence.Multiplicative = 13;
        OperatorPrecedence._map[14] = "Unary";
        OperatorPrecedence.Unary = 14;
        OperatorPrecedence._map[15] = "Lim";
        OperatorPrecedence.Lim = 15;
    })(TypeScript.OperatorPrecedence || (TypeScript.OperatorPrecedence = {}));
    var OperatorPrecedence = TypeScript.OperatorPrecedence;
    (function (Reservation) {
        Reservation._map = [];
        Reservation.None = 0;
        Reservation.Javascript = 1;
        Reservation.JavascriptFuture = 2;
        Reservation.TypeScript = 4;
        Reservation.JavascriptFutureStrict = 8;
        Reservation.TypeScriptAndJS = Reservation.Javascript | Reservation.TypeScript;
        Reservation.TypeScriptAndJSFuture = Reservation.JavascriptFuture | Reservation.TypeScript;
        Reservation.TypeScriptAndJSFutureStrict = Reservation.JavascriptFutureStrict | Reservation.TypeScript;
    })(TypeScript.Reservation || (TypeScript.Reservation = {}));
    var Reservation = TypeScript.Reservation;
    var TokenInfo = (function () {
        function TokenInfo(tokenId, reservation, binopPrecedence, binopNodeType, unopPrecedence, unopNodeType, text, ers) {
            this.tokenId = tokenId;
            this.reservation = reservation;
            this.binopPrecedence = binopPrecedence;
            this.binopNodeType = binopNodeType;
            this.unopPrecedence = unopPrecedence;
            this.unopNodeType = unopNodeType;
            this.text = text;
            this.ers = ers;
        }
        return TokenInfo;
    })();
    TypeScript.TokenInfo = TokenInfo;    
    function setTokenInfo(tokenId, reservation, binopPrecedence, binopNodeType, unopPrecedence, unopNodeType, text, ers) {
        if(tokenId !== undefined) {
            TypeScript.tokenTable[tokenId] = new TokenInfo(tokenId, reservation, binopPrecedence, binopNodeType, unopPrecedence, unopNodeType, text, ers);
            if(binopNodeType != TypeScript.NodeType.None) {
                TypeScript.nodeTypeTable[binopNodeType] = text;
                TypeScript.nodeTypeToTokTable[binopNodeType] = tokenId;
            }
            if(unopNodeType != TypeScript.NodeType.None) {
                TypeScript.nodeTypeTable[unopNodeType] = text;
            }
        }
    }
    setTokenInfo(TokenID.Any, Reservation.TypeScript, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "any", TypeScript.ErrorRecoverySet.PrimType);
    setTokenInfo(TokenID.Bool, Reservation.TypeScript, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "bool", TypeScript.ErrorRecoverySet.PrimType);
    setTokenInfo(TokenID.Break, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "break", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.Case, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "case", TypeScript.ErrorRecoverySet.SCase);
    setTokenInfo(TokenID.Catch, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "catch", TypeScript.ErrorRecoverySet.Catch);
    setTokenInfo(TokenID.Class, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "class", TypeScript.ErrorRecoverySet.TypeScriptS);
    setTokenInfo(TokenID.Const, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "const", TypeScript.ErrorRecoverySet.Var);
    setTokenInfo(TokenID.Continue, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "continue", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.Debugger, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.Debugger, "debugger", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.Default, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "default", TypeScript.ErrorRecoverySet.SCase);
    setTokenInfo(TokenID.Delete, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.Unary, TypeScript.NodeType.Delete, "delete", TypeScript.ErrorRecoverySet.Prefix);
    setTokenInfo(TokenID.Do, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "do", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.Else, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "else", TypeScript.ErrorRecoverySet.Else);
    setTokenInfo(TokenID.Enum, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "enum", TypeScript.ErrorRecoverySet.TypeScriptS);
    setTokenInfo(TokenID.Export, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "export", TypeScript.ErrorRecoverySet.TypeScriptS);
    setTokenInfo(TokenID.Extends, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "extends", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.Declare, Reservation.TypeScript, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "declare", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.False, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "false", TypeScript.ErrorRecoverySet.RLit);
    setTokenInfo(TokenID.Finally, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "finally", TypeScript.ErrorRecoverySet.Catch);
    setTokenInfo(TokenID.For, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "for", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.Function, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "function", TypeScript.ErrorRecoverySet.Func);
    setTokenInfo(TokenID.Constructor, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "constructor", TypeScript.ErrorRecoverySet.Func);
    setTokenInfo(TokenID.Get, Reservation.TypeScript, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "get", TypeScript.ErrorRecoverySet.Func);
    setTokenInfo(TokenID.Set, Reservation.TypeScript, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "set", TypeScript.ErrorRecoverySet.Func);
    setTokenInfo(TokenID.If, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "if", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.Implements, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "implements", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.Import, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "import", TypeScript.ErrorRecoverySet.TypeScriptS);
    setTokenInfo(TokenID.In, Reservation.TypeScriptAndJS, OperatorPrecedence.Relational, TypeScript.NodeType.In, OperatorPrecedence.None, TypeScript.NodeType.None, "in", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.InstanceOf, Reservation.TypeScriptAndJS, OperatorPrecedence.Relational, TypeScript.NodeType.InstOf, OperatorPrecedence.None, TypeScript.NodeType.None, "instanceof", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Interface, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "interface", TypeScript.ErrorRecoverySet.TypeScriptS);
    setTokenInfo(TokenID.Let, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "let", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.Module, Reservation.TypeScript, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "module", TypeScript.ErrorRecoverySet.TypeScriptS);
    setTokenInfo(TokenID.New, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "new", TypeScript.ErrorRecoverySet.PreOp);
    setTokenInfo(TokenID.Number, Reservation.TypeScript, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "number", TypeScript.ErrorRecoverySet.PrimType);
    setTokenInfo(TokenID.Null, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "null", TypeScript.ErrorRecoverySet.RLit);
    setTokenInfo(TokenID.Package, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "package", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.Private, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "private", TypeScript.ErrorRecoverySet.TypeScriptS);
    setTokenInfo(TokenID.Protected, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "protected", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.Public, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "public", TypeScript.ErrorRecoverySet.TypeScriptS);
    setTokenInfo(TokenID.Return, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "return", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.Static, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "static", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.String, Reservation.TypeScript, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "string", TypeScript.ErrorRecoverySet.PrimType);
    setTokenInfo(TokenID.Super, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "super", TypeScript.ErrorRecoverySet.RLit);
    setTokenInfo(TokenID.Switch, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "switch", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.This, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "this", TypeScript.ErrorRecoverySet.RLit);
    setTokenInfo(TokenID.Throw, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "throw", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.True, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "true", TypeScript.ErrorRecoverySet.RLit);
    setTokenInfo(TokenID.Try, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "try", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.TypeOf, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.Unary, TypeScript.NodeType.Typeof, "typeof", TypeScript.ErrorRecoverySet.Prefix);
    setTokenInfo(TokenID.Var, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "var", TypeScript.ErrorRecoverySet.Var);
    setTokenInfo(TokenID.Void, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.Unary, TypeScript.NodeType.Void, "void", TypeScript.ErrorRecoverySet.Prefix);
    setTokenInfo(TokenID.With, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.With, "with", TypeScript.ErrorRecoverySet.Stmt);
    setTokenInfo(TokenID.While, Reservation.TypeScriptAndJS, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "while", TypeScript.ErrorRecoverySet.While);
    setTokenInfo(TokenID.Yield, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "yield", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.Identifier, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "identifier", TypeScript.ErrorRecoverySet.ID);
    setTokenInfo(TokenID.NumberLiteral, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "numberLiteral", TypeScript.ErrorRecoverySet.Literal);
    setTokenInfo(TokenID.RegularExpressionLiteral, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "regex", TypeScript.ErrorRecoverySet.RegExp);
    setTokenInfo(TokenID.StringLiteral, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "qstring", TypeScript.ErrorRecoverySet.Literal);
    setTokenInfo(TokenID.Semicolon, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, ";", TypeScript.ErrorRecoverySet.SColon);
    setTokenInfo(TokenID.CloseParen, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, ")", TypeScript.ErrorRecoverySet.RParen);
    setTokenInfo(TokenID.CloseBracket, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "]", TypeScript.ErrorRecoverySet.RBrack);
    setTokenInfo(TokenID.OpenBrace, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "{", TypeScript.ErrorRecoverySet.LCurly);
    setTokenInfo(TokenID.CloseBrace, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "}", TypeScript.ErrorRecoverySet.RCurly);
    setTokenInfo(TokenID.DotDotDot, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "...", TypeScript.ErrorRecoverySet.None);
    setTokenInfo(TokenID.Comma, Reservation.None, OperatorPrecedence.Comma, TypeScript.NodeType.Comma, OperatorPrecedence.None, TypeScript.NodeType.None, ",", TypeScript.ErrorRecoverySet.Comma);
    setTokenInfo(TokenID.Equals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.Asg, OperatorPrecedence.None, TypeScript.NodeType.None, "=", TypeScript.ErrorRecoverySet.Asg);
    setTokenInfo(TokenID.PlusEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgAdd, OperatorPrecedence.None, TypeScript.NodeType.None, "+=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.MinusEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgSub, OperatorPrecedence.None, TypeScript.NodeType.None, "-=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.AsteriskEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgMul, OperatorPrecedence.None, TypeScript.NodeType.None, "*=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.SlashEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgDiv, OperatorPrecedence.None, TypeScript.NodeType.None, "/=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.PercentEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgMod, OperatorPrecedence.None, TypeScript.NodeType.None, "%=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.AmpersandEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgAnd, OperatorPrecedence.None, TypeScript.NodeType.None, "&=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.CaretEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgXor, OperatorPrecedence.None, TypeScript.NodeType.None, "^=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.BarEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgOr, OperatorPrecedence.None, TypeScript.NodeType.None, "|=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.LessThanLessThanEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgLsh, OperatorPrecedence.None, TypeScript.NodeType.None, "<<=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.GreaterThanGreaterThanEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgRsh, OperatorPrecedence.None, TypeScript.NodeType.None, ">>=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.GreaterThanGreaterThanGreaterThanEquals, Reservation.None, OperatorPrecedence.Assignment, TypeScript.NodeType.AsgRs2, OperatorPrecedence.None, TypeScript.NodeType.None, ">>>=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Question, Reservation.None, OperatorPrecedence.Conditional, TypeScript.NodeType.ConditionalExpression, OperatorPrecedence.None, TypeScript.NodeType.None, "?", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Colon, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, ":", TypeScript.ErrorRecoverySet.Colon);
    setTokenInfo(TokenID.BarBar, Reservation.None, OperatorPrecedence.LogicalOr, TypeScript.NodeType.LogOr, OperatorPrecedence.None, TypeScript.NodeType.None, "||", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.AmpersandAmpersand, Reservation.None, OperatorPrecedence.LogicalAnd, TypeScript.NodeType.LogAnd, OperatorPrecedence.None, TypeScript.NodeType.None, "&&", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Bar, Reservation.None, OperatorPrecedence.BitwiseOr, TypeScript.NodeType.Or, OperatorPrecedence.None, TypeScript.NodeType.None, "|", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Caret, Reservation.None, OperatorPrecedence.BitwiseExclusiveOr, TypeScript.NodeType.Xor, OperatorPrecedence.None, TypeScript.NodeType.None, "^", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.And, Reservation.None, OperatorPrecedence.BitwiseAnd, TypeScript.NodeType.And, OperatorPrecedence.None, TypeScript.NodeType.None, "&", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.EqualsEquals, Reservation.None, OperatorPrecedence.Equality, TypeScript.NodeType.Eq, OperatorPrecedence.None, TypeScript.NodeType.None, "==", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.ExclamationEquals, Reservation.None, OperatorPrecedence.Equality, TypeScript.NodeType.Ne, OperatorPrecedence.None, TypeScript.NodeType.None, "!=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.EqualsEqualsEquals, Reservation.None, OperatorPrecedence.Equality, TypeScript.NodeType.Eqv, OperatorPrecedence.None, TypeScript.NodeType.None, "===", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.ExclamationEqualsEquals, Reservation.None, OperatorPrecedence.Equality, TypeScript.NodeType.NEqv, OperatorPrecedence.None, TypeScript.NodeType.None, "!==", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.LessThan, Reservation.None, OperatorPrecedence.Relational, TypeScript.NodeType.Lt, OperatorPrecedence.None, TypeScript.NodeType.None, "<", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.LessThanEquals, Reservation.None, OperatorPrecedence.Relational, TypeScript.NodeType.Le, OperatorPrecedence.None, TypeScript.NodeType.None, "<=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.GreaterThan, Reservation.None, OperatorPrecedence.Relational, TypeScript.NodeType.Gt, OperatorPrecedence.None, TypeScript.NodeType.None, ">", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.GreaterThanEquals, Reservation.None, OperatorPrecedence.Relational, TypeScript.NodeType.Ge, OperatorPrecedence.None, TypeScript.NodeType.None, ">=", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.LessThanLessThan, Reservation.None, OperatorPrecedence.Shift, TypeScript.NodeType.Lsh, OperatorPrecedence.None, TypeScript.NodeType.None, "<<", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.GreaterThanGreaterThan, Reservation.None, OperatorPrecedence.Shift, TypeScript.NodeType.Rsh, OperatorPrecedence.None, TypeScript.NodeType.None, ">>", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.GreaterThanGreaterThanGreaterThan, Reservation.None, OperatorPrecedence.Shift, TypeScript.NodeType.Rs2, OperatorPrecedence.None, TypeScript.NodeType.None, ">>>", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Plus, Reservation.None, OperatorPrecedence.Additive, TypeScript.NodeType.Add, OperatorPrecedence.Unary, TypeScript.NodeType.Pos, "+", TypeScript.ErrorRecoverySet.AddOp);
    setTokenInfo(TokenID.Minus, Reservation.None, OperatorPrecedence.Additive, TypeScript.NodeType.Sub, OperatorPrecedence.Unary, TypeScript.NodeType.Neg, "-", TypeScript.ErrorRecoverySet.AddOp);
    setTokenInfo(TokenID.Asterisk, Reservation.None, OperatorPrecedence.Multiplicative, TypeScript.NodeType.Mul, OperatorPrecedence.None, TypeScript.NodeType.None, "*", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Slash, Reservation.None, OperatorPrecedence.Multiplicative, TypeScript.NodeType.Div, OperatorPrecedence.None, TypeScript.NodeType.None, "/", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Percent, Reservation.None, OperatorPrecedence.Multiplicative, TypeScript.NodeType.Mod, OperatorPrecedence.None, TypeScript.NodeType.None, "%", TypeScript.ErrorRecoverySet.BinOp);
    setTokenInfo(TokenID.Tilde, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.Unary, TypeScript.NodeType.Not, "~", TypeScript.ErrorRecoverySet.PreOp);
    setTokenInfo(TokenID.Exclamation, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.Unary, TypeScript.NodeType.LogNot, "!", TypeScript.ErrorRecoverySet.PreOp);
    setTokenInfo(TokenID.PlusPlus, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.Unary, TypeScript.NodeType.IncPre, "++", TypeScript.ErrorRecoverySet.PreOp);
    setTokenInfo(TokenID.MinusMinus, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.Unary, TypeScript.NodeType.DecPre, "--", TypeScript.ErrorRecoverySet.PreOp);
    setTokenInfo(TokenID.OpenParen, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "(", TypeScript.ErrorRecoverySet.LParen);
    setTokenInfo(TokenID.OpenBracket, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "[", TypeScript.ErrorRecoverySet.LBrack);
    setTokenInfo(TokenID.Dot, Reservation.None, OperatorPrecedence.Unary, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, ".", TypeScript.ErrorRecoverySet.Dot);
    setTokenInfo(TokenID.EndOfFile, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "<EOF>", TypeScript.ErrorRecoverySet.EOF);
    setTokenInfo(TokenID.EqualsGreaterThan, Reservation.None, OperatorPrecedence.None, TypeScript.NodeType.None, OperatorPrecedence.None, TypeScript.NodeType.None, "=>", TypeScript.ErrorRecoverySet.None);
    function lookupToken(tokenId) {
        return TypeScript.tokenTable[tokenId];
    }
    TypeScript.lookupToken = lookupToken;
    (function (TokenClass) {
        TokenClass._map = [];
        TokenClass._map[0] = "Punctuation";
        TokenClass.Punctuation = 0;
        TokenClass._map[1] = "Keyword";
        TokenClass.Keyword = 1;
        TokenClass._map[2] = "Operator";
        TokenClass.Operator = 2;
        TokenClass._map[3] = "Comment";
        TokenClass.Comment = 3;
        TokenClass._map[4] = "Whitespace";
        TokenClass.Whitespace = 4;
        TokenClass._map[5] = "Identifier";
        TokenClass.Identifier = 5;
        TokenClass._map[6] = "NumberLiteral";
        TokenClass.NumberLiteral = 6;
        TokenClass._map[7] = "StringLiteral";
        TokenClass.StringLiteral = 7;
        TokenClass._map[8] = "RegExpLiteral";
        TokenClass.RegExpLiteral = 8;
    })(TypeScript.TokenClass || (TypeScript.TokenClass = {}));
    var TokenClass = TypeScript.TokenClass;
    var SavedToken = (function () {
        function SavedToken(tok, minChar, limChar) {
            this.tok = tok;
            this.minChar = minChar;
            this.limChar = limChar;
        }
        return SavedToken;
    })();
    TypeScript.SavedToken = SavedToken;    
    var Token = (function () {
        function Token(tokenId) {
            this.tokenId = tokenId;
        }
        Token.prototype.toString = function () {
            return "token: " + this.tokenId + " " + this.getText() + " (" + (TokenID)._map[this.tokenId] + ")";
        };
        Token.prototype.print = function (line, outfile) {
            outfile.WriteLine(this.toString() + ",on line" + line);
        };
        Token.prototype.getText = function () {
            return TypeScript.tokenTable[this.tokenId].text;
        };
        Token.prototype.classification = function () {
            if(this.tokenId <= TokenID.LimKeyword) {
                return TokenClass.Keyword;
            } else {
                var tokenInfo = lookupToken(this.tokenId);
                if(tokenInfo != undefined) {
                    if((tokenInfo.unopNodeType != TypeScript.NodeType.None) || (tokenInfo.binopNodeType != TypeScript.NodeType.None)) {
                        return TokenClass.Operator;
                    }
                }
            }
            return TokenClass.Punctuation;
        };
        return Token;
    })();
    TypeScript.Token = Token;    
    var NumberLiteralToken = (function (_super) {
        __extends(NumberLiteralToken, _super);
        function NumberLiteralToken(value, hasEmptyFraction) {
                _super.call(this, TokenID.NumberLiteral);
            this.value = value;
            this.hasEmptyFraction = hasEmptyFraction;
        }
        NumberLiteralToken.prototype.getText = function () {
            return this.hasEmptyFraction ? this.value.toString() + ".0" : this.value.toString();
        };
        NumberLiteralToken.prototype.classification = function () {
            return TokenClass.NumberLiteral;
        };
        return NumberLiteralToken;
    })(Token);
    TypeScript.NumberLiteralToken = NumberLiteralToken;    
    var StringLiteralToken = (function (_super) {
        __extends(StringLiteralToken, _super);
        function StringLiteralToken(value) {
                _super.call(this, TokenID.StringLiteral);
            this.value = value;
        }
        StringLiteralToken.prototype.getText = function () {
            return this.value;
        };
        StringLiteralToken.prototype.classification = function () {
            return TokenClass.StringLiteral;
        };
        return StringLiteralToken;
    })(Token);
    TypeScript.StringLiteralToken = StringLiteralToken;    
    var IdentifierToken = (function (_super) {
        __extends(IdentifierToken, _super);
        function IdentifierToken(value, hasEscapeSequence) {
                _super.call(this, TokenID.Identifier);
            this.value = value;
            this.hasEscapeSequence = hasEscapeSequence;
        }
        IdentifierToken.prototype.getText = function () {
            return this.value;
        };
        IdentifierToken.prototype.classification = function () {
            return TokenClass.Identifier;
        };
        return IdentifierToken;
    })(Token);
    TypeScript.IdentifierToken = IdentifierToken;    
    var WhitespaceToken = (function (_super) {
        __extends(WhitespaceToken, _super);
        function WhitespaceToken(tokenId, value) {
                _super.call(this, tokenId);
            this.value = value;
        }
        WhitespaceToken.prototype.getText = function () {
            return this.value;
        };
        WhitespaceToken.prototype.classification = function () {
            return TokenClass.Whitespace;
        };
        return WhitespaceToken;
    })(Token);
    TypeScript.WhitespaceToken = WhitespaceToken;    
    var CommentToken = (function (_super) {
        __extends(CommentToken, _super);
        function CommentToken(tokenID, value, isBlock, startPos, line, endsLine) {
                _super.call(this, tokenID);
            this.value = value;
            this.isBlock = isBlock;
            this.startPos = startPos;
            this.line = line;
            this.endsLine = endsLine;
        }
        CommentToken.prototype.getText = function () {
            return this.value;
        };
        CommentToken.prototype.classification = function () {
            return TokenClass.Comment;
        };
        return CommentToken;
    })(Token);
    TypeScript.CommentToken = CommentToken;    
    var RegularExpressionLiteralToken = (function (_super) {
        __extends(RegularExpressionLiteralToken, _super);
        function RegularExpressionLiteralToken(regex) {
                _super.call(this, TokenID.RegularExpressionLiteral);
            this.regex = regex;
        }
        RegularExpressionLiteralToken.prototype.getText = function () {
            return this.regex.toString();
        };
        RegularExpressionLiteralToken.prototype.classification = function () {
            return TokenClass.RegExpLiteral;
        };
        return RegularExpressionLiteralToken;
    })(Token);
    TypeScript.RegularExpressionLiteralToken = RegularExpressionLiteralToken;    
    TypeScript.staticTokens = new Array();
    function initializeStaticTokens() {
        for(var i = 0; i <= TokenID.LimFixed; i++) {
            TypeScript.staticTokens[i] = new Token(i);
        }
    }
    TypeScript.initializeStaticTokens = initializeStaticTokens;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var ArrayCache = (function () {
        function ArrayCache() {
            this.arrayBase = null;
        }
        ArrayCache.prototype.specialize = function (arrInstType, checker) {
            if(this.arrayBase == null) {
                this.arrayBase = arrInstType.specializeType(checker.wildElm.type, this.arrayType.elementType, checker, true);
            }
            return this.arrayBase;
        };
        return ArrayCache;
    })();
    TypeScript.ArrayCache = ArrayCache;    
    var TypeComparisonInfo = (function () {
        function TypeComparisonInfo() {
            this.onlyCaptureFirstError = false;
            this.flags = TypeScript.TypeRelationshipFlags.SuccessfulComparison;
            this.message = "";
        }
        TypeComparisonInfo.prototype.addMessageToFront = function (message) {
            if(!this.onlyCaptureFirstError) {
                this.message = this.message ? message + ":\n\t" + this.message : message;
            } else {
                this.setMessage(message);
            }
        };
        TypeComparisonInfo.prototype.setMessage = function (message) {
            this.message = message;
        };
        return TypeComparisonInfo;
    })();
    TypeScript.TypeComparisonInfo = TypeComparisonInfo;    
    (function (TypeCheckCollectionMode) {
        TypeCheckCollectionMode._map = [];
        TypeCheckCollectionMode._map[0] = "Resident";
        TypeCheckCollectionMode.Resident = 0;
        TypeCheckCollectionMode._map[1] = "Transient";
        TypeCheckCollectionMode.Transient = 1;
    })(TypeScript.TypeCheckCollectionMode || (TypeScript.TypeCheckCollectionMode = {}));
    var TypeCheckCollectionMode = TypeScript.TypeCheckCollectionMode;
    var PersistentGlobalTypeState = (function () {
        function PersistentGlobalTypeState(errorReporter) {
            this.errorReporter = errorReporter;
            this.importedGlobalsTable = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            this.importedGlobalsTypeTable = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            this.globals = null;
            this.globalTypes = null;
            this.ambientGlobals = null;
            this.ambientGlobalTypes = null;
            this.residentGlobalValues = new TypeScript.StringHashTable();
            this.residentGlobalTypes = new TypeScript.StringHashTable();
            this.residentGlobalAmbientValues = new TypeScript.StringHashTable();
            this.residentGlobalAmbientTypes = new TypeScript.StringHashTable();
            this.residentTypeCheck = true;
            this.mod = null;
            this.gloMod = null;
            this.wildElm = null;
            this.importedGlobals = new TypeScript.SymbolScopeBuilder(null, this.importedGlobalsTable, null, this.importedGlobalsTypeTable, null, null);
            this.dualGlobalValues = new TypeScript.DualStringHashTable(this.residentGlobalValues, new TypeScript.StringHashTable());
            this.dualGlobalTypes = new TypeScript.DualStringHashTable(this.residentGlobalTypes, new TypeScript.StringHashTable());
            this.dualAmbientGlobalValues = new TypeScript.DualStringHashTable(this.residentGlobalAmbientValues, new TypeScript.StringHashTable());
            this.dualAmbientGlobalTypes = new TypeScript.DualStringHashTable(this.residentGlobalAmbientTypes, new TypeScript.StringHashTable());
            var dualGlobalScopedMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(this.dualGlobalValues, new TypeScript.StringHashTable()));
            var dualGlobalScopedAmbientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(this.dualAmbientGlobalValues, new TypeScript.StringHashTable()));
            var dualGlobalScopedEnclosedTypes = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(this.dualGlobalTypes, new TypeScript.StringHashTable()));
            var dualGlobalScopedAmbientEnclosedTypes = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(this.dualAmbientGlobalTypes, new TypeScript.StringHashTable()));
            this.globalScope = new TypeScript.SymbolScopeBuilder(dualGlobalScopedMembers, dualGlobalScopedAmbientMembers, dualGlobalScopedEnclosedTypes, dualGlobalScopedAmbientEnclosedTypes, this.importedGlobals, null);
            this.voidType = this.enterPrimitive(TypeScript.Primitive.Void, "void");
            this.booleanType = this.enterPrimitive(TypeScript.Primitive.Boolean, "bool");
            this.doubleType = this.enterPrimitive(TypeScript.Primitive.Double, "number");
            this.importedGlobals.ambientEnclosedTypes.addPublicMember("number", this.doubleType.symbol);
            this.stringType = this.enterPrimitive(TypeScript.Primitive.String, "string");
            this.anyType = this.enterPrimitive(TypeScript.Primitive.Any, "any");
            this.nullType = this.enterPrimitive(TypeScript.Primitive.Null, "null");
            this.undefinedType = this.enterPrimitive(TypeScript.Primitive.Undefined, "undefined");
            this.setCollectionMode(TypeCheckCollectionMode.Resident);
            this.wildElm = new TypeScript.TypeSymbol("_element", -1, 0, -1, new TypeScript.Type());
            this.importedGlobalsTypeTable.addPublicMember(this.wildElm.name, this.wildElm);
            this.mod = new TypeScript.ModuleType(dualGlobalScopedEnclosedTypes, dualGlobalScopedAmbientEnclosedTypes);
            this.mod.members = dualGlobalScopedMembers;
            this.mod.ambientMembers = dualGlobalScopedAmbientMembers;
            this.mod.containedScope = this.globalScope;
            this.gloMod = new TypeScript.TypeSymbol(TypeScript.globalId, -1, 0, -1, this.mod);
            this.mod.members.addPublicMember(this.gloMod.name, this.gloMod);
            this.defineGlobalValue("undefined", this.undefinedType);
        }
        PersistentGlobalTypeState.prototype.enterPrimitive = function (flags, name) {
            var primitive = new TypeScript.Type();
            primitive.primitiveTypeClass = flags;
            var symbol = new TypeScript.TypeSymbol(name, -1, name.length, -1, primitive);
            symbol.typeCheckStatus = TypeScript.TypeCheckStatus.Finished;
            primitive.symbol = symbol;
            this.importedGlobals.enter(null, null, symbol, this.errorReporter, true, true, true);
            return primitive;
        };
        PersistentGlobalTypeState.prototype.setCollectionMode = function (mode) {
            this.residentTypeCheck = this.dualGlobalValues.insertPrimary = this.dualGlobalTypes.insertPrimary = this.dualAmbientGlobalValues.insertPrimary = this.dualAmbientGlobalTypes.insertPrimary = mode == TypeCheckCollectionMode.Resident;
        };
        PersistentGlobalTypeState.prototype.refreshPersistentState = function () {
            this.globals = new TypeScript.StringHashTable();
            this.globalTypes = new TypeScript.StringHashTable();
            this.ambientGlobals = new TypeScript.StringHashTable();
            this.ambientGlobalTypes = new TypeScript.StringHashTable();
            this.globalTypes.add(this.voidType.symbol.name, this.voidType.symbol);
            this.globalTypes.add(this.booleanType.symbol.name, this.booleanType.symbol);
            this.globalTypes.add(this.doubleType.symbol.name, this.doubleType.symbol);
            this.globalTypes.add("number", this.doubleType.symbol);
            this.globalTypes.add(this.stringType.symbol.name, this.stringType.symbol);
            this.globalTypes.add(this.anyType.symbol.name, this.anyType.symbol);
            this.globalTypes.add(this.nullType.symbol.name, this.nullType.symbol);
            this.globalTypes.add(this.undefinedType.symbol.name, this.undefinedType.symbol);
            this.dualGlobalValues.secondaryTable = this.globals;
            this.dualGlobalTypes.secondaryTable = this.globalTypes;
            this.dualAmbientGlobalValues.secondaryTable = this.ambientGlobals;
            this.dualAmbientGlobalTypes.secondaryTable = this.ambientGlobalTypes;
        };
        PersistentGlobalTypeState.prototype.defineGlobalValue = function (name, type) {
            var valueLocation = new TypeScript.ValueLocation();
            valueLocation.typeLink = new TypeScript.TypeLink();
            var sym = new TypeScript.VariableSymbol(name, 0, -1, valueLocation);
            sym.setType(type);
            sym.typeCheckStatus = TypeScript.TypeCheckStatus.Finished;
            sym.container = this.gloMod;
            this.importedGlobalsTable.addPublicMember(name, sym);
        };
        return PersistentGlobalTypeState;
    })();
    TypeScript.PersistentGlobalTypeState = PersistentGlobalTypeState;    
    var ContextualTypeContext = (function () {
        function ContextualTypeContext(contextualType, provisional, contextID) {
            this.contextualType = contextualType;
            this.provisional = provisional;
            this.contextID = contextID;
            this.targetSig = null;
            this.targetThis = null;
            this.targetAccessorType = null;
        }
        return ContextualTypeContext;
    })();
    TypeScript.ContextualTypeContext = ContextualTypeContext;    
    var ContextualTypingContextStack = (function () {
        function ContextualTypingContextStack(checker) {
            this.checker = checker;
            this.contextStack = [];
            this.hadProvisionalErrors = false;
        }
        ContextualTypingContextStack.contextID = TypeScript.TypeCheckStatus.Finished + 1;
        ContextualTypingContextStack.prototype.pushContextualType = function (type, provisional) {
            this.contextStack.push(new ContextualTypeContext(type, provisional, ContextualTypingContextStack.contextID++));
            this.checker.errorReporter.pushToErrorSink = provisional;
        };
        ContextualTypingContextStack.prototype.popContextualType = function () {
            var tc = this.contextStack.pop();
            this.checker.errorReporter.pushToErrorSink = this.isProvisional();
            this.hadProvisionalErrors = this.hadProvisionalErrors || (tc.provisional && (this.checker.errorReporter.getCapturedErrors().length));
            this.checker.errorReporter.freeCapturedErrors();
            return tc;
        };
        ContextualTypingContextStack.prototype.getContextualType = function () {
            return (!this.contextStack.length ? null : this.contextStack[this.contextStack.length - 1]);
        };
        ContextualTypingContextStack.prototype.getContextID = function () {
            return (!this.contextStack.length ? TypeScript.TypeCheckStatus.Finished : this.contextStack[this.contextStack.length - 1].contextID);
        };
        ContextualTypingContextStack.prototype.isProvisional = function () {
            return (!this.contextStack.length ? false : this.contextStack[this.contextStack.length - 1].provisional);
        };
        return ContextualTypingContextStack;
    })();
    TypeScript.ContextualTypingContextStack = ContextualTypingContextStack;    
    var TypeChecker = (function () {
        function TypeChecker(persistentState) {
            this.persistentState = persistentState;
            this.errorReporter = null;
            this.checkControlFlow = false;
            this.printControlFlowGraph = false;
            this.checkControlFlowUseDef = false;
            this.styleSettings = null;
            this.units = null;
            this.anon = "_anonymous";
            this.locationInfo = null;
            this.typeFlow = null;
            this.currentCompareA = null;
            this.currentCompareB = null;
            this.currentModDecl = null;
            this.inBind = false;
            this.inWith = false;
            this.errorsOnWith = true;
            this.currentContextualTypeContext = null;
            this.resolvingBases = false;
            this.canCallDefinitionSignature = false;
            this.assignableCache = {
            };
            this.subtypeCache = {
            };
            this.identicalCache = {
            };
            this.provisionalStartedTypecheckObjects = [];
            this.mustCaptureGlobalThis = false;
            this.voidType = this.persistentState.voidType;
            this.booleanType = this.persistentState.booleanType;
            this.numberType = this.persistentState.doubleType;
            this.stringType = this.persistentState.stringType;
            this.anyType = this.persistentState.anyType;
            this.nullType = this.persistentState.nullType;
            this.undefinedType = this.persistentState.undefinedType;
            this.globals = this.persistentState.dualGlobalValues;
            this.globalTypes = this.persistentState.dualGlobalTypes;
            this.ambientGlobals = this.persistentState.dualAmbientGlobalValues;
            this.ambientGlobalTypes = this.persistentState.dualAmbientGlobalTypes;
            this.gloModType = this.persistentState.mod;
            this.gloMod = this.persistentState.gloMod;
            this.wildElm = this.persistentState.wildElm;
            this.globalScope = this.persistentState.globalScope;
            this.typingContextStack = new ContextualTypingContextStack(this);
        }
        TypeChecker.prototype.setStyleOptions = function (style) {
            this.styleSettings = style;
        };
        TypeChecker.prototype.setContextualType = function (type, provisional) {
            this.typingContextStack.pushContextualType(type, provisional);
            this.currentContextualTypeContext = this.typingContextStack.getContextualType();
        };
        TypeChecker.prototype.unsetContextualType = function () {
            var lastTC = this.typingContextStack.popContextualType();
            this.currentContextualTypeContext = this.typingContextStack.getContextualType();
            return lastTC;
        };
        TypeChecker.prototype.hadProvisionalErrors = function () {
            return this.typingContextStack.hadProvisionalErrors;
        };
        TypeChecker.prototype.resetProvisionalErrors = function () {
            if(!this.typingContextStack.getContextualType()) {
                this.typingContextStack.hadProvisionalErrors = false;
            }
        };
        TypeChecker.prototype.typeCheckWithContextualType = function (contextType, provisional, condition, ast) {
            if(condition) {
                this.setContextualType(contextType, this.typingContextStack.isProvisional() || provisional);
            }
            this.typeFlow.typeCheck(ast);
            if(condition) {
                this.unsetContextualType();
            }
        };
        TypeChecker.prototype.resetTargetType = function () {
            this.currentContextualTypeContext = this.typingContextStack.getContextualType();
        };
        TypeChecker.prototype.killCurrentContextualType = function () {
            this.currentContextualTypeContext = null;
            this.errorReporter.pushToErrorSink = false;
        };
        TypeChecker.prototype.hasTargetType = function () {
            return this.currentContextualTypeContext && this.currentContextualTypeContext.contextualType;
        };
        TypeChecker.prototype.getTargetTypeContext = function () {
            return this.currentContextualTypeContext;
        };
        TypeChecker.prototype.inProvisionalTypecheckMode = function () {
            return this.typingContextStack.isProvisional();
        };
        TypeChecker.prototype.getTypeCheckFinishedStatus = function () {
            if(this.inProvisionalTypecheckMode()) {
                return this.typingContextStack.getContextID();
            }
            return TypeScript.TypeCheckStatus.Finished;
        };
        TypeChecker.prototype.typeStatusIsFinished = function (status) {
            return status == TypeScript.TypeCheckStatus.Finished || (this.inProvisionalTypecheckMode() && status == this.typingContextStack.getContextID());
        };
        TypeChecker.prototype.addStartedPTO = function (pto) {
            if(this.inProvisionalTypecheckMode()) {
                this.provisionalStartedTypecheckObjects[this.provisionalStartedTypecheckObjects.length] = pto;
            }
        };
        TypeChecker.prototype.cleanStartedPTO = function () {
            for(var i = 0; i < this.provisionalStartedTypecheckObjects.length; i++) {
                if(this.provisionalStartedTypecheckObjects[i].typeCheckStatus >= this.typingContextStack.getContextID()) {
                    this.provisionalStartedTypecheckObjects[i].typeCheckStatus = TypeScript.TypeCheckStatus.NotStarted;
                }
            }
            this.provisionalStartedTypecheckObjects = [];
        };
        TypeChecker.prototype.collectTypes = function (ast) {
            if(ast.nodeType == TypeScript.NodeType.Script) {
                var script = ast;
                this.locationInfo = script.locationInfo;
            }
            var globalChain = new TypeScript.ScopeChain(this.gloMod, null, this.globalScope);
            var context = new TypeScript.TypeCollectionContext(globalChain, this);
            TypeScript.getAstWalkerFactory().walk(ast, TypeScript.preCollectTypes, TypeScript.postCollectTypes, null, context);
        };
        TypeChecker.prototype.makeArrayType = function (type) {
            if(type.arrayCache == null) {
                type.arrayCache = new ArrayCache();
                type.arrayCache.arrayType = new TypeScript.Type();
                type.arrayCache.arrayType.elementType = type;
                type.arrayCache.arrayType.symbol = type.symbol;
            }
            return type.arrayCache.arrayType;
        };
        TypeChecker.prototype.getParameterList = function (funcDecl, container) {
            var args = funcDecl.arguments;
            var parameterTable = null;
            var parameterBuilder = null;
            var len = args.members.length;
            var nonOptionalParams = 0;
            var result = [];
            if(len > 0) {
                parameterTable = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                parameterBuilder = new TypeScript.SymbolScopeBuilder(parameterTable, null, null, null, null, container);
                for(var i = 0; i < len; i++) {
                    var parameter = args.members[i];
                    var paramDef = new TypeScript.ValueLocation();
                    var parameterSymbol = new TypeScript.ParameterSymbol(parameter.id.text, parameter.minChar, this.locationInfo.unitIndex, paramDef);
                    parameterSymbol.declAST = parameter;
                    parameterSymbol.funcDecl = funcDecl;
                    parameter.id.sym = parameterSymbol;
                    parameter.sym = parameterSymbol;
                    paramDef.symbol = parameterSymbol;
                    paramDef.typeLink = TypeScript.getTypeLink(parameter.typeExpr, this, false);
                    parameterBuilder.enter(null, parameter, parameterSymbol, this.errorReporter, true, false, false);
                    result[result.length] = parameterSymbol;
                    if(!parameter.isOptionalArg()) {
                        nonOptionalParams++;
                    }
                }
            }
            return {
                parameters: result,
                nonOptionalParameterCount: nonOptionalParams
            };
        };
        TypeChecker.prototype.createFunctionSignature = function (funcDecl, container, scope, overloadGroupSym, addToScope) {
            var isExported = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Exported | TypeScript.FncFlags.ClassPropertyMethodExported) || container == this.gloMod;
            var isStatic = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Static);
            var isPrivate = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Private);
            var isDefinition = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Definition);
            var isAmbient = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Ambient);
            var isConstructor = funcDecl.isConstructMember() || funcDecl.isConstructor;
            var isGlobal = container == this.gloMod;
            var signature = new TypeScript.Signature();
            var isLambda = funcDecl.fncFlags & TypeScript.FncFlags.IsFunctionExpression;
            if(funcDecl.returnTypeAnnotation || isDefinition) {
                signature.returnType = TypeScript.getTypeLink(funcDecl.returnTypeAnnotation, this, false);
            } else {
                signature.returnType = new TypeScript.TypeLink();
                signature.returnType.type = this.anyType;
            }
            signature.hasVariableArgList = funcDecl.variableArgList;
            var sigData = this.getParameterList(funcDecl, container);
            signature.parameters = sigData.parameters;
            signature.nonOptionalParameterCount = sigData.nonOptionalParameterCount;
            funcDecl.signature = signature;
            signature.declAST = funcDecl;
            var useOverloadGroupSym = overloadGroupSym && overloadGroupSym.getType() && !overloadGroupSym.isAccessor() && (funcDecl.isSignature() || (isAmbient == TypeScript.hasFlag(overloadGroupSym.flags, TypeScript.SymbolFlags.Ambient)));
            if(useOverloadGroupSym && isPrivate != TypeScript.hasFlag(overloadGroupSym.flags, TypeScript.SymbolFlags.Private)) {
                this.errorReporter.simpleError(funcDecl, "Public/Private visibility of overloads does not agree");
            }
            var groupType = useOverloadGroupSym ? overloadGroupSym.getType() : new TypeScript.Type();
            if(isConstructor) {
                if(groupType.construct == null) {
                    groupType.construct = new TypeScript.SignatureGroup();
                }
                groupType.construct.addSignature(signature);
                groupType.construct.hasImplementation = !(funcDecl.isSignature());
                if(groupType.construct.hasImplementation) {
                    groupType.setHasImplementation();
                }
            } else {
                if(funcDecl.isIndexerMember()) {
                    if(groupType.index == null) {
                        groupType.index = new TypeScript.SignatureGroup();
                        groupType.index.flags |= TypeScript.SignatureFlags.IsIndexer;
                    }
                    groupType.index.addSignature(signature);
                    groupType.index.hasImplementation = !(funcDecl.isSignature());
                    if(groupType.index.hasImplementation) {
                        groupType.setHasImplementation();
                    }
                } else {
                    if(groupType.call == null) {
                        groupType.call = new TypeScript.SignatureGroup();
                    }
                    groupType.call.addSignature(signature);
                    groupType.call.hasImplementation = !(funcDecl.isSignature());
                    if(groupType.call.hasImplementation) {
                        groupType.setHasImplementation();
                    }
                }
            }
            var instanceType = groupType.instanceType;
            var funcName = null;
            var usedHint = false;
            if(funcDecl.name && !funcDecl.name.isMissing()) {
                funcName = funcDecl.name.text;
            } else {
                if(funcDecl.hint) {
                    funcName = funcDecl.hint;
                    usedHint = true;
                }
            }
            if(groupType.symbol == null) {
                groupType.symbol = new TypeScript.TypeSymbol(funcName ? funcName : this.anon, funcDecl.minChar, funcDecl.limChar - funcDecl.minChar, this.locationInfo.unitIndex, groupType);
                if(!useOverloadGroupSym) {
                    groupType.symbol.declAST = funcDecl;
                }
            }
            if(isStatic) {
                groupType.symbol.flags |= TypeScript.SymbolFlags.Static;
            }
            if(isAmbient) {
                groupType.symbol.flags |= TypeScript.SymbolFlags.Ambient;
            }
            if(isPrivate) {
                groupType.symbol.flags |= TypeScript.SymbolFlags.Private;
            }
            groupType.symbol.isMethod = funcDecl.isMethod();
            if(groupType.symbol.isMethod) {
                groupType.symbol.flags |= TypeScript.SymbolFlags.Property;
            }
            funcDecl.type = groupType;
            if(!isConstructor) {
                if(funcName && !isLambda && !funcDecl.isAccessor() && !usedHint) {
                    if(addToScope) {
                        if(funcDecl.isMethod() && isStatic) {
                            if(!(container).type.members.publicMembers.add(funcName, groupType.symbol)) {
                                this.errorReporter.duplicateIdentifier(funcDecl, funcName);
                            }
                            groupType.symbol.container = container;
                        } else {
                            if(overloadGroupSym == null || (overloadGroupSym.declAST && !(overloadGroupSym.declAST).isOverload && (container.isType()))) {
                                scope.enter(container, funcDecl, groupType.symbol, this.errorReporter, !isPrivate && (isExported || isStatic || isGlobal), false, isAmbient);
                            }
                        }
                    } else {
                        if(!funcDecl.isSpecialFn()) {
                            groupType.symbol.container = container;
                        }
                    }
                } else {
                    if(!funcDecl.isSpecialFn()) {
                        groupType.symbol.container = container;
                    }
                }
            }
            if(useOverloadGroupSym) {
                var overloadGroupType = overloadGroupSym ? overloadGroupSym.getType() : null;
                var classType = groupType;
                if(classType != overloadGroupType) {
                    if(classType.construct == null) {
                        if(overloadGroupType && overloadGroupType.construct) {
                            classType.construct = overloadGroupType.construct;
                        } else {
                            classType.construct = new TypeScript.SignatureGroup();
                        }
                    } else {
                        if(overloadGroupType) {
                            if(overloadGroupType.construct) {
                                classType.construct.signatures.concat(overloadGroupType.construct.signatures);
                            }
                        }
                    }
                    if(overloadGroupType) {
                        if(classType.call == null) {
                            classType.call = overloadGroupType.call;
                        } else {
                            if(overloadGroupType.call) {
                                classType.call.signatures.concat(overloadGroupType.call.signatures);
                            }
                        }
                        if(!isStatic) {
                            if(classType.instanceType == null) {
                                classType.instanceType = overloadGroupType.instanceType;
                            }
                            var instanceType = classType.instanceType;
                            if(instanceType) {
                                if(instanceType.call == null) {
                                    instanceType.call = overloadGroupType.call;
                                } else {
                                    if(overloadGroupType.call) {
                                        instanceType.call.signatures.concat(overloadGroupType.call.signatures);
                                    }
                                }
                            }
                        }
                        if(classType.index == null) {
                            classType.index = overloadGroupType.index;
                        } else {
                            if(overloadGroupType.index) {
                                classType.index.signatures.concat(overloadGroupType.index.signatures);
                            }
                        }
                    }
                }
            }
            return signature;
        };
        TypeChecker.prototype.createAccessorSymbol = function (funcDecl, fgSym, enclosingClass, addToMembers, isClassProperty, scope, container) {
            var accessorSym = null;
            var sig = funcDecl.signature;
            var nameText = funcDecl.name.text;
            var isStatic = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Static);
            var isPrivate = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Private);
            if(fgSym == null) {
                var field = new TypeScript.ValueLocation();
                accessorSym = new TypeScript.FieldSymbol(nameText, funcDecl.minChar, this.locationInfo.unitIndex, false, field);
                field.symbol = accessorSym;
                accessorSym.declAST = funcDecl;
                if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor)) {
                    if(accessorSym.getter) {
                        this.errorReporter.simpleError(funcDecl, "Redeclaration of property getter");
                    }
                    accessorSym.getter = sig.declAST.type.symbol;
                } else {
                    if(accessorSym.setter) {
                        this.errorReporter.simpleError(funcDecl, "Redeclaration of property setter");
                    }
                    accessorSym.setter = sig.declAST.type.symbol;
                }
                field.typeLink = TypeScript.getTypeLink(null, this, false);
                if(addToMembers) {
                    if(enclosingClass) {
                        if(!enclosingClass.members.publicMembers.add(nameText, accessorSym)) {
                            this.errorReporter.duplicateIdentifier(funcDecl, accessorSym.name);
                        }
                        accessorSym.container = enclosingClass.symbol;
                    } else {
                        this.errorReporter.simpleError(funcDecl, "Accessor property may not be added in this context");
                    }
                } else {
                    scope.enter(container, funcDecl, accessorSym, this.errorReporter, !isPrivate || isStatic, false, false);
                }
                if(isClassProperty) {
                    accessorSym.flags |= TypeScript.SymbolFlags.Property;
                }
                if(isStatic) {
                    accessorSym.flags |= TypeScript.SymbolFlags.Static;
                }
                if(isPrivate) {
                    accessorSym.flags |= TypeScript.SymbolFlags.Private;
                } else {
                    accessorSym.flags |= TypeScript.SymbolFlags.Public;
                }
            } else {
                accessorSym = (fgSym);
                if(isPrivate != TypeScript.hasFlag(accessorSym.flags, TypeScript.SymbolFlags.Private)) {
                    this.errorReporter.simpleError(funcDecl, "Getter and setter accessors do not agree in visibility");
                }
                if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor)) {
                    if(accessorSym.getter) {
                        this.errorReporter.simpleError(funcDecl, "Redeclaration of property getter");
                    }
                    accessorSym.getter = funcDecl.type.symbol;
                } else {
                    if(accessorSym.setter) {
                        this.errorReporter.simpleError(funcDecl, "Redeclaration of property setter");
                    }
                    accessorSym.setter = funcDecl.type.symbol;
                }
            }
            return accessorSym;
        };
        TypeChecker.prototype.addBases = function (resultScope, type, baseContext) {
            resultScope.addParentScope(new TypeScript.SymbolTableScope(type.members, type.ambientMembers, type.getAllEnclosedTypes(), type.getAllAmbientEnclosedTypes(), type.symbol));
            var i = 0;
            var parent;
            if(type.extendsList) {
                for(var len = type.extendsList.length; i < len; i++) {
                    parent = type.extendsList[i];
                    if(baseContext.baseId == parent.typeID) {
                        this.errorReporter.reportErrorFromSym(parent.symbol, "Type '" + baseContext.base + "' is recursively referenced as a base class of itself");
                        parent.symbol.flags |= TypeScript.SymbolFlags.RecursivelyReferenced;
                        break;
                    }
                    this.addBases(resultScope, parent, baseContext);
                }
            }
        };
        TypeChecker.prototype.scopeOf = function (type) {
            var resultScope = new TypeScript.SymbolAggregateScope(type.symbol);
            var baseContext = {
                base: type.symbol && type.symbol.name ? type.symbol.name : "{}",
                baseId: type.typeID
            };
            this.addBases(resultScope, type, baseContext);
            return resultScope;
        };
        TypeChecker.prototype.lookupMemberTypeSymbol = function (containingType, name) {
            var symbol = null;
            if(containingType.containedScope) {
                symbol = containingType.containedScope.find(name, false, true);
            } else {
                if(containingType.members) {
                    symbol = containingType.members.allMembers.lookup(name);
                    if(symbol == null && containingType.ambientMembers) {
                        symbol = containingType.ambientMembers.allMembers.lookup(name);
                    }
                }
            }
            if(symbol == null) {
                var typeMembers = containingType.getAllEnclosedTypes();
                var ambientTypeMembers = containingType.getAllAmbientEnclosedTypes();
                if(typeMembers) {
                    symbol = typeMembers.allMembers.lookup(name);
                    if(symbol == null && ambientTypeMembers) {
                        symbol = ambientTypeMembers.allMembers.lookup(name);
                    }
                }
            }
            if(symbol && symbol.isType()) {
                return symbol;
            } else {
                return null;
            }
        };
        TypeChecker.prototype.findSymbolForDynamicModule = function (idText, currentFileName, search) {
            var originalIdText = idText;
            var symbol = search(idText);
            if(symbol == null) {
                if(!symbol) {
                    idText = TypeScript.swapQuotes(originalIdText);
                    symbol = search(idText);
                }
                if(!symbol) {
                    idText = TypeScript.stripQuotes(originalIdText) + ".ts";
                    symbol = search(idText);
                }
                if(!symbol) {
                    idText = TypeScript.stripQuotes(originalIdText) + ".str";
                    symbol = search(idText);
                }
                if(!symbol) {
                    idText = TypeScript.stripQuotes(originalIdText) + ".d.ts";
                    symbol = search(idText);
                }
                if(!symbol) {
                    idText = TypeScript.stripQuotes(originalIdText) + ".d.str";
                    symbol = search(idText);
                }
                if(!symbol && !TypeScript.isRelative(originalIdText)) {
                    idText = originalIdText;
                    var strippedIdText = TypeScript.stripQuotes(idText);
                    var path = TypeScript.getRootFilePath(TypeScript.switchToForwardSlashes(currentFileName));
                    while(symbol == null && path != "") {
                        idText = TypeScript.normalizePath(path + strippedIdText + ".ts");
                        symbol = search(idText);
                        if(symbol == null) {
                            idText = TypeScript.changePathToSTR(idText);
                            symbol = search(idText);
                        }
                        if(symbol == null) {
                            idText = TypeScript.changePathToDTS(idText);
                            symbol = search(idText);
                        }
                        if(symbol == null) {
                            idText = TypeScript.changePathToDSTR(idText);
                            symbol = search(idText);
                        }
                        if(symbol == null) {
                            if(path === '/') {
                                path = '';
                            } else {
                                path = TypeScript.normalizePath(path + "..");
                                path = path && path != '/' ? path + '/' : path;
                            }
                        }
                    }
                }
            }
            return symbol;
        };
        TypeChecker.prototype.resolveTypeMember = function (scope, dotNode) {
            var lhs = dotNode.operand1;
            var rhs = dotNode.operand2;
            var resultType = this.anyType;
            var lhsType = this.anyType;
            if(lhs && rhs && (rhs.nodeType == TypeScript.NodeType.Name)) {
                if(lhs.nodeType == TypeScript.NodeType.Dot) {
                    lhsType = this.resolveTypeMember(scope, lhs);
                } else {
                    if(lhs.nodeType == TypeScript.NodeType.Name) {
                        var identifier = lhs;
                        var symbol = scope.find(identifier.text, false, true);
                        if(symbol == null) {
                            this.errorReporter.unresolvedSymbol(identifier, identifier.actualText);
                        } else {
                            if(symbol.isType()) {
                                var typeSymbol = symbol;
                                if(typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == TypeScript.NodeType.Name) {
                                    var modPath = (typeSymbol.aliasLink.alias).text;
                                    var modSym = this.findSymbolForDynamicModule(modPath, this.locationInfo.filename, function (id) {
                                        return scope.find(id, false, true);
                                    });
                                    if(modSym) {
                                        typeSymbol.type = modSym.getType();
                                    }
                                }
                                if(TypeScript.optimizeModuleCodeGen && symbol) {
                                    var symType = symbol.getType();
                                    if(symType && typeSymbol.aliasLink && typeSymbol.onlyReferencedAsTypeRef) {
                                        var modDecl = symType.symbol.declAST;
                                        if(modDecl && TypeScript.hasFlag(modDecl.modFlags, TypeScript.ModuleFlags.IsDynamic)) {
                                            typeSymbol.onlyReferencedAsTypeRef = !this.resolvingBases;
                                        }
                                    }
                                }
                                if(!symbol.visible(scope, this)) {
                                    this.errorReporter.simpleError(lhs, "The symbol '" + identifier.actualText + "' is not visible at this point");
                                }
                                lhsType = symbol.getType();
                                identifier.sym = symbol;
                            } else {
                                this.errorReporter.simpleError(lhs, "Expected type");
                            }
                        }
                    }
                }
                if(!lhsType) {
                    lhsType = this.anyType;
                }
                if(lhsType != this.anyType) {
                    var rhsIdentifier = rhs;
                    var resultSymbol = this.lookupMemberTypeSymbol(lhsType, rhsIdentifier.text);
                    if(resultSymbol == null) {
                        resultType = this.anyType;
                        this.errorReporter.simpleError(dotNode, "Expected type");
                    } else {
                        resultType = resultSymbol.getType();
                        if(!resultSymbol.visible(scope, this)) {
                            this.errorReporter.simpleError(lhs, "The symbol '" + (rhs).actualText + "' is not visible at this point");
                        }
                    }
                    rhsIdentifier.sym = resultType.symbol;
                }
            }
            if(resultType.isClass()) {
                resultType = resultType.instanceType;
            }
            return resultType;
        };
        TypeChecker.prototype.resolveFuncDecl = function (funcDecl, scope, fgSym) {
            var functionGroupSymbol = this.createFunctionSignature(funcDecl, scope.container, scope, fgSym, false).declAST.type.symbol;
            var signatures;
            if(funcDecl.isConstructMember()) {
                signatures = functionGroupSymbol.type.construct.signatures;
            } else {
                if(funcDecl.isIndexerMember()) {
                    signatures = functionGroupSymbol.type.getInstanceType().index.signatures;
                } else {
                    signatures = functionGroupSymbol.type.call.signatures;
                }
            }
            var signature = signatures[signatures.length - 1];
            var len = signature.parameters.length;
            for(var i = 0; i < len; i++) {
                var paramSym = signature.parameters[i];
                this.resolveTypeLink(scope, paramSym.parameter.typeLink, true);
            }
            if(len && funcDecl.variableArgList) {
                if(!signature.parameters[len - 1].parameter.typeLink.type.elementType) {
                    this.errorReporter.simpleErrorFromSym(signature.parameters[len - 1].parameter.symbol, "... parameter must have array type");
                    signature.parameters[len - 1].parameter.typeLink.type = this.makeArrayType(signature.parameters[len - 1].parameter.typeLink.type);
                }
            }
            this.resolveTypeLink(scope, signature.returnType, funcDecl.isSignature());
            return functionGroupSymbol;
        };
        TypeChecker.prototype.resolveVarDecl = function (varDecl, scope) {
            var field = new TypeScript.ValueLocation();
            var fieldSymbol = new TypeScript.FieldSymbol(varDecl.id.text, varDecl.minChar, this.locationInfo.unitIndex, (varDecl.varFlags & TypeScript.VarFlags.Readonly) == TypeScript.VarFlags.None, field);
            fieldSymbol.transferVarFlags(varDecl.varFlags);
            field.symbol = fieldSymbol;
            fieldSymbol.declAST = varDecl;
            field.typeLink = TypeScript.getTypeLink(varDecl.typeExpr, this, varDecl.init == null);
            this.resolveTypeLink(scope, field.typeLink, true);
            varDecl.sym = fieldSymbol;
            varDecl.type = field.typeLink.type;
            return fieldSymbol;
        };
        TypeChecker.prototype.resolveTypeLink = function (scope, typeLink, supplyVar) {
            var arrayCount = 0;
            if(typeLink.type == null) {
                var ast = typeLink.ast;
                if(ast) {
                    while(typeLink.type == null) {
                        switch(ast.nodeType) {
                            case TypeScript.NodeType.Name: {
                                var identifier = ast;
                                var symbol = scope.find(identifier.text, false, true);
                                if(symbol == null) {
                                    typeLink.type = this.anyType;
                                    this.errorReporter.unresolvedSymbol(identifier, identifier.actualText);
                                } else {
                                    if(symbol.isType()) {
                                        if(!symbol.visible(scope, this)) {
                                            this.errorReporter.simpleError(ast, "The symbol '" + identifier.actualText + "' is not visible at this point");
                                        }
                                        identifier.sym = symbol;
                                        typeLink.type = symbol.getType();
                                        if(typeLink.type) {
                                            if(typeLink.type.isClass()) {
                                                typeLink.type = typeLink.type.instanceType;
                                            }
                                        } else {
                                            typeLink.type = this.anyType;
                                        }
                                    } else {
                                        typeLink.type = this.anyType;
                                        this.errorReporter.simpleError(ast, "Expected type");
                                    }
                                }
                                break;

                            }
                            case TypeScript.NodeType.Dot: {
                                typeLink.type = this.resolveTypeMember(scope, ast);
                                break;

                            }
                            case TypeScript.NodeType.TypeRef: {
                                var typeRef = ast;
                                arrayCount = typeRef.arrayCount;
                                ast = typeRef.term;
                                if(ast == null) {
                                    typeLink.type = this.anyType;
                                }
                                break;

                            }
                            case TypeScript.NodeType.InterfaceDeclaration: {
                                var interfaceDecl = ast;
                                var interfaceType = new TypeScript.Type();
                                var interfaceSymbol = new TypeScript.TypeSymbol((interfaceDecl.name).text, ast.minChar, ast.limChar - ast.minChar, this.locationInfo.unitIndex, interfaceType);
                                interfaceType.symbol = interfaceSymbol;
                                interfaceType.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                                interfaceType.containedScope = new TypeScript.SymbolTableScope(interfaceType.members, null, null, null, interfaceSymbol);
                                interfaceType.containedScope.container = interfaceSymbol;
                                interfaceType.memberScope = interfaceType.containedScope;
                                var memberList = interfaceDecl.members;
                                var props = memberList.members;
                                var propsLen = props.length;
                                for(var j = 0; j < propsLen; j++) {
                                    var propDecl = props[j];
                                    var propSym = null;
                                    var addMember = true;
                                    var id = null;
                                    if(propDecl.nodeType == TypeScript.NodeType.FuncDecl) {
                                        var funcDecl = propDecl;
                                        id = funcDecl.name;
                                        propSym = interfaceType.members.allMembers.lookup(funcDecl.getNameText());
                                        addMember = (propSym == null);
                                        if(funcDecl.isSpecialFn()) {
                                            addMember = false;
                                            propSym = this.resolveFuncDecl(funcDecl, scope, interfaceSymbol);
                                        } else {
                                            propSym = this.resolveFuncDecl(funcDecl, scope, propSym);
                                        }
                                        funcDecl.type = (propSym).type;
                                    } else {
                                        id = (propDecl).id;
                                        propSym = this.resolveVarDecl(propDecl, scope);
                                        addMember = !id.isMissing();
                                    }
                                    if(addMember) {
                                        if(id && TypeScript.hasFlag(id.flags, TypeScript.ASTFlags.OptionalName)) {
                                            propSym.flags |= TypeScript.SymbolFlags.Optional;
                                        }
                                        if(!interfaceType.members.allMembers.add(propSym.name, propSym)) {
                                            this.errorReporter.duplicateIdentifier(ast, propSym.name);
                                        }
                                    }
                                }
                                ast.type = interfaceType;
                                typeLink.type = interfaceType;
                                break;

                            }
                            case TypeScript.NodeType.FuncDecl: {
                                var tsym = this.resolveFuncDecl(ast, scope, null);
                                typeLink.type = tsym.type;
                                break;

                            }
                            default: {
                                typeLink.type = this.anyType;
                                this.errorReporter.simpleError(ast, "Expected type");
                                break;

                            }
                        }
                    }
                }
                for(var count = arrayCount; count > 0; count--) {
                    typeLink.type = this.makeArrayType(typeLink.type);
                }
                if(supplyVar && (typeLink.type == null)) {
                    typeLink.type = this.anyType;
                }
                if(typeLink.ast) {
                    typeLink.ast.type = typeLink.type;
                }
            }
        };
        TypeChecker.prototype.resolveBaseTypeLink = function (typeLink, scope) {
            this.resolvingBases = true;
            this.resolveTypeLink(scope, typeLink, true);
            this.resolvingBases = false;
            var extendsType = null;
            if(typeLink.type.isClass()) {
                extendsType = typeLink.type.instanceType;
            } else {
                extendsType = typeLink.type;
            }
            return extendsType;
        };
        TypeChecker.prototype.findMostApplicableSignature = function (signatures, args) {
            if(signatures.length == 1) {
                return {
                    sig: signatures[0].signature,
                    ambiguous: false
                };
            }
            var best = signatures[0];
            var Q = null;
            var AType = null;
            var PType = null;
            var QType = null;
            var ambiguous = false;
            for(var qSig = 1; qSig < signatures.length; qSig++) {
                Q = signatures[qSig];
                var i = 0;
                for(i = 0; args && i < args.members.length; i++) {
                    AType = args.members[i].type;
                    PType = i < best.signature.parameters.length ? best.signature.parameters[i].getType() : best.signature.parameters[best.signature.parameters.length - 1].getType().elementType;
                    QType = i < Q.signature.parameters.length ? Q.signature.parameters[i].getType() : Q.signature.parameters[Q.signature.parameters.length - 1].getType().elementType;
                    if(this.typesAreIdentical(PType, QType)) {
                        continue;
                    } else {
                        if(this.typesAreIdentical(AType, PType)) {
                            break;
                        } else {
                            if(this.typesAreIdentical(AType, QType)) {
                                best = Q;
                                break;
                            } else {
                                if(this.sourceIsSubtypeOfTarget(PType, QType)) {
                                    break;
                                } else {
                                    if(this.sourceIsSubtypeOfTarget(QType, PType)) {
                                        best = Q;
                                        break;
                                    } else {
                                        if(Q.hadProvisionalErrors) {
                                            break;
                                        } else {
                                            if(best.hadProvisionalErrors) {
                                                best = Q;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if(!args || i == args.members.length) {
                    var collection = {
                        getLength: function () {
                            return 2;
                        },
                        setTypeAtIndex: function (index, type) {
                        },
                        getTypeAtIndex: function (index) {
                            return index ? Q.signature.returnType.type : best.signature.returnType.type;
                        }
                    };
                    var bct = this.findBestCommonType(best.signature.returnType.type, null, collection, true);
                    ambiguous = !bct;
                } else {
                    ambiguous = false;
                }
            }
            return {
                sig: best.signature,
                ambiguous: ambiguous
            };
        };
        TypeChecker.prototype.getApplicableSignatures = function (signatures, args, comparisonInfo) {
            var applicableSigs = [];
            var memberType = null;
            var miss = false;
            var cxt = null;
            var hadProvisionalErrors = false;
            for(var i = 0; i < signatures.length; i++) {
                miss = false;
                for(var j = 0; j < args.members.length; j++) {
                    if(j >= signatures[i].parameters.length) {
                        continue;
                    }
                    memberType = signatures[i].parameters[j].getType();
                    if(signatures[i].declAST.variableArgList && (j >= signatures[i].nonOptionalParameterCount - 1) && memberType.isArray()) {
                        memberType = memberType.elementType;
                    }
                    if(memberType == this.anyType) {
                        continue;
                    } else {
                        if(args.members[j].nodeType == TypeScript.NodeType.FuncDecl) {
                            if(this.typeFlow.functionInterfaceType && memberType == this.typeFlow.functionInterfaceType) {
                                continue;
                            }
                            if(!this.canContextuallyTypeFunction(memberType, args.members[j], true)) {
                                if(this.canContextuallyTypeFunction(memberType, args.members[j], false)) {
                                    this.typeFlow.typeCheck(args.members[j]);
                                    if(!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {
                                        break;
                                    }
                                } else {
                                    break;
                                }
                            } else {
                                this.typeCheckWithContextualType(memberType, true, true, args.members[j]);
                                this.cleanStartedPTO();
                                hadProvisionalErrors = this.hadProvisionalErrors();
                                if(!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {
                                    if(comparisonInfo) {
                                        comparisonInfo.setMessage("Could not apply type '" + memberType.getTypeName() + "' to argument " + (j + 1) + ", which is of type '" + args.members[j].type.getTypeName() + "'");
                                    }
                                    miss = true;
                                }
                                this.resetProvisionalErrors();
                                if(miss) {
                                    break;
                                }
                            }
                        } else {
                            if(args.members[j].nodeType == TypeScript.NodeType.ObjectLit) {
                                if(this.typeFlow.objectInterfaceType && memberType == this.typeFlow.objectInterfaceType) {
                                    continue;
                                }
                                this.typeCheckWithContextualType(memberType, true, true, args.members[j]);
                                this.cleanStartedPTO();
                                hadProvisionalErrors = this.hadProvisionalErrors();
                                if(!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {
                                    if(comparisonInfo) {
                                        comparisonInfo.setMessage("Could not apply type '" + memberType.getTypeName() + "' to argument " + (j + 1) + ", which is of type '" + args.members[j].type.getTypeName() + "'");
                                    }
                                    miss = true;
                                }
                                this.resetProvisionalErrors();
                                if(miss) {
                                    break;
                                }
                            } else {
                                if(args.members[j].nodeType == TypeScript.NodeType.ArrayLit) {
                                    if(this.typeFlow.arrayInterfaceType && memberType == this.typeFlow.arrayInterfaceType) {
                                        continue;
                                    }
                                    this.typeCheckWithContextualType(memberType, true, true, args.members[j]);
                                    this.cleanStartedPTO();
                                    hadProvisionalErrors = this.hadProvisionalErrors();
                                    if(!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {
                                        if(comparisonInfo) {
                                            comparisonInfo.setMessage("Could not apply type '" + memberType.getTypeName() + "' to argument " + (j + 1) + ", which is of type '" + args.members[j].type.getTypeName() + "'");
                                        }
                                        break;
                                    }
                                    this.resetProvisionalErrors();
                                    if(miss) {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                if(j == args.members.length) {
                    applicableSigs[applicableSigs.length] = {
                        signature: signatures[i],
                        hadProvisionalErrors: hadProvisionalErrors
                    };
                }
                hadProvisionalErrors = false;
            }
            return applicableSigs;
        };
        TypeChecker.prototype.canContextuallyTypeFunction = function (candidateType, funcDecl, beStringent) {
            if(funcDecl.isParenthesized || funcDecl.isMethod() || beStringent && funcDecl.returnTypeAnnotation || funcDecl.isInlineCallLiteral) {
                return false;
            }
            beStringent = beStringent || (this.typeFlow.functionInterfaceType == candidateType);
            if(!beStringent) {
                return true;
            }
            if(!funcDecl.signature) {
                this.createFunctionSignature(funcDecl, this.typeFlow.scope.container, this.typeFlow.scope, null, null);
                this.typeFlow.typeCheck(funcDecl);
            }
            var signature = funcDecl.signature;
            var paramLen = signature.parameters.length;
            for(var i = 0; i < paramLen; i++) {
                var param = signature.parameters[i];
                var symbol = param;
                var argDecl = symbol.declAST;
                if(beStringent && argDecl.typeExpr) {
                    return false;
                }
            }
            if(candidateType.construct && candidateType.call) {
                return false;
            }
            var candidateSigs = candidateType.construct ? candidateType.construct : candidateType.call;
            if(!candidateSigs || candidateSigs.signatures.length > 1) {
                return false;
            }
            return true;
        };
        TypeChecker.prototype.canContextuallyTypeObjectLiteral = function (targetType, objectLit) {
            if(targetType == this.typeFlow.objectInterfaceType) {
                return true;
            }
            var memberDecls = objectLit.operand;
            if(!(memberDecls && targetType.memberScope)) {
                return false;
            }
            var id = null;
            var targetMember = null;
            var text = "";
            var foundSyms = {
            };
            for(var i = 0; i < memberDecls.members.length; i++) {
                id = (memberDecls.members[i]).operand1;
                if(id.nodeType == TypeScript.NodeType.Name) {
                    text = (id).text;
                } else {
                    if(id.nodeType == TypeScript.NodeType.QString) {
                        var idText = (id).text;
                        text = idText.substring(1, idText.length - 1);
                    } else {
                        return false;
                    }
                }
                targetMember = targetType.memberScope.find(text, true, false);
                if(!targetMember) {
                    return false;
                }
                foundSyms[text] = true;
            }
            var targetMembers = targetType.memberScope.getAllValueSymbolNames(true);
            for(var i = 0; i < targetMembers.length; i++) {
                var memberName = targetMembers[i];
                var memberSym = targetType.memberScope.find(memberName, true, false);
                if(!foundSyms[targetMembers[i]] && !TypeScript.hasFlag(memberSym.flags, TypeScript.SymbolFlags.Optional)) {
                    return false;
                }
            }
            return true;
        };
        TypeChecker.prototype.widenType = function (t) {
            if(t == this.undefinedType || t == this.nullType) {
                return this.anyType;
            }
            return t;
        };
        TypeChecker.prototype.isNullOrUndefinedType = function (t) {
            return t == this.undefinedType || t == this.nullType;
        };
        TypeChecker.prototype.findBestCommonType = function (initialType, targetType, collection, acceptVoid, comparisonInfo) {
            var i = 0;
            var len = collection.getLength();
            var nlastChecked = 0;
            var bestCommonType = initialType;
            if(targetType) {
                bestCommonType = bestCommonType ? bestCommonType.mergeOrdered(targetType, this, acceptVoid) : targetType;
            }
            var convergenceType = bestCommonType;
            while(nlastChecked < len) {
                for(i = 0; i < len; i++) {
                    if(i == nlastChecked) {
                        continue;
                    }
                    if(convergenceType && (bestCommonType = convergenceType.mergeOrdered(collection.getTypeAtIndex(i), this, acceptVoid, comparisonInfo))) {
                        convergenceType = bestCommonType;
                    }
                    if(bestCommonType == this.anyType || bestCommonType == null) {
                        break;
                    } else {
                        if(targetType) {
                            collection.setTypeAtIndex(i, targetType);
                        }
                    }
                }
                if(convergenceType && bestCommonType) {
                    break;
                }
                nlastChecked++;
                if(nlastChecked < len) {
                    convergenceType = collection.getTypeAtIndex(nlastChecked);
                }
            }
            return acceptVoid ? bestCommonType : (bestCommonType == this.voidType ? null : bestCommonType);
        };
        TypeChecker.prototype.typesAreIdentical = function (t1, t2) {
            if(t1 == t2) {
                return true;
            }
            if(!t1 || !t2) {
                return false;
            }
            if(t1.isClass() || t1.isClassInstance()) {
                return false;
            }
            var comboId = (t2.typeID << 16) | t1.typeID;
            if(this.identicalCache[comboId]) {
                return true;
            }
            if((t1.typeFlags & TypeScript.TypeFlags.IsEnum) || (t2.typeFlags & TypeScript.TypeFlags.IsEnum)) {
                return false;
            }
            if(t1.isArray() || t2.isArray()) {
                if(!(t1.isArray() && t2.isArray())) {
                    return false;
                }
                this.identicalCache[comboId] = false;
                var ret = this.typesAreIdentical(t1.elementType, t2.elementType);
                if(ret) {
                    this.subtypeCache[comboId] = true;
                } else {
                    this.subtypeCache[comboId] = undefined;
                }
                return ret;
            }
            if(t1.primitiveTypeClass != t2.primitiveTypeClass) {
                return false;
            }
            this.identicalCache[comboId] = false;
            if(t1.memberScope && t2.memberScope) {
                var t1MemberKeys = t1.memberScope.getAllValueSymbolNames(true).sort();
                var t2MemberKeys = t2.memberScope.getAllValueSymbolNames(true).sort();
                if(t1MemberKeys.length != t2MemberKeys.length) {
                    this.identicalCache[comboId] = undefined;
                    return false;
                }
                var t1MemberSymbol = null;
                var t2MemberSymbol = null;
                var t1MemberType = null;
                var t2MemberType = null;
                for(var iMember = 0; iMember < t1MemberKeys.length; iMember++) {
                    if(t1MemberKeys[iMember] != t2MemberKeys[iMember]) {
                        this.identicalCache[comboId] = undefined;
                        return false;
                    }
                    t1MemberSymbol = t1.memberScope.find(t1MemberKeys[iMember], false, false);
                    t2MemberSymbol = t2.memberScope.find(t2MemberKeys[iMember], false, false);
                    if((t1MemberSymbol.flags & TypeScript.SymbolFlags.Optional) != (t2MemberSymbol.flags & TypeScript.SymbolFlags.Optional)) {
                        this.identicalCache[comboId] = undefined;
                        return false;
                    }
                    t1MemberType = t1MemberSymbol.getType();
                    t2MemberType = t2MemberSymbol.getType();
                    if(t1MemberType && t2MemberType && (this.identicalCache[(t2MemberType.typeID << 16) | t1MemberType.typeID] != undefined)) {
                        continue;
                    }
                    if(!this.typesAreIdentical(t1MemberType, t2MemberType)) {
                        this.identicalCache[comboId] = undefined;
                        return false;
                    }
                }
            } else {
                if(t1.memberScope || t2.memberScope) {
                    this.identicalCache[comboId] = undefined;
                    return false;
                }
            }
            if(!this.signatureGroupsAreIdentical(t1.call, t2.call)) {
                this.identicalCache[comboId] = undefined;
                return false;
            }
            if(!this.signatureGroupsAreIdentical(t1.construct, t2.construct)) {
                this.identicalCache[comboId] = undefined;
                return false;
            }
            if(!this.signatureGroupsAreIdentical(t1.index, t2.index)) {
                this.identicalCache[comboId] = undefined;
                return false;
            }
            this.identicalCache[comboId] = true;
            return true;
        };
        TypeChecker.prototype.signatureGroupsAreIdentical = function (sg1, sg2) {
            if(sg1 == sg2) {
                return true;
            }
            if(!sg1 || !sg2) {
                return false;
            }
            if(sg1.signatures.length != sg2.signatures.length) {
                return false;
            }
            var sig1 = null;
            var sig2 = null;
            var sigsMatch = false;
            for(var iSig1 = 0; iSig1 < sg1.signatures.length; iSig1++) {
                sig1 = sg1.signatures[iSig1];
                for(var iSig2 = 0; iSig2 < sg2.signatures.length; iSig2++) {
                    sig2 = sg2.signatures[iSig2];
                    if(this.signaturesAreIdentical(sig1, sig2)) {
                        sigsMatch = true;
                        break;
                    }
                }
                if(sigsMatch) {
                    sigsMatch = false;
                    continue;
                }
                return false;
            }
            return true;
        };
        TypeChecker.prototype.signaturesAreIdentical = function (s1, s2) {
            if(s1.hasVariableArgList != s2.hasVariableArgList) {
                return false;
            }
            if(s1.nonOptionalParameterCount != s2.nonOptionalParameterCount) {
                return false;
            }
            if(s1.parameters.length != s2.parameters.length) {
                return false;
            }
            if(!this.typesAreIdentical(s1.returnType.type, s2.returnType.type)) {
                return false;
            }
            for(var iParam = 0; iParam < s1.parameters.length; iParam++) {
                if(!this.typesAreIdentical(s1.parameters[iParam].parameter.typeLink.type, s2.parameters[iParam].parameter.typeLink.type)) {
                    return false;
                }
            }
            return true;
        };
        TypeChecker.prototype.sourceIsSubtypeOfTarget = function (source, target, comparisonInfo) {
            return this.sourceIsRelatableToTarget(source, target, false, this.subtypeCache, comparisonInfo);
        };
        TypeChecker.prototype.signatureGroupIsSubtypeOfTarget = function (sg1, sg2, comparisonInfo) {
            return this.signatureGroupIsRelatableToTarget(sg1, sg2, false, this.subtypeCache, comparisonInfo);
        };
        TypeChecker.prototype.signatureIsSubtypeOfTarget = function (s1, s2, comparisonInfo) {
            return this.signatureIsRelatableToTarget(s1, s2, false, this.subtypeCache, comparisonInfo);
        };
        TypeChecker.prototype.sourceIsAssignableToTarget = function (source, target, comparisonInfo) {
            return this.sourceIsRelatableToTarget(source, target, true, this.assignableCache, comparisonInfo);
        };
        TypeChecker.prototype.signatureGroupIsAssignableToTarget = function (sg1, sg2, comparisonInfo) {
            return this.signatureGroupIsRelatableToTarget(sg1, sg2, true, this.assignableCache, comparisonInfo);
        };
        TypeChecker.prototype.signatureIsAssignableToTarget = function (s1, s2, comparisonInfo) {
            return this.signatureIsRelatableToTarget(s1, s2, true, this.assignableCache, comparisonInfo);
        };
        TypeChecker.prototype.sourceIsRelatableToTarget = function (source, target, assignableTo, comparisonCache, comparisonInfo) {
            if(source == target) {
                return true;
            }
            if(!(source && target)) {
                return true;
            }
            var comboId = (source.typeID << 16) | target.typeID;
            if(comparisonCache[comboId] != undefined) {
                return true;
            }
            if(assignableTo) {
                if(source == this.anyType || target == this.anyType) {
                    return true;
                }
            } else {
                if(target == this.anyType) {
                    return true;
                }
            }
            if(source == this.undefinedType) {
                return true;
            }
            if((source == this.nullType) && (target != this.undefinedType && target != this.voidType)) {
                return true;
            }
            if(target == this.numberType && (source.typeFlags & TypeScript.TypeFlags.IsEnum)) {
                return true;
            }
            if(source == this.numberType && (target.typeFlags & TypeScript.TypeFlags.IsEnum)) {
                return true;
            }
            if((source.typeFlags & TypeScript.TypeFlags.IsEnum) || (target.typeFlags & TypeScript.TypeFlags.IsEnum)) {
                return false;
            }
            if(source.isArray() || target.isArray()) {
                if(!(source.isArray() && target.isArray())) {
                    return false;
                }
                comparisonCache[comboId] = false;
                var ret = this.sourceIsRelatableToTarget(source.elementType, target.elementType, assignableTo, comparisonCache, comparisonInfo);
                if(ret) {
                    comparisonCache[comboId] = true;
                } else {
                    comparisonCache[comboId] = undefined;
                }
                return ret;
            }
            if(source.primitiveTypeClass != target.primitiveTypeClass) {
                if(target.primitiveTypeClass == TypeScript.Primitive.None) {
                    if(source == this.numberType && this.typeFlow.numberInterfaceType) {
                        source = this.typeFlow.numberInterfaceType;
                    } else {
                        if(source == this.stringType && this.typeFlow.stringInterfaceType) {
                            source = this.typeFlow.stringInterfaceType;
                        } else {
                            if(source == this.booleanType && this.typeFlow.booleanInterfaceType) {
                                source = this.typeFlow.booleanInterfaceType;
                            } else {
                                return false;
                            }
                        }
                    }
                } else {
                    return false;
                }
            }
            comparisonCache[comboId] = false;
            if(source.hasBase(target)) {
                comparisonCache[comboId] = true;
                return true;
            }
            if(this.typeFlow.objectInterfaceType && target == this.typeFlow.objectInterfaceType) {
                return true;
            }
            if(this.typeFlow.functionInterfaceType && (source.call || source.construct) && target == this.typeFlow.functionInterfaceType) {
                return true;
            }
            if(target.isClass() || target.isClassInstance()) {
                comparisonCache[comboId] = undefined;
                return false;
            }
            if(target.memberScope && source.memberScope) {
                var mPropKeys = target.memberScope.getAllValueSymbolNames(true);
                var mProp = null;
                var nProp = null;
                var mPropType = null;
                var nPropType = null;
                var inferenceSymbol = null;
                for(var iMProp = 0; iMProp < mPropKeys.length; iMProp++) {
                    mProp = target.memberScope.find(mPropKeys[iMProp], false, false);
                    nProp = source.memberScope.find(mPropKeys[iMProp], false, false);
                    if(mProp.name == "arguments" && this.typeFlow.iargumentsInterfaceType && (this.typeFlow.iargumentsInterfaceType.symbol.flags & TypeScript.SymbolFlags.CompilerGenerated) && mProp.kind() == TypeScript.SymbolKind.Variable && (mProp).variable.typeLink.type == this.typeFlow.iargumentsInterfaceType) {
                        continue;
                    }
                    if(mProp.isInferenceSymbol()) {
                        inferenceSymbol = mProp;
                        if(inferenceSymbol.typeCheckStatus == TypeScript.TypeCheckStatus.NotStarted) {
                            this.typeFlow.typeCheck(mProp.declAST);
                        }
                    }
                    mPropType = mProp.getType();
                    if(!nProp) {
                        if(this.typeFlow.objectInterfaceType) {
                            nProp = this.typeFlow.objectInterfaceType.memberScope.find(mPropKeys[iMProp], false, false);
                        }
                        if(!nProp) {
                            if(this.typeFlow.functionInterfaceType && (mPropType.call || mPropType.construct)) {
                                nProp = this.typeFlow.functionInterfaceType.memberScope.find(mPropKeys[iMProp], false, false);
                            }
                            if(!nProp) {
                                if(!(mProp.flags & TypeScript.SymbolFlags.Optional)) {
                                    comparisonCache[comboId] = undefined;
                                    if(comparisonInfo) {
                                        comparisonInfo.flags |= TypeScript.TypeRelationshipFlags.RequiredPropertyIsMissing;
                                        comparisonInfo.addMessageToFront("Type '" + source.getTypeName() + "' is missing property '" + mPropKeys[iMProp] + "' from type '" + target.getTypeName() + "'");
                                    }
                                    return false;
                                } else {
                                    continue;
                                }
                            }
                        }
                    }
                    if(nProp.isInferenceSymbol()) {
                        inferenceSymbol = nProp;
                        if(inferenceSymbol.typeCheckStatus == TypeScript.TypeCheckStatus.NotStarted) {
                            this.typeFlow.typeCheck(nProp.declAST);
                        }
                    }
                    nPropType = nProp.getType();
                    if(mPropType && nPropType && (comparisonCache[(nPropType.typeID << 16) | mPropType.typeID] != undefined)) {
                        continue;
                    }
                    if(!this.sourceIsRelatableToTarget(nPropType, mPropType, assignableTo, comparisonCache, comparisonInfo)) {
                        comparisonCache[comboId] = undefined;
                        if(comparisonInfo) {
                            comparisonInfo.flags |= TypeScript.TypeRelationshipFlags.IncompatiblePropertyTypes;
                            comparisonInfo.addMessageToFront("Types of property '" + mProp.name + "' of types '" + source.getTypeName() + "' and '" + target.getTypeName() + "' are incompatible");
                        }
                        return false;
                    }
                }
            }
            if(source.call || target.call) {
                if(!this.signatureGroupIsRelatableToTarget(source.call, target.call, assignableTo, comparisonCache, comparisonInfo)) {
                    if(comparisonInfo) {
                        if(source.call && target.call) {
                            comparisonInfo.addMessageToFront("Call signatures of types '" + source.getTypeName() + "' and '" + target.getTypeName() + "' are incompatible");
                        } else {
                            var hasSig = target.call ? target.getTypeName() : source.getTypeName();
                            var lacksSig = !target.call ? target.getTypeName() : source.getTypeName();
                            comparisonInfo.setMessage("Type '" + hasSig + "' requires a call signature, but Type '" + lacksSig + "' lacks one");
                        }
                        comparisonInfo.flags |= TypeScript.TypeRelationshipFlags.IncompatibleSignatures;
                    }
                    comparisonCache[comboId] = undefined;
                    return false;
                }
            }
            if(source.construct || target.construct) {
                if(!this.signatureGroupIsRelatableToTarget(source.construct, target.construct, assignableTo, comparisonCache, comparisonInfo)) {
                    if(comparisonInfo) {
                        if(source.construct && target.construct) {
                            comparisonInfo.addMessageToFront("Construct signatures of types '" + source.getTypeName() + "' and '" + target.getTypeName() + "' are incompatible");
                        } else {
                            var hasSig = target.construct ? target.getTypeName() : source.getTypeName();
                            var lacksSig = !target.construct ? target.getTypeName() : source.getTypeName();
                            comparisonInfo.setMessage("Type '" + hasSig + "' requires a construct signature, but Type '" + lacksSig + "' lacks one");
                        }
                        comparisonInfo.flags |= TypeScript.TypeRelationshipFlags.IncompatibleSignatures;
                    }
                    comparisonCache[comboId] = undefined;
                    return false;
                }
            }
            if(target.index) {
                var targetIndex = !target.index && this.typeFlow.objectInterfaceType ? this.typeFlow.objectInterfaceType.index : target.index;
                var sourceIndex = !source.index && this.typeFlow.objectInterfaceType ? this.typeFlow.objectInterfaceType.index : source.index;
                if(!this.signatureGroupIsRelatableToTarget(sourceIndex, targetIndex, assignableTo, comparisonCache, comparisonInfo)) {
                    if(comparisonInfo) {
                        comparisonInfo.addMessageToFront("Index signatures of types '" + source.getTypeName() + "' and '" + target.getTypeName() + "' are incompatible");
                        comparisonInfo.flags |= TypeScript.TypeRelationshipFlags.IncompatibleSignatures;
                    }
                    comparisonCache[comboId] = undefined;
                    return false;
                }
            }
            comparisonCache[comboId] = true;
            return true;
        };
        TypeChecker.prototype.signatureGroupIsRelatableToTarget = function (sourceSG, targetSG, assignableTo, comparisonCache, comparisonInfo) {
            if(sourceSG == targetSG) {
                return true;
            }
            if(!(sourceSG && targetSG)) {
                return false;
            }
            var mSig = null;
            var nSig = null;
            var foundMatch = false;
            for(var iMSig = 0; iMSig < targetSG.signatures.length; iMSig++) {
                mSig = targetSG.signatures[iMSig];
                for(var iNSig = 0; iNSig < sourceSG.signatures.length; iNSig++) {
                    nSig = sourceSG.signatures[iNSig];
                    if(this.signatureIsRelatableToTarget(nSig, mSig, assignableTo, comparisonCache, comparisonInfo)) {
                        foundMatch = true;
                        break;
                    }
                }
                if(foundMatch) {
                    foundMatch = false;
                    continue;
                }
                return false;
            }
            return true;
        };
        TypeChecker.prototype.signatureIsRelatableToTarget = function (sourceSig, targetSig, assignableTo, comparisonCache, comparisonInfo) {
            if(!sourceSig.parameters || !targetSig.parameters) {
                return false;
            }
            var targetVarArgCount = targetSig.hasVariableArgList ? targetSig.nonOptionalParameterCount - 1 : targetSig.nonOptionalParameterCount;
            var sourceVarArgCount = sourceSig.hasVariableArgList ? sourceSig.nonOptionalParameterCount - 1 : sourceSig.nonOptionalParameterCount;
            if(sourceVarArgCount > targetVarArgCount && !targetSig.hasVariableArgList) {
                if(comparisonInfo) {
                    comparisonInfo.flags |= TypeScript.TypeRelationshipFlags.SourceSignatureHasTooManyParameters;
                    comparisonInfo.addMessageToFront("Call signature expects " + targetVarArgCount + " or fewer parameters");
                }
                return false;
            }
            var sourceReturnType = sourceSig.returnType.type;
            var targetReturnType = targetSig.returnType.type;
            if(targetReturnType != this.voidType) {
                if(!this.sourceIsRelatableToTarget(sourceReturnType, targetReturnType, assignableTo, comparisonCache, comparisonInfo)) {
                    if(comparisonInfo) {
                        comparisonInfo.flags |= TypeScript.TypeRelationshipFlags.IncompatibleReturnTypes;
                    }
                    return false;
                }
            }
            var len = (sourceVarArgCount < targetVarArgCount && sourceSig.hasVariableArgList) ? targetVarArgCount : sourceVarArgCount;
            var sourceParamType = null;
            var targetParamType = null;
            var sourceParamName = "";
            var targetParamName = "";
            for(var iSource = 0, iTarget = 0; iSource < len; iSource++ , iTarget++) {
                if(!sourceSig.hasVariableArgList || iSource < sourceVarArgCount) {
                    sourceParamType = (sourceSig.parameters[iSource]).parameter.typeLink.type;
                    sourceParamName = (sourceSig.parameters[iSource]).parameter.symbol.name;
                } else {
                    if(iSource == sourceVarArgCount) {
                        sourceParamType = (sourceSig.parameters[iSource]).parameter.typeLink.type;
                        if(sourceParamType.elementType) {
                            sourceParamType = sourceParamType.elementType;
                        }
                        sourceParamName = (sourceSig.parameters[iSource]).parameter.symbol.name;
                    }
                }
                if(iTarget < targetSig.parameters.length && iTarget < targetVarArgCount) {
                    targetParamType = (targetSig.parameters[iTarget]).parameter.typeLink.type;
                    targetParamName = (targetSig.parameters[iTarget]).parameter.symbol.name;
                } else {
                    if(targetSig.hasVariableArgList && iTarget == targetVarArgCount) {
                        targetParamType = (targetSig.parameters[iTarget]).parameter.typeLink.type;
                        if(targetParamType.elementType) {
                            targetParamType = targetParamType.elementType;
                        }
                        targetParamName = (targetSig.parameters[iTarget]).parameter.symbol.name;
                    }
                }
                if(!(this.sourceIsRelatableToTarget(sourceParamType, targetParamType, assignableTo, comparisonCache, comparisonInfo) || this.sourceIsRelatableToTarget(targetParamType, sourceParamType, assignableTo, comparisonCache, comparisonInfo))) {
                    if(comparisonInfo) {
                        comparisonInfo.flags |= TypeScript.TypeRelationshipFlags.IncompatibleParameterTypes;
                    }
                    return false;
                }
            }
            return true;
        };
        return TypeChecker;
    })();
    TypeScript.TypeChecker = TypeChecker;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var Continuation = (function () {
        function Continuation(normalBlock) {
            this.normalBlock = normalBlock;
            this.exceptionBlock = -1;
        }
        return Continuation;
    })();
    TypeScript.Continuation = Continuation;    
    function getBaseTypeLinks(bases, baseTypeLinks) {
        if(bases) {
            var len = bases.members.length;
            if(baseTypeLinks == null) {
                baseTypeLinks = new Array();
            }
            for(var i = 0; i < len; i++) {
                var baseExpr = bases.members[i];
                var name = baseExpr;
                var typeLink = new TypeScript.TypeLink();
                typeLink.ast = name;
                baseTypeLinks[baseTypeLinks.length] = typeLink;
            }
        }
        return baseTypeLinks;
    }
    function getBases(type, typeDecl) {
        type.extendsTypeLinks = getBaseTypeLinks(typeDecl.extendsList, type.extendsTypeLinks);
        type.implementsTypeLinks = getBaseTypeLinks(typeDecl.implementsList, type.implementsTypeLinks);
    }
    function addPrototypeField(classType, ast, context) {
        var field = new TypeScript.ValueLocation();
        field.typeLink = new TypeScript.TypeLink();
        field.typeLink.ast = ast;
        field.typeLink.type = classType.instanceType;
        var fieldSymbol = new TypeScript.FieldSymbol("prototype", ast.minChar, context.checker.locationInfo.unitIndex, true, field);
        fieldSymbol.flags |= (TypeScript.SymbolFlags.Property | TypeScript.SymbolFlags.BuiltIn);
        field.symbol = fieldSymbol;
        fieldSymbol.declAST = ast;
        classType.members.addPublicMember("prototype", fieldSymbol);
    }
    function createNewConstructGroupForType(type) {
        var signature = new TypeScript.Signature();
        signature.returnType = new TypeScript.TypeLink();
        signature.returnType.type = type.instanceType;
        signature.parameters = [];
        type.construct = new TypeScript.SignatureGroup();
        type.construct.addSignature(signature);
    }
    TypeScript.createNewConstructGroupForType = createNewConstructGroupForType;
    function cloneParentConstructGroupForChildType(child, parent) {
        child.construct = new TypeScript.SignatureGroup();
        var sig = null;
        if(!parent.construct) {
            createNewConstructGroupForType(parent);
        }
        for(var i = 0; i < parent.construct.signatures.length; i++) {
            sig = new TypeScript.Signature();
            sig.parameters = parent.construct.signatures[i].parameters;
            sig.nonOptionalParameterCount = parent.construct.signatures[i].nonOptionalParameterCount;
            sig.typeCheckStatus = parent.construct.signatures[i].typeCheckStatus;
            sig.declAST = parent.construct.signatures[i].declAST;
            sig.returnType = new TypeScript.TypeLink();
            sig.returnType.type = child.instanceType;
            child.construct.addSignature(sig);
        }
    }
    TypeScript.cloneParentConstructGroupForChildType = cloneParentConstructGroupForChildType;
    TypeScript.globalId = "__GLO";
    function findTypeSymbolInScopeChain(name, scopeChain) {
        var symbol = scopeChain.scope.find(name, false, true);
        if(symbol == null && scopeChain.previous) {
            symbol = findTypeSymbolInScopeChain(name, scopeChain.previous);
        }
        return symbol;
    }
    function findSymbolFromAlias(alias, context) {
        var symbol = null;
        switch(alias.nodeType) {
            case TypeScript.NodeType.Name: {
                var name = (alias).text;
                var isDynamic = TypeScript.isQuoted(name);
                var findSym = function (id) {
                    if(context.members) {
                        return context.members.lookup(name);
                    } else {
                        return findTypeSymbolInScopeChain(name, context.topLevelScope);
                    }
                };
                if(isDynamic) {
                    symbol = context.tcContext.checker.findSymbolForDynamicModule(name, context.tcContext.script.locationInfo.filename, findSym);
                } else {
                    symbol = findSym(name);
                }
                break;

            }
            case TypeScript.NodeType.Dot: {
                var dottedExpr = alias;
                var op1Sym = findSymbolFromAlias(dottedExpr.operand1, context);
                if(op1Sym && op1Sym.getType()) {
                    symbol = findSymbolFromAlias(dottedExpr.operand2, context);
                }
                break;

            }
            default: {
                break;

            }
        }
        if(symbol) {
            var symType = symbol.getType();
            if(symType) {
                var members = symType.members;
                if(members) {
                    context.members = members.publicMembers;
                }
            }
        }
        return symbol;
    }
    function preCollectImportTypes(ast, parent, context) {
        var scopeChain = context.scopeChain;
        var typeSymbol = null;
        var modType = null;
        var importDecl = ast;
        var aliasedModSymbol = findSymbolFromAlias(importDecl.alias, {
            topLevelScope: scopeChain,
            members: null,
            tcContext: context
        });
        var isGlobal = context.scopeChain.container == context.checker.gloMod;
        if(aliasedModSymbol) {
            var aliasedModType = aliasedModSymbol.getType();
            if(aliasedModType) {
                modType = aliasedModType;
            }
        }
        typeSymbol = new TypeScript.TypeSymbol(importDecl.id.text, importDecl.id.minChar, importDecl.limChar - importDecl.minChar, context.checker.locationInfo.unitIndex, modType);
        typeSymbol.aliasLink = importDecl;
        if(context.scopeChain.moduleDecl) {
            typeSymbol.flags |= TypeScript.SymbolFlags.ModuleMember;
            typeSymbol.declModule = context.scopeChain.moduleDecl;
        }
        typeSymbol.declAST = importDecl;
        importDecl.id.sym = typeSymbol;
        scopeChain.scope.enter(scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isGlobal, true, false);
        scopeChain.scope.enter(scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isGlobal, false, false);
        return true;
    }
    TypeScript.preCollectImportTypes = preCollectImportTypes;
    function preCollectModuleTypes(ast, parent, context) {
        var scopeChain = context.scopeChain;
        var moduleDecl = ast;
        var isAmbient = TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.Ambient);
        var isEnum = TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.IsEnum);
        var isGlobal = context.scopeChain.container == context.checker.gloMod;
        var isExported = TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.Exported);
        var modName = (moduleDecl.name).text;
        var isDynamic = TypeScript.isQuoted(modName);
        var symbol = scopeChain.scope.findLocal(modName, false, false);
        var typeSymbol = null;
        var modType = null;
        if((symbol == null) || (symbol.kind() != TypeScript.SymbolKind.Type)) {
            if(modType == null) {
                var enclosedTypes = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                var ambientEnclosedTypes = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                modType = new TypeScript.ModuleType(enclosedTypes, ambientEnclosedTypes);
                if(isEnum) {
                    modType.typeFlags |= TypeScript.TypeFlags.IsEnum;
                }
                modType.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                modType.ambientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                modType.setHasImplementation();
            }
            typeSymbol = new TypeScript.TypeSymbol(modName, moduleDecl.name.minChar, modName.length, context.checker.locationInfo.unitIndex, modType);
            typeSymbol.isDynamic = TypeScript.isQuoted(moduleDecl.prettyName);
            if(context.scopeChain.moduleDecl) {
                typeSymbol.declModule = context.scopeChain.moduleDecl;
            }
            typeSymbol.declAST = moduleDecl;
            typeSymbol.prettyName = moduleDecl.prettyName;
            scopeChain.scope.enter(scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
            scopeChain.scope.enter(scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, false, isAmbient);
            modType.symbol = typeSymbol;
        } else {
            if(symbol && symbol.declAST && symbol.declAST.nodeType != TypeScript.NodeType.ModuleDeclaration) {
                context.checker.errorReporter.simpleError(moduleDecl, "Conflicting symbol name for module '" + modName + "'");
            }
            typeSymbol = symbol;
            var publicEnclosedTypes = typeSymbol.type.getAllEnclosedTypes().publicMembers;
            var publicEnclosedTypesTable = (publicEnclosedTypes == null) ? new TypeScript.StringHashTable() : publicEnclosedTypes;
            var enclosedTypes = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(publicEnclosedTypesTable, new TypeScript.StringHashTable()));
            var publicEnclosedAmbientTypes = typeSymbol.type.getAllAmbientEnclosedTypes().publicMembers;
            var publicAmbientEnclosedTypesTable = (publicEnclosedAmbientTypes == null) ? new TypeScript.StringHashTable() : publicEnclosedAmbientTypes;
            var ambientEnclosedTypes = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(publicAmbientEnclosedTypesTable, new TypeScript.StringHashTable()));
            var publicMembers = typeSymbol.type.members.publicMembers;
            var publicMembersTable = (publicMembers == null) ? new TypeScript.StringHashTable() : publicMembers;
            var members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(publicMembersTable, new TypeScript.StringHashTable()));
            var publicAmbientMembers = typeSymbol.type.ambientMembers.publicMembers;
            var publicAmbientMembersTable = (publicAmbientMembers == null) ? new TypeScript.StringHashTable() : publicAmbientMembers;
            var ambientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(publicAmbientMembersTable, new TypeScript.StringHashTable()));
            modType = new TypeScript.ModuleType(enclosedTypes, ambientEnclosedTypes);
            if(isEnum) {
                modType.typeFlags |= TypeScript.TypeFlags.IsEnum;
            }
            modType.members = members;
            modType.ambientMembers = ambientMembers;
            modType.setHasImplementation();
            modType.symbol = typeSymbol;
            typeSymbol.addLocation(moduleDecl.minChar);
            typeSymbol.expansions.push(modType);
            typeSymbol.expansionsDeclAST.push(moduleDecl);
        }
        if(context.scopeChain.moduleDecl) {
            context.scopeChain.moduleDecl.recordNonInterface();
        }
        if(isExported) {
            typeSymbol.flags |= TypeScript.SymbolFlags.Exported;
        }
        if((context.scopeChain.moduleDecl) || (context.scopeChain.container == context.checker.gloMod)) {
            typeSymbol.flags |= TypeScript.SymbolFlags.ModuleMember;
        }
        moduleDecl.mod = modType;
        TypeScript.pushTypeCollectionScope(typeSymbol, modType.members, modType.ambientMembers, modType.enclosedTypes, modType.ambientEnclosedTypes, context, null, null, moduleDecl);
        return true;
    }
    TypeScript.preCollectModuleTypes = preCollectModuleTypes;
    function preCollectClassTypes(ast, parent, context) {
        var scopeChain = context.scopeChain;
        var classDecl = ast;
        var classType;
        var instanceType;
        var typeSymbol = null;
        var className = (classDecl.name).text;
        var alreadyInScope = false;
        var isAmbient = TypeScript.hasFlag(classDecl.varFlags, TypeScript.VarFlags.Ambient);
        var isExported = TypeScript.hasFlag(classDecl.varFlags, TypeScript.VarFlags.Exported);
        var isGlobal = context.scopeChain.container == context.checker.gloMod;
        var containerMod = scopeChain.container;
        var foundValSymbol = false;
        typeSymbol = scopeChain.scope.findLocal(className, false, true);
        if(!typeSymbol) {
            var valTypeSymbol = scopeChain.scope.findLocal(className, false, false);
            if(valTypeSymbol && valTypeSymbol.isType() && valTypeSymbol.declAST && valTypeSymbol.declAST.nodeType == TypeScript.NodeType.FuncDecl && (valTypeSymbol.declAST).isSignature()) {
                typeSymbol = valTypeSymbol;
                foundValSymbol = true;
                if(isExported) {
                    typeSymbol.flags |= TypeScript.SymbolFlags.Exported;
                }
                if(isAmbient) {
                    typeSymbol.flags |= TypeScript.SymbolFlags.Ambient;
                }
                context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
            }
        }
        if(typeSymbol && !foundValSymbol && (typeSymbol.declAST != classDecl)) {
            typeSymbol = null;
        }
        if(typeSymbol == null) {
            var valueSymbol = scopeChain.scope.findLocal(className, false, false);
            classType = new TypeScript.Type();
            classType.setHasImplementation();
            instanceType = new TypeScript.Type();
            instanceType.setHasImplementation();
            classType.instanceType = instanceType;
            classType.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            classType.ambientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            addPrototypeField(classType, classDecl, context);
            instanceType.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            instanceType.ambientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            typeSymbol = new TypeScript.TypeSymbol(className, classDecl.name.minChar, className.length, context.checker.locationInfo.unitIndex, classType);
            typeSymbol.declAST = classDecl;
            typeSymbol.instanceType = instanceType;
            classType.symbol = typeSymbol;
            instanceType.symbol = typeSymbol;
            if(context.scopeChain.moduleDecl) {
                context.scopeChain.moduleDecl.recordNonInterface();
                typeSymbol.declModule = context.scopeChain.moduleDecl;
                typeSymbol.flags |= TypeScript.SymbolFlags.ModuleMember;
            }
            if(isExported) {
                typeSymbol.flags |= TypeScript.SymbolFlags.Exported;
            }
            if(isAmbient) {
                typeSymbol.flags |= TypeScript.SymbolFlags.Ambient;
            }
            ast.type = classType;
            context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
            if(valueSymbol == null) {
                context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, false, isAmbient);
            }
        } else {
            classType = typeSymbol.type;
            if(classType.instanceType == null) {
                classType.instanceType = new TypeScript.Type();
                classType.instanceType.setHasImplementation();
                classType.instanceType.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                classType.instanceType.symbol = classType.symbol;
                classType.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                classType.ambientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            }
            instanceType = classType.instanceType;
            ast.type = classType;
        }
        if(!classDecl.constructorDecl) {
            if(typeSymbol && typeSymbol.declAST && typeSymbol.declAST.type && typeSymbol.declAST.type.call && !(typeSymbol.declAST).isOverload) {
                context.checker.errorReporter.duplicateIdentifier(typeSymbol.declAST, typeSymbol.name);
            }
            createNewConstructGroupForType(classDecl.type);
        }
        classType.typeFlags |= TypeScript.TypeFlags.IsClass;
        instanceType.typeFlags |= TypeScript.TypeFlags.IsClass;
        getBases(instanceType, classDecl);
        TypeScript.pushTypeCollectionScope(typeSymbol, instanceType.members, instanceType.ambientMembers, null, null, context, instanceType, classType, null);
        return true;
    }
    TypeScript.preCollectClassTypes = preCollectClassTypes;
    function preCollectInterfaceTypes(ast, parent, context) {
        var scopeChain = context.scopeChain;
        var interfaceDecl = ast;
        var interfaceSymbol = null;
        var interfaceType = null;
        var isExported = TypeScript.hasFlag(interfaceDecl.varFlags, TypeScript.VarFlags.Exported);
        var isGlobal = context.scopeChain.container == context.checker.gloMod;
        var alreadyInScope = true;
        alreadyInScope = false;
        var interfaceName = (interfaceDecl.name).text;
        interfaceSymbol = scopeChain.scope.findLocal(interfaceName, false, true);
        if(interfaceSymbol == null) {
            interfaceType = new TypeScript.Type();
            interfaceSymbol = new TypeScript.TypeSymbol(interfaceName, interfaceDecl.name.minChar, interfaceName.length, context.checker.locationInfo.unitIndex, interfaceType);
            interfaceType.symbol = interfaceSymbol;
            interfaceType.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            interfaceType.ambientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            interfaceSymbol.declAST = interfaceDecl;
            interfaceSymbol.declModule = context.scopeChain.moduleDecl;
        } else {
            alreadyInScope = true;
            interfaceType = interfaceSymbol.type;
        }
        if(!interfaceType) {
            interfaceType = context.checker.anyType;
        }
        ast.type = interfaceType;
        getBases(interfaceType, interfaceDecl);
        if(isExported) {
            interfaceSymbol.flags |= TypeScript.SymbolFlags.Exported;
        }
        if(context.scopeChain.moduleDecl) {
            interfaceSymbol.flags |= TypeScript.SymbolFlags.ModuleMember;
        }
        if(!alreadyInScope) {
            context.scopeChain.scope.enter(context.scopeChain.container, ast, interfaceSymbol, context.checker.errorReporter, isGlobal || isExported, true, false);
        }
        TypeScript.pushTypeCollectionScope(interfaceSymbol, interfaceType.members, interfaceType.ambientMembers, null, null, context, interfaceType, null, null);
        return true;
    }
    TypeScript.preCollectInterfaceTypes = preCollectInterfaceTypes;
    function preCollectArgDeclTypes(ast, parent, context) {
        var scopeChain = context.scopeChain;
        var argDecl = ast;
        if(TypeScript.hasFlag(argDecl.varFlags, TypeScript.VarFlags.Public | TypeScript.VarFlags.Private)) {
            var field = new TypeScript.ValueLocation();
            var isPrivate = TypeScript.hasFlag(argDecl.varFlags, TypeScript.VarFlags.Private);
            var fieldSymbol = new TypeScript.FieldSymbol(argDecl.id.text, argDecl.id.minChar, context.checker.locationInfo.unitIndex, !TypeScript.hasFlag(argDecl.varFlags, TypeScript.VarFlags.Readonly), field);
            fieldSymbol.transferVarFlags(argDecl.varFlags);
            field.symbol = fieldSymbol;
            fieldSymbol.declAST = ast;
            argDecl.parameterPropertySym = fieldSymbol;
            context.scopeChain.scope.enter(context.scopeChain.container, ast, fieldSymbol, context.checker.errorReporter, !isPrivate, false, false);
            field.typeLink = TypeScript.getTypeLink(argDecl.typeExpr, context.checker, argDecl.init == null);
            argDecl.sym = fieldSymbol;
        }
        return false;
    }
    TypeScript.preCollectArgDeclTypes = preCollectArgDeclTypes;
    function preCollectVarDeclTypes(ast, parent, context) {
        var scopeChain = context.scopeChain;
        var varDecl = ast;
        var isAmbient = TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Ambient);
        var isExported = TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Exported);
        var isGlobal = context.scopeChain.container == context.checker.gloMod;
        var isProperty = TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Property);
        var isStatic = TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Static);
        var isPrivate = TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Private);
        var isOptional = TypeScript.hasFlag(varDecl.id.flags, TypeScript.ASTFlags.OptionalName);
        if(context.scopeChain.moduleDecl) {
            context.scopeChain.moduleDecl.recordNonInterface();
        }
        if(isProperty || isExported || (context.scopeChain.container == context.checker.gloMod) || context.scopeChain.moduleDecl) {
            if(isAmbient) {
                var existingSym = scopeChain.scope.findLocal(varDecl.id.text, false, false);
                if(existingSym) {
                    varDecl.sym = existingSym;
                    return false;
                }
            }
            if(varDecl.id == null) {
                context.checker.errorReporter.simpleError(varDecl, "Expected variable identifier at this location");
                return false;
            }
            var field = new TypeScript.ValueLocation();
            var fieldSymbol = new TypeScript.FieldSymbol(varDecl.id.text, varDecl.id.minChar, context.checker.locationInfo.unitIndex, (varDecl.varFlags & TypeScript.VarFlags.Readonly) == TypeScript.VarFlags.None, field);
            fieldSymbol.transferVarFlags(varDecl.varFlags);
            if(isOptional) {
                fieldSymbol.flags |= TypeScript.SymbolFlags.Optional;
            }
            field.symbol = fieldSymbol;
            fieldSymbol.declAST = ast;
            if((context.scopeChain.moduleDecl) || (context.scopeChain.container == context.checker.gloMod)) {
                fieldSymbol.flags |= TypeScript.SymbolFlags.ModuleMember;
                fieldSymbol.declModule = context.scopeChain.moduleDecl;
            }
            if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Property) && isStatic && context.scopeChain.classType) {
                if(!context.scopeChain.classType.members.publicMembers.add(varDecl.id.text, fieldSymbol)) {
                    context.checker.errorReporter.duplicateIdentifier(ast, fieldSymbol.name);
                }
                fieldSymbol.container = context.scopeChain.classType.symbol;
            } else {
                context.scopeChain.scope.enter(context.scopeChain.container, ast, fieldSymbol, context.checker.errorReporter, !isPrivate && (isProperty || isExported || isGlobal || isStatic), false, isAmbient);
            }
            if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Exported)) {
                fieldSymbol.flags |= TypeScript.SymbolFlags.Exported;
            }
            field.typeLink = TypeScript.getTypeLink(varDecl.typeExpr, context.checker, varDecl.init == null);
            varDecl.sym = fieldSymbol;
        }
        return false;
    }
    TypeScript.preCollectVarDeclTypes = preCollectVarDeclTypes;
    function preCollectFuncDeclTypes(ast, parent, context) {
        var scopeChain = context.scopeChain;
        if(context.scopeChain.moduleDecl) {
            context.scopeChain.moduleDecl.recordNonInterface();
        }
        var funcDecl = ast;
        var fgSym = null;
        var nameText = funcDecl.getNameText();
        var isExported = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Exported | TypeScript.FncFlags.ClassPropertyMethodExported);
        var isStatic = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Static);
        var isPrivate = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Private);
        var isConstructor = funcDecl.isConstructMember() || funcDecl.isConstructor;
        var containerSym = (((funcDecl.isMethod() && isStatic) || funcDecl.isAccessor()) && context.scopeChain.classType ? context.scopeChain.classType.symbol : context.scopeChain.container);
        var containerScope = context.scopeChain.scope;
        var isGlobal = containerSym == context.checker.gloMod;
        var isOptional = funcDecl.name && TypeScript.hasFlag(funcDecl.name.flags, TypeScript.ASTFlags.OptionalName);
        var go = false;
        var foundSymbol = false;
        if(isConstructor && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod)) {
            containerSym = containerSym.container;
            containerScope = scopeChain.previous.scope;
        }
        funcDecl.unitIndex = context.checker.locationInfo.unitIndex;
        if(!funcDecl.isConstructor && containerSym && containerSym.declAST && containerSym.declAST.nodeType == TypeScript.NodeType.FuncDecl && (containerSym.declAST).isConstructor && !funcDecl.isMethod()) {
            return go;
        }
        if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Signature)) {
            var instType = context.scopeChain.thisType;
            if(nameText && nameText != "__missing") {
                if(isStatic) {
                    fgSym = containerSym.type.members.allMembers.lookup(nameText);
                } else {
                    fgSym = containerScope.findLocal(nameText, false, false);
                    if(fgSym == null) {
                        fgSym = containerScope.findLocal(nameText, false, true);
                    }
                }
                if(fgSym) {
                    foundSymbol = true;
                    if(!funcDecl.isSignature() && (TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Ambient) != TypeScript.hasFlag(fgSym.flags, TypeScript.SymbolFlags.Ambient))) {
                        fgSym = null;
                    }
                }
            }
            if(fgSym == null) {
                if(!(funcDecl.isSpecialFn())) {
                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, null, !foundSymbol).declAST.type.symbol;
                } else {
                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, containerSym, false).declAST.type.symbol;
                }
                if(fgSym.declAST == null || !funcDecl.isSpecialFn()) {
                    fgSym.declAST = ast;
                }
            } else {
                if((fgSym.kind() == TypeScript.SymbolKind.Type)) {
                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, false).declAST.type.symbol;
                } else {
                    context.checker.errorReporter.simpleError(funcDecl, "Function or method '" + funcDecl.name.actualText + "' already declared as a property");
                }
            }
            if(funcDecl.isSpecialFn() && !isStatic) {
                funcDecl.type = instType ? instType : fgSym.type;
            } else {
                funcDecl.type = fgSym.type;
            }
        } else {
            if(nameText) {
                if(isStatic) {
                    fgSym = containerSym.type.members.allMembers.lookup(nameText);
                } else {
                    if(funcDecl.isConstructor && context.scopeChain.previous) {
                        fgSym = context.scopeChain.previous.scope.findLocal(nameText, false, false);
                    }
                    if(fgSym == null) {
                        fgSym = containerScope.findLocal(nameText, false, false);
                    }
                }
                if(fgSym) {
                    foundSymbol = true;
                    if(!isConstructor && fgSym.declAST.nodeType == TypeScript.NodeType.FuncDecl && !(fgSym.declAST).isAccessor() && !(fgSym.declAST).isSignature()) {
                        fgSym = null;
                        foundSymbol = false;
                    }
                }
            }
            if(fgSym && !fgSym.isAccessor() && fgSym.type && fgSym.type.construct && fgSym.type.construct.signatures != [] && (fgSym.type.construct.signatures[0].declAST == null || !TypeScript.hasFlag(fgSym.type.construct.signatures[0].declAST.fncFlags, TypeScript.FncFlags.Ambient)) && !funcDecl.isConstructor) {
                context.checker.errorReporter.simpleError(funcDecl, "Functions may not have class overloads");
            }
            if(fgSym && !(fgSym.kind() == TypeScript.SymbolKind.Type) && funcDecl.isMethod() && !funcDecl.isAccessor() && !funcDecl.isConstructor) {
                context.checker.errorReporter.simpleError(funcDecl, "Function or method '" + funcDecl.name.actualText + "' already declared as a property");
                fgSym.type = context.checker.anyType;
            }
            var sig = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, !foundSymbol);
            if(((!fgSym || fgSym.declAST.nodeType != TypeScript.NodeType.FuncDecl) && funcDecl.isAccessor()) || (fgSym && fgSym.isAccessor())) {
                funcDecl.accessorSymbol = context.checker.createAccessorSymbol(funcDecl, fgSym, containerSym.type, (funcDecl.isMethod() && isStatic), true, containerScope, containerSym);
            }
            funcDecl.type.symbol.declAST = ast;
            if(funcDecl.isConstructor) {
                go = true;
            }
            ; ;
        }
        if(isExported) {
            if(funcDecl.type.call) {
                funcDecl.type.symbol.flags |= TypeScript.SymbolFlags.Exported;
            }
            if(fgSym && !fgSym.isAccessor() && fgSym.kind() == TypeScript.SymbolKind.Type && fgSym.type.call) {
                fgSym.flags |= TypeScript.SymbolFlags.Exported;
            }
        }
        if(context.scopeChain.moduleDecl && !funcDecl.isSpecialFn()) {
            funcDecl.type.symbol.flags |= TypeScript.SymbolFlags.ModuleMember;
            funcDecl.type.symbol.declModule = context.scopeChain.moduleDecl;
        }
        if(fgSym && isOptional) {
            fgSym.flags |= TypeScript.SymbolFlags.Optional;
        }
        return go;
    }
    TypeScript.preCollectFuncDeclTypes = preCollectFuncDeclTypes;
    function preCollectTypes(ast, parent, walker) {
        var context = walker.state;
        var go = false;
        var scopeChain = context.scopeChain;
        if(ast.nodeType == TypeScript.NodeType.Script) {
            var script = ast;
            context.script = script;
            go = true;
        } else {
            if(ast.nodeType == TypeScript.NodeType.List) {
                go = true;
            } else {
                if(ast.nodeType == TypeScript.NodeType.ImportDeclaration) {
                    go = preCollectImportTypes(ast, parent, context);
                } else {
                    if(ast.nodeType == TypeScript.NodeType.With) {
                        go = false;
                    } else {
                        if(ast.nodeType == TypeScript.NodeType.ModuleDeclaration) {
                            go = preCollectModuleTypes(ast, parent, context);
                        } else {
                            if(ast.nodeType == TypeScript.NodeType.ClassDeclaration) {
                                go = preCollectClassTypes(ast, parent, context);
                            } else {
                                if(ast.nodeType == TypeScript.NodeType.Block) {
                                    go = true;
                                } else {
                                    if(ast.nodeType == TypeScript.NodeType.InterfaceDeclaration) {
                                        go = preCollectInterfaceTypes(ast, parent, context);
                                    } else {
                                        if(ast.nodeType == TypeScript.NodeType.ArgDecl) {
                                            go = preCollectArgDeclTypes(ast, parent, context);
                                        } else {
                                            if(ast.nodeType == TypeScript.NodeType.VarDecl) {
                                                go = preCollectVarDeclTypes(ast, parent, context);
                                            } else {
                                                if(ast.nodeType == TypeScript.NodeType.FuncDecl) {
                                                    go = preCollectFuncDeclTypes(ast, parent, context);
                                                } else {
                                                    if(ast.isStatementOrExpression() && context.scopeChain.moduleDecl) {
                                                        context.scopeChain.moduleDecl.recordNonInterface();
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        walker.options.goChildren = go;
        return ast;
    }
    TypeScript.preCollectTypes = preCollectTypes;
    function postCollectTypes(ast, parent, walker) {
        var context = walker.state;
        if(ast.nodeType == TypeScript.NodeType.ModuleDeclaration) {
            TypeScript.popTypeCollectionScope(context);
        } else {
            if(ast.nodeType == TypeScript.NodeType.ClassDeclaration) {
                TypeScript.popTypeCollectionScope(context);
            } else {
                if(ast.nodeType == TypeScript.NodeType.InterfaceDeclaration) {
                    TypeScript.popTypeCollectionScope(context);
                }
            }
        }
        return ast;
    }
    TypeScript.postCollectTypes = postCollectTypes;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var ScopeChain = (function () {
        function ScopeChain(container, previous, scope) {
            this.container = container;
            this.previous = previous;
            this.scope = scope;
        }
        return ScopeChain;
    })();
    TypeScript.ScopeChain = ScopeChain;    
    var BBUseDefInfo = (function () {
        function BBUseDefInfo(bb) {
            this.bb = bb;
            this.defsBySymbol = new Array();
            this.useIndexBySymbol = new Array();
        }
        BBUseDefInfo.prototype.updateTop = function () {
            var temp = new BitVector(this.top.bitCount);
            for(var i = 0, succLen = this.bb.successors.length; i < succLen; i++) {
                var succ = this.bb.successors[i];
                if(succ.useDef) {
                    temp.union(succ.useDef.top);
                }
            }
            temp.difference(this.kill);
            temp.union(this.gen);
            var changed = temp.notEq(this.top);
            this.top = temp;
            return changed;
        };
        BBUseDefInfo.prototype.initialize = function (useDefContext) {
            var _this = this;
            var defSym = function (sym, context) {
                if(context.isLocalSym(sym)) {
                    var index = context.getSymbolIndex(sym);
                    _this.useIndexBySymbol[index] = new Array();
                    _this.defsBySymbol[index] = true;
                }
            };
            var useSym = function (sym, context, ast) {
                if(context.isLocalSym(sym)) {
                    var symIndex = context.getSymbolIndex(sym);
                    if(_this.useIndexBySymbol[symIndex] == undefined) {
                        _this.useIndexBySymbol[symIndex] = new Array();
                    }
                    var symUses = _this.useIndexBySymbol[symIndex];
                    var astIndex = context.getUseIndex(ast);
                    context.addUse(symIndex, astIndex);
                    symUses.push(astIndex);
                }
            };
            function initUseDefPre(cur, parent, walker) {
                var context = walker.state;
                if(cur == null) {
                    cur = null;
                }
                if(cur.nodeType == TypeScript.NodeType.VarDecl) {
                    var varDecl = cur;
                    if(varDecl.init || TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.AutoInit)) {
                        defSym(varDecl.sym, context);
                    }
                } else {
                    if(cur.nodeType == TypeScript.NodeType.Name) {
                        if(parent) {
                            if(parent.nodeType == TypeScript.NodeType.Asg) {
                                var asg = parent;
                                if(asg.operand1 == cur) {
                                    return cur;
                                }
                            } else {
                                if(parent.nodeType == TypeScript.NodeType.VarDecl) {
                                    var parentDecl = parent;
                                    if(parentDecl.id == cur) {
                                        return cur;
                                    }
                                }
                            }
                        }
                        var id = cur;
                        useSym(id.sym, context, cur);
                    } else {
                        if((cur.nodeType >= TypeScript.NodeType.Asg) && (cur.nodeType <= TypeScript.NodeType.LastAsg)) {
                            var asg = cur;
                            if(asg.operand1 && (asg.operand1.nodeType == TypeScript.NodeType.Name)) {
                                var id = asg.operand1;
                                defSym(id.sym, context);
                            }
                        } else {
                            if(cur.nodeType == TypeScript.NodeType.FuncDecl) {
                                walker.options.goChildren = false;
                            }
                        }
                    }
                }
                return cur;
            }
            var options = new TypeScript.AstWalkOptions();
            options.reverseSiblings = true;
            TypeScript.getAstWalkerFactory().walk(this.bb.content, initUseDefPre, null, options, useDefContext);
        };
        BBUseDefInfo.prototype.initializeGen = function (useDefContext) {
            var symbolLen = this.useIndexBySymbol.length;
            var bitCount = useDefContext.uses.length;
            this.gen = new BitVector(bitCount);
            for(var s = 0; s < symbolLen; s++) {
                var symUses = this.useIndexBySymbol[s];
                if((symUses != undefined) && (symUses.length > 0)) {
                    for(var u = 0, uLen = symUses.length; u < uLen; u++) {
                        this.gen.set(symUses[u], true);
                    }
                }
            }
            this.top = this.gen;
        };
        BBUseDefInfo.prototype.initializeKill = function (useDefContext) {
            this.kill = new BitVector(this.gen.bitCount);
            for(var s = 0, symbolLen = this.defsBySymbol.length; s < symbolLen; s++) {
                if(this.defsBySymbol[s]) {
                    var globalSymUses = useDefContext.useIndexBySymbol[s];
                    if(globalSymUses) {
                        for(var u = 0, useLen = globalSymUses.length; u < useLen; u++) {
                            this.kill.set(globalSymUses[u], true);
                        }
                    }
                }
            }
        };
        return BBUseDefInfo;
    })();
    TypeScript.BBUseDefInfo = BBUseDefInfo;    
    var UseDefContext = (function () {
        function UseDefContext() {
            this.useIndexBySymbol = new Array();
            this.uses = new Array();
            this.symbols = new Array();
            this.symbolMap = new TypeScript.StringHashTable();
            this.symbolCount = 0;
        }
        UseDefContext.prototype.getSymbolIndex = function (sym) {
            var name = sym.name;
            var index = (this.symbolMap.lookup(name));
            if(index == null) {
                index = this.symbolCount++;
                this.symbols[index] = sym;
                this.symbolMap.add(name, index);
            }
            return index;
        };
        UseDefContext.prototype.addUse = function (symIndex, astIndex) {
            var useBySym = this.useIndexBySymbol[symIndex];
            if(useBySym == undefined) {
                useBySym = new Array();
                this.useIndexBySymbol[symIndex] = useBySym;
            }
            useBySym[useBySym.length] = astIndex;
        };
        UseDefContext.prototype.getUseIndex = function (ast) {
            this.uses[this.uses.length] = ast;
            return this.uses.length - 1;
        };
        UseDefContext.prototype.isLocalSym = function (sym) {
            return (sym && (sym.container == this.func) && (sym.kind() == TypeScript.SymbolKind.Variable));
        };
        UseDefContext.prototype.killSymbol = function (sym, bbUses) {
            var index = this.symbolMap.lookup(sym.name);
            var usesOfSym = this.useIndexBySymbol[index];
            for(var k = 0, len = usesOfSym.length; k < len; k++) {
                bbUses.set(usesOfSym[k], true);
            }
        };
        return UseDefContext;
    })();
    TypeScript.UseDefContext = UseDefContext;    
    var BitVector = (function () {
        function BitVector(bitCount) {
            this.bitCount = bitCount;
            this.firstBits = 0;
            this.restOfBits = null;
            if(this.bitCount > BitVector.packBits) {
                this.restOfBits = new Array();
                var len = Math.floor(this.bitCount / BitVector.packBits);
                for(var i = 0; i < len; i++) {
                    this.restOfBits[i] = 0;
                }
            }
        }
        BitVector.packBits = 30;
        BitVector.prototype.set = function (bitIndex, value) {
            if(bitIndex < BitVector.packBits) {
                if(value) {
                    this.firstBits |= (1 << bitIndex);
                } else {
                    this.firstBits &= (~(1 << bitIndex));
                }
            } else {
                var offset = Math.floor(bitIndex / BitVector.packBits) - 1;
                var localIndex = bitIndex % BitVector.packBits;
                if(value) {
                    this.restOfBits[offset] |= (1 << localIndex);
                } else {
                    this.restOfBits[offset] &= (~(1 << localIndex));
                }
            }
        };
        BitVector.prototype.map = function (fn) {
            var k;
            for(k = 0; k < BitVector.packBits; k++) {
                if(k == this.bitCount) {
                    return;
                }
                if(((1 << k) & this.firstBits) != 0) {
                    fn(k);
                }
            }
            if(this.restOfBits) {
                var len;
                var cumu = BitVector.packBits;
                for(k = 0 , len = this.restOfBits.length; k < len; k++) {
                    var myBits = this.restOfBits[k];
                    for(var j = 0; j < BitVector.packBits; j++) {
                        if(((1 << j) & myBits) != 0) {
                            fn(cumu);
                        }
                        cumu++;
                        if(cumu == this.bitCount) {
                            return;
                        }
                    }
                }
            }
        };
        BitVector.prototype.union = function (b) {
            this.firstBits |= b.firstBits;
            if(this.restOfBits) {
                for(var k = 0, len = this.restOfBits.length; k < len; k++) {
                    var myBits = this.restOfBits[k];
                    var bBits = b.restOfBits[k];
                    this.restOfBits[k] = myBits | bBits;
                }
            }
        };
        BitVector.prototype.intersection = function (b) {
            this.firstBits &= b.firstBits;
            if(this.restOfBits) {
                for(var k = 0, len = this.restOfBits.length; k < len; k++) {
                    var myBits = this.restOfBits[k];
                    var bBits = b.restOfBits[k];
                    this.restOfBits[k] = myBits & bBits;
                }
            }
        };
        BitVector.prototype.notEq = function (b) {
            if(this.firstBits != b.firstBits) {
                return true;
            }
            if(this.restOfBits) {
                for(var k = 0, len = this.restOfBits.length; k < len; k++) {
                    var myBits = this.restOfBits[k];
                    var bBits = b.restOfBits[k];
                    if(myBits != bBits) {
                        return true;
                    }
                }
            }
            return false;
        };
        BitVector.prototype.difference = function (b) {
            var oldFirstBits = this.firstBits;
            this.firstBits &= (~b.firstBits);
            if(this.restOfBits) {
                for(var k = 0, len = this.restOfBits.length; k < len; k++) {
                    var myBits = this.restOfBits[k];
                    var bBits = b.restOfBits[k];
                    this.restOfBits[k] &= (~bBits);
                }
            }
        };
        return BitVector;
    })();
    TypeScript.BitVector = BitVector;    
    var BasicBlock = (function () {
        function BasicBlock() {
            this.predecessors = new Array();
            this.index = -1;
            this.markValue = 0;
            this.successors = new Array();
            this.useDef = null;
            this.content = new TypeScript.ASTList();
        }
        BasicBlock.prototype.marked = function (markBase) {
            return this.markValue > markBase;
        };
        BasicBlock.prototype.mark = function () {
            this.markValue++;
        };
        BasicBlock.prototype.addSuccessor = function (successor) {
            this.successors[this.successors.length] = successor;
            successor.predecessors[successor.predecessors.length] = this;
        };
        return BasicBlock;
    })();
    TypeScript.BasicBlock = BasicBlock;    
    var ControlFlowContext = (function () {
        function ControlFlowContext(current, exit) {
            this.current = current;
            this.exit = exit;
            this.entry = null;
            this.unreachable = null;
            this.noContinuation = false;
            this.statementStack = new Array();
            this.currentSwitch = new Array();
            this.markBase = 0;
            this.linearBBs = new Array();
            this.entry = this.current;
        }
        ControlFlowContext.prototype.walk = function (ast, parent) {
            return this.walker.walk(ast, parent);
        };
        ControlFlowContext.prototype.pushSwitch = function (bb) {
            this.currentSwitch.push(bb);
        };
        ControlFlowContext.prototype.popSwitch = function () {
            return this.currentSwitch.pop();
        };
        ControlFlowContext.prototype.reportUnreachable = function (er) {
            if(this.unreachable && (this.unreachable.length > 0)) {
                var len = this.unreachable.length;
                for(var i = 0; i < len; i++) {
                    var unreachableAST = this.unreachable[i];
                    if(unreachableAST.nodeType != TypeScript.NodeType.EndCode) {
                        er.simpleError(unreachableAST, "unreachable code");
                    }
                }
            }
        };
        ControlFlowContext.prototype.printAST = function (ast, outfile) {
            var printContext = new TypeScript.PrintContext(outfile, null);
            printContext.increaseIndent();
            TypeScript.getAstWalkerFactory().walk(ast, TypeScript.prePrintAST, TypeScript.postPrintAST, null, printContext);
            printContext.decreaseIndent();
        };
        ControlFlowContext.prototype.printBlockContent = function (bb, outfile) {
            var content = bb.content;
            for(var i = 0, len = content.members.length; i < len; i++) {
                var ast = content.members[i];
                this.printAST(ast, outfile);
            }
        };
        ControlFlowContext.prototype.bfs = function (nodeFunc, edgeFunc, preEdges, postEdges) {
            var markValue = this.markBase++;
            var q = new Array();
            q[q.length] = this.entry;
            while(q.length > 0) {
                var bb = q.pop();
                if(!(bb.marked(markValue))) {
                    bb.mark();
                    if(nodeFunc) {
                        nodeFunc(bb);
                    }
                    var succLen = bb.successors.length;
                    if(succLen > 0) {
                        if(preEdges) {
                            preEdges();
                        }
                        for(var j = succLen - 1; j >= 0; j--) {
                            var successor = bb.successors[j];
                            if(!(successor.marked(this.markBase))) {
                                if(edgeFunc) {
                                    edgeFunc(bb, successor);
                                }
                                q[q.length] = successor;
                            }
                        }
                        if(postEdges) {
                            postEdges();
                        }
                    }
                }
            }
        };
        ControlFlowContext.prototype.useDef = function (er, funcSym) {
            var _this = this;
            var useDefContext = new UseDefContext();
            useDefContext.func = funcSym;
            var useDefInit = function (bb) {
                bb.useDef = new BBUseDefInfo(bb);
                bb.useDef.initialize(useDefContext);
                _this.linearBBs[_this.linearBBs.length] = bb;
            };
            this.bfs(useDefInit, null, null, null);
            var i, bbLen;
            for(i = 0 , bbLen = this.linearBBs.length; i < bbLen; i++) {
                this.linearBBs[i].useDef.initializeGen(useDefContext);
                this.linearBBs[i].useDef.initializeKill(useDefContext);
            }
            var changed = true;
            while(changed) {
                changed = false;
                for(i = 0; i < bbLen; i++) {
                    changed = this.linearBBs[i].useDef.updateTop() || changed;
                }
            }
            var top = this.entry.useDef.top;
            top.map(function (index) {
                var ast = useDefContext.uses[index];
                er.simpleError(ast, "use of variable '" + ast.actualText + "' that is not definitely assigned");
            });
        };
        ControlFlowContext.prototype.print = function (outfile) {
            var _this = this;
            var index = 0;
            var node = function (bb) {
                if(bb.index < 0) {
                    bb.index = index++;
                }
                if(bb == _this.exit) {
                    outfile.WriteLine("Exit block with index " + bb.index);
                } else {
                    outfile.WriteLine("Basic block with index " + bb.index);
                    _this.printBlockContent(bb, outfile);
                }
            };
            function preEdges() {
                outfile.Write("  Branches to ");
            }
            function postEdges() {
                outfile.WriteLine("");
            }
            function edge(node1, node2) {
                if(node2.index < 0) {
                    node2.index = index++;
                }
                outfile.Write(node2.index + " ");
            }
            this.bfs(node, edge, preEdges, postEdges);
            if(this.unreachable != null) {
                for(var i = 0, len = this.unreachable.length; i < len; i++) {
                    outfile.WriteLine("Unreachable basic block ...");
                    this.printAST(this.unreachable[i], outfile);
                }
            }
        };
        ControlFlowContext.prototype.pushStatement = function (stmt, continueBB, breakBB) {
            this.statementStack.push({
                stmt: stmt,
                continueBB: continueBB,
                breakBB: breakBB
            });
        };
        ControlFlowContext.prototype.popStatement = function () {
            return this.statementStack.pop();
        };
        ControlFlowContext.prototype.returnStmt = function () {
            this.current.addSuccessor(this.exit);
            this.setUnreachable();
        };
        ControlFlowContext.prototype.setUnreachable = function () {
            this.current = null;
            this.noContinuation = true;
        };
        ControlFlowContext.prototype.addUnreachable = function (ast) {
            if(this.unreachable === null) {
                this.unreachable = new Array();
            }
            this.unreachable[this.unreachable.length] = ast;
        };
        ControlFlowContext.prototype.unconditionalBranch = function (target, isContinue) {
            var targetBB = null;
            for(var i = 0, len = this.statementStack.length; i < len; i++) {
                var targetInfo = this.statementStack[i];
                if(targetInfo.stmt == target) {
                    if(isContinue) {
                        targetBB = targetInfo.continueBB;
                    } else {
                        targetBB = targetInfo.breakBB;
                    }
                    break;
                }
            }
            if(targetBB) {
                this.current.addSuccessor(targetBB);
            }
            this.setUnreachable();
        };
        ControlFlowContext.prototype.addContent = function (ast) {
            if(this.current) {
                this.current.content.append(ast);
            }
        };
        return ControlFlowContext;
    })();
    TypeScript.ControlFlowContext = ControlFlowContext;    
    var ResolutionDataCache = (function () {
        function ResolutionDataCache() {
            this.cacheSize = 16;
            this.rdCache = [];
            this.nextUp = 0;
            for(var i = 0; i < this.cacheSize; i++) {
                this.rdCache[i] = {
                    actuals: new Array(),
                    exactCandidates: new Array(),
                    conversionCandidates: new Array(),
                    id: i
                };
            }
        }
        ResolutionDataCache.prototype.getResolutionData = function () {
            var rd = null;
            if(this.nextUp < this.cacheSize) {
                rd = this.rdCache[this.nextUp];
            }
            if(rd == null) {
                this.cacheSize++;
                rd = {
                    actuals: new Array(),
                    exactCandidates: new Array(),
                    conversionCandidates: new Array(),
                    id: this.cacheSize
                };
                this.rdCache[this.cacheSize] = rd;
            }
            this.nextUp++;
            return rd;
        };
        ResolutionDataCache.prototype.returnResolutionData = function (rd) {
            rd.actuals.length = 0;
            rd.exactCandidates.length = 0;
            rd.conversionCandidates.length = 0;
            this.nextUp = rd.id;
        };
        return ResolutionDataCache;
    })();
    TypeScript.ResolutionDataCache = ResolutionDataCache;    
    var TypeFlow = (function () {
        function TypeFlow(logger, initScope, parser, checker) {
            this.logger = logger;
            this.initScope = initScope;
            this.parser = parser;
            this.checker = checker;
            this.thisFnc = null;
            this.thisClassNode = null;
            this.enclosingFncIsMethod = false;
            this.arrayInterfaceType = null;
            this.stringInterfaceType = null;
            this.objectInterfaceType = null;
            this.functionInterfaceType = null;
            this.numberInterfaceType = null;
            this.booleanInterfaceType = null;
            this.iargumentsInterfaceType = null;
            this.currentScript = null;
            this.inImportTypeCheck = false;
            this.inTypeRefTypeCheck = false;
            this.inArrayElementTypeCheck = false;
            this.resolutionDataCache = new ResolutionDataCache();
            this.nestingLevel = 0;
            this.inSuperCall = false;
            this.checker.typeFlow = this;
            this.scope = this.initScope;
            this.globalScope = this.initScope;
            this.doubleType = this.checker.numberType;
            this.booleanType = this.checker.booleanType;
            this.stringType = this.checker.stringType;
            this.anyType = this.checker.anyType;
            this.regexType = this.anyType;
            this.nullType = this.checker.nullType;
            this.voidType = this.checker.voidType;
            this.arrayAnyType = this.checker.makeArrayType(this.anyType);
        }
        TypeFlow.prototype.initLibs = function () {
            var arraySym = this.globalScope.find("Array", false, true);
            if(arraySym && (arraySym.kind() == TypeScript.SymbolKind.Type)) {
                this.arrayInterfaceType = (arraySym).type;
            }
            var stringSym = this.globalScope.find("String", false, true);
            if(stringSym && (stringSym.kind() == TypeScript.SymbolKind.Type)) {
                this.stringInterfaceType = (stringSym).type;
            }
            var objectSym = this.globalScope.find("Object", false, true);
            if(objectSym && (objectSym.kind() == TypeScript.SymbolKind.Type)) {
                this.objectInterfaceType = (objectSym).type;
            }
            var fnSym = this.globalScope.find("Function", false, true);
            if(fnSym && (fnSym.kind() == TypeScript.SymbolKind.Type)) {
                this.functionInterfaceType = (fnSym).type;
            }
            var numberSym = this.globalScope.find("Number", false, true);
            if(numberSym && (numberSym.kind() == TypeScript.SymbolKind.Type)) {
                this.numberInterfaceType = (numberSym).type;
            }
            var booleanSym = this.globalScope.find("Boolean", false, true);
            if(booleanSym && (booleanSym.kind() == TypeScript.SymbolKind.Type)) {
                this.booleanInterfaceType = (booleanSym).type;
            }
            var regexSym = this.globalScope.find("RegExp", false, true);
            if(regexSym && (regexSym.kind() == TypeScript.SymbolKind.Type)) {
                this.regexType = (regexSym).type;
            }
        };
        TypeFlow.prototype.cast = function (ast, type) {
            return this.castWithCoercion(ast, type, true, false);
        };
        TypeFlow.prototype.castWithCoercion = function (ast, type, applyCoercion, typeAssertion) {
            var comparisonInfo = new TypeScript.TypeComparisonInfo();
            if(this.checker.sourceIsAssignableToTarget(ast.type, type, comparisonInfo) || (typeAssertion && this.checker.sourceIsAssignableToTarget(type, ast.type, comparisonInfo))) {
                if(applyCoercion) {
                    if(type == null) {
                        ast.type = this.anyType;
                    } else {
                        if(type.isClass()) {
                            ast.type = type.instanceType;
                        } else {
                            ast.type = type;
                        }
                    }
                }
                return ast;
            } else {
                this.checker.errorReporter.incompatibleTypes(ast, ast.type, type, null, this.scope, comparisonInfo);
                return ast;
            }
        };
        TypeFlow.prototype.inScopeTypeCheck = function (ast, enclosingScope) {
            var prevScope = this.scope;
            this.scope = enclosingScope;
            var svThisFnc = this.thisFnc;
            var svThisType = this.thisType;
            var svThisClassNode = this.thisClassNode;
            var svCurrentModDecl = this.checker.currentModDecl;
            var prevMethodStatus = this.enclosingFncIsMethod;
            var container = this.scope.container;
            var fnc = null;
            while(container) {
                if(container.kind() == TypeScript.SymbolKind.Type) {
                    var typeSym = container;
                    var type = typeSym.type;
                    if(type.call) {
                        if(fnc == null) {
                            this.enclosingFncIsMethod = typeSym.isMethod;
                            fnc = container.declAST;
                        }
                    }
                    if(type.isClass()) {
                        this.thisType = type.instanceType;
                        if(typeSym.declAST && (typeSym.declAST.nodeType == TypeScript.NodeType.ClassDeclaration)) {
                            this.thisClassNode = typeSym.declAST;
                        }
                        break;
                    }
                    if(type.isModuleType()) {
                        this.checker.currentModDecl = typeSym.declAST;
                        break;
                    }
                }
                container = container.container;
            }
            this.thisFnc = fnc;
            var updated = this.typeCheck(ast);
            this.thisFnc = svThisFnc;
            this.thisType = svThisType;
            this.thisClassNode = svThisClassNode;
            this.checker.currentModDecl = svCurrentModDecl;
            this.enclosingFncIsMethod = prevMethodStatus;
            this.scope = prevScope;
            return updated;
        };
        TypeFlow.prototype.typeCheck = function (ast) {
            if(ast) {
                return ast.typeCheck(this);
            } else {
                return null;
            }
        };
        TypeFlow.prototype.inScopeTypeCheckDecl = function (ast) {
            if(ast.nodeType == TypeScript.NodeType.VarDecl || ast.nodeType == TypeScript.NodeType.ArgDecl) {
                this.inScopeTypeCheckBoundDecl(ast);
            } else {
                if(ast.nodeType == TypeScript.NodeType.FuncDecl) {
                    var funcDecl = ast;
                    if(funcDecl.isAccessor()) {
                        this.typeCheckFunction(funcDecl);
                    }
                }
            }
        };
        TypeFlow.prototype.inScopeTypeCheckBoundDecl = function (varDecl) {
            var sym = varDecl.sym;
            var svThisFnc = this.thisFnc;
            var svThisType = this.thisType;
            var prevMethodStatus = this.enclosingFncIsMethod;
            var prevLocationInfo = this.checker.locationInfo;
            if(sym && sym.container) {
                var instanceScope = TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.ClassConstructorProperty) ? sym.container.getType().constructorScope : sym.container.instanceScope();
                if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Property) && sym.container.declAST.nodeType == TypeScript.NodeType.FuncDecl) {
                    this.thisFnc = sym.container.declAST;
                }
                if(instanceScope) {
                    var prevScope = this.scope;
                    this.scope = instanceScope;
                    var container = sym.container;
                    if(this.checker.units && (sym.unitIndex >= 0) && (sym.unitIndex < this.checker.units.length)) {
                        this.checker.locationInfo = this.checker.units[sym.unitIndex];
                    } else {
                        this.checker.locationInfo = TypeScript.unknownLocationInfo;
                    }
                    while(container) {
                        if(container.kind() == TypeScript.SymbolKind.Type) {
                            var typeSym = container;
                            var type = typeSym.type;
                            if(type.call) {
                                this.enclosingFncIsMethod = typeSym.isMethod;
                            }
                            if(type.isClass()) {
                                this.thisType = type.instanceType;
                                break;
                            }
                        }
                        container = container.container;
                    }
                    this.typeCheckBoundDecl(varDecl);
                    this.scope = prevScope;
                }
            }
            this.thisFnc = svThisFnc;
            this.thisType = svThisType;
            this.checker.locationInfo = prevLocationInfo;
            this.enclosingFncIsMethod = prevMethodStatus;
        };
        TypeFlow.prototype.resolveBoundDecl = function (varDecl) {
            if(varDecl.typeExpr) {
                if(varDecl.typeExpr.type == null || (varDecl.typeExpr.type && varDecl.typeExpr.type == this.anyType && this.scope) || varDecl.typeExpr.type.symbol == null || !this.checker.typeStatusIsFinished(varDecl.typeExpr.type.symbol.typeCheckStatus)) {
                    this.typeCheck(varDecl.typeExpr);
                }
                varDecl.type = varDecl.typeExpr.type;
                if(varDecl.sym) {
                    varDecl.sym.setType(varDecl.type);
                }
            } else {
                if(varDecl.init == null) {
                    if(this.checker.styleSettings.implicitAny) {
                        this.checker.errorReporter.styleError(varDecl, "type implicitly set to 'any'");
                    }
                    varDecl.type = this.anyType;
                    if(varDecl.sym) {
                        if(varDecl.sym.isType()) {
                            var tsym = varDecl.sym;
                            if(tsym.isMethod) {
                                this.checker.errorReporter.simpleError(varDecl, "Cannot bind method group to variable.  (Did you mean to use 'declare function' instead of 'declare var'?)");
                                return;
                            } else {
                                this.checker.errorReporter.simpleError(varDecl, "Cannot bind type to variable");
                                return;
                            }
                        }
                        varDecl.sym.setType(varDecl.type);
                    }
                }
            }
        };
        TypeFlow.prototype.typeCheckBoundDecl = function (varDecl) {
            var _this = this;
            var infSym = varDecl.sym;
            if(infSym == null) {
                if(varDecl.init) {
                    varDecl.init = this.typeCheck(varDecl.init);
                    varDecl.type = this.checker.widenType(varDecl.init.type);
                } else {
                    if(this.checker.styleSettings.implicitAny) {
                        this.checker.errorReporter.styleError(varDecl, "type implicitly set to 'any'");
                    }
                    varDecl.type = this.anyType;
                }
            } else {
                if(infSym.typeCheckStatus == TypeScript.TypeCheckStatus.Started) {
                    if(this.checker.styleSettings.implicitAny) {
                        this.checker.errorReporter.styleError(varDecl, "type implicitly set to 'any'");
                    }
                    varDecl.type = this.anyType;
                    infSym.setType(this.anyType);
                } else {
                    if(infSym.typeCheckStatus == TypeScript.TypeCheckStatus.NotStarted) {
                        infSym.typeCheckStatus = TypeScript.TypeCheckStatus.Started;
                        this.checker.addStartedPTO(infSym);
                        var resolved = false;
                        if(varDecl.type == null) {
                            if(varDecl.typeExpr) {
                                this.resolveBoundDecl(varDecl);
                                resolved = true;
                                varDecl.type = varDecl.typeExpr.type;
                                infSym.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();
                            }
                        }
                        if(varDecl.init) {
                            var isLocalStatic = TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.LocalStatic);
                            var prevScope = this.scope;
                            var applyTargetType = !varDecl.init.isParenthesized;
                            if(isLocalStatic) {
                                this.scope = varDecl.sym.container.getType().memberScope;
                            }
                            if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Property) && this.thisClassNode) {
                                TypeScript.getAstWalkerFactory().walk(varDecl.init, function (ast, parent, walker) {
                                    if(ast && ast.nodeType == TypeScript.NodeType.FuncDecl) {
                                        if(TypeScript.hasFlag((ast).fncFlags, TypeScript.FncFlags.IsFatArrowFunction)) {
                                            (ast).fncFlags |= TypeScript.FncFlags.IsPropertyBound;
                                        }
                                        walker.options.goChildren = false;
                                    }
                                    return ast;
                                });
                            }
                            this.checker.typeCheckWithContextualType(varDecl.type, this.checker.inProvisionalTypecheckMode(), applyTargetType, varDecl.init);
                            this.scope = prevScope;
                            if(varDecl.type) {
                                var preserveScope = false;
                                var preservedContainedScope = null;
                                if(varDecl.init.type) {
                                    preservedContainedScope = varDecl.init.type.containedScope;
                                    preserveScope = true;
                                    if(varDecl.init.type == this.voidType) {
                                        this.checker.errorReporter.simpleError(varDecl, "Cannot assign type 'void' to variable '" + varDecl.id.actualText + "'");
                                    }
                                }
                                varDecl.init = this.castWithCoercion(varDecl.init, varDecl.type, applyTargetType && !this.checker.inProvisionalTypecheckMode(), false);
                                if(preserveScope && varDecl.init.type.containedScope == null) {
                                    varDecl.init.type.containedScope = preservedContainedScope;
                                }
                            } else {
                                varDecl.type = this.checker.widenType(varDecl.init.type);
                                if(varDecl.type == this.voidType) {
                                    this.checker.errorReporter.simpleError(varDecl, "Cannot assign type 'void' to variable '" + varDecl.id.actualText + "'");
                                    varDecl.type = this.anyType;
                                }
                            }
                            infSym.setType(varDecl.type);
                        } else {
                            if(!resolved) {
                                this.resolveBoundDecl(varDecl);
                            }
                        }
                        infSym.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();
                    } else {
                        if(this.checker.typeStatusIsFinished(infSym.typeCheckStatus) && (infSym.declAST != varDecl)) {
                            if(varDecl.init) {
                                varDecl.init = this.typeCheck(varDecl.init);
                                varDecl.type = infSym.getType();
                                varDecl.init = this.cast(varDecl.init, varDecl.type);
                            }
                        }
                    }
                }
            }
            if(varDecl.id && varDecl.sym) {
                varDecl.id.sym = varDecl.sym;
            }
            if(varDecl.sym && varDecl.sym.container) {
                this.checkTypePrivacy(varDecl.sym.getType(), varDecl.sym, function (typeName, isModuleName) {
                    return _this.varPrivacyErrorReporter(varDecl, typeName, isModuleName);
                });
            }
            return varDecl;
        };
        TypeFlow.prototype.varPrivacyErrorReporter = function (varDecl, typeName, isModuleName) {
            var typestring = "";
            if(isModuleName) {
                var quotestring = "";
                if(!TypeScript.isQuoted(typeName)) {
                    quotestring = "'";
                }
                typestring = " is using inaccessible module " + quotestring + typeName + quotestring;
            } else {
                typestring = " has or is using private type '" + typeName + "'";
            }
            if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Public)) {
                if(varDecl.sym.container.declAST.nodeType == TypeScript.NodeType.InterfaceDeclaration) {
                    this.checker.errorReporter.simpleError(varDecl, "property '" + varDecl.sym.name + "' of exported interface" + typestring);
                } else {
                    this.checker.errorReporter.simpleError(varDecl, "public member '" + varDecl.sym.name + "' of exported class" + typestring);
                }
            } else {
                this.checker.errorReporter.simpleError(varDecl, "exported variable '" + varDecl.sym.name + "'" + typestring);
            }
        };
        TypeFlow.prototype.typeCheckSuper = function (ast) {
            if(this.thisType && (this.enclosingFncIsMethod && !this.thisFnc.isStatic()) && this.thisType.baseClass()) {
                ast.type = this.thisType.baseClass();
            } else {
                if(!this.enclosingFncIsMethod && this.thisType && this.thisType.baseClass() && this.thisFnc && TypeScript.hasFlag(this.thisFnc.fncFlags, TypeScript.FncFlags.IsFatArrowFunction)) {
                    var enclosingFnc = this.thisFnc.enclosingFnc;
                    while(TypeScript.hasFlag(enclosingFnc.fncFlags, TypeScript.FncFlags.IsFatArrowFunction)) {
                        enclosingFnc = enclosingFnc.enclosingFnc;
                    }
                    if(enclosingFnc && (enclosingFnc.isMethod() || enclosingFnc.isConstructor) && !enclosingFnc.isStatic()) {
                        ast.type = this.thisType.baseClass();
                        enclosingFnc.setHasSuperReferenceInFatArrowFunction();
                        return ast;
                    }
                }
                ast.type = this.anyType;
                this.checker.errorReporter.invalidSuperReference(ast);
            }
            return ast;
        };
        TypeFlow.prototype.typeCheckThis = function (ast) {
            ast.type = this.anyType;
            var illegalThisRef = false;
            if(this.thisFnc == null) {
                if(this.thisType) {
                    if(this.thisClassNode && this.thisClassNode.nodeType == TypeScript.NodeType.ClassDeclaration) {
                        illegalThisRef = true;
                    } else {
                        ast.type = this.thisType;
                    }
                } else {
                    if(this.checker.currentModDecl) {
                        this.checker.errorReporter.simpleError(ast, "'this' may not be referenced within module bodies");
                    }
                }
            } else {
                if(this.thisClassNode && (TypeScript.hasFlag(this.thisFnc.fncFlags, TypeScript.FncFlags.IsPropertyBound) || (this.inSuperCall && TypeScript.hasFlag((this.thisClassNode).varFlags, TypeScript.VarFlags.ClassSuperMustBeFirstCallInConstructor)))) {
                    illegalThisRef = true;
                }
                if(this.thisFnc.isMethod() || this.thisFnc.isConstructor || this.thisFnc.isTargetTypedAsMethod) {
                    if(this.thisType && !(this.thisFnc.fncFlags & TypeScript.FncFlags.Static)) {
                        ast.type = this.thisType;
                    }
                }
            }
            if(!this.enclosingFncIsMethod && this.thisFnc && TypeScript.hasFlag(this.thisFnc.fncFlags, TypeScript.FncFlags.IsFatArrowFunction)) {
                if(this.thisFnc.boundToProperty) {
                    var container = this.thisFnc.boundToProperty.sym.container;
                    if(container.declAST.nodeType == TypeScript.NodeType.FuncDecl) {
                        (container.declAST).setHasSelfReference();
                    }
                } else {
                    var encFnc = this.thisFnc.enclosingFnc;
                    var firstEncFnc = encFnc;
                    while(encFnc) {
                        if(this.thisClassNode && TypeScript.hasFlag(encFnc.fncFlags, TypeScript.FncFlags.IsPropertyBound)) {
                            illegalThisRef = true;
                        }
                        if(!TypeScript.hasFlag(encFnc.fncFlags, TypeScript.FncFlags.IsFatArrowFunction) || encFnc.hasSelfReference()) {
                            encFnc.setHasSelfReference();
                            break;
                        }
                        encFnc = encFnc.enclosingFnc;
                    }
                    if(!encFnc && firstEncFnc) {
                        encFnc = firstEncFnc;
                        encFnc.setHasSelfReference();
                    } else {
                        if(!encFnc) {
                            if(this.thisClassNode) {
                                (this.thisClassNode).varFlags |= TypeScript.VarFlags.MustCaptureThis;
                            } else {
                                if(this.checker.currentModDecl) {
                                    this.checker.currentModDecl.modFlags |= TypeScript.ModuleFlags.MustCaptureThis;
                                } else {
                                    this.checker.mustCaptureGlobalThis = true;
                                }
                            }
                        }
                    }
                    if(encFnc && (encFnc.isMethod() || encFnc.isConstructor) && this.thisType && !TypeScript.hasFlag(encFnc.fncFlags, TypeScript.FncFlags.Static)) {
                        ast.type = this.thisType;
                    }
                }
            }
            if(illegalThisRef) {
                this.checker.errorReporter.simpleError(ast, "Keyword 'this' cannot be referenced in initializers in a class body, or in super constructor calls");
            }
            return ast;
        };
        TypeFlow.prototype.setTypeFromSymbol = function (ast, symbol) {
            if(symbol.isVariable()) {
                if(symbol.isInferenceSymbol()) {
                    var infSym = symbol;
                    if(infSym.declAST && !this.checker.typeStatusIsFinished(infSym.typeCheckStatus)) {
                        this.inScopeTypeCheckDecl(infSym.declAST);
                    }
                    if(!this.checker.styleSettings.innerScopeDeclEscape) {
                        if(infSym.declAST && (infSym.declAST.nodeType == TypeScript.NodeType.VarDecl)) {
                            if(this.nestingLevel < (infSym.declAST).nestingLevel) {
                                this.checker.errorReporter.styleError(ast, "Illegal reference to a variable defined in more nested scope");
                            }
                        }
                    }
                }
                ast.type = symbol.getType();
                if(!symbol.writeable()) {
                    ast.flags = ast.flags & (~(TypeScript.ASTFlags.Writeable));
                }
            } else {
                if(symbol.isType()) {
                    ast.type = symbol.getType();
                    ast.flags = ast.flags & (~(TypeScript.ASTFlags.Writeable));
                } else {
                    ast.type = this.anyType;
                    this.checker.errorReporter.symbolDoesNotReferToAValue(ast, symbol.name);
                }
            }
        };
        TypeFlow.prototype.typeCheckName = function (ast) {
            var _this = this;
            var identifier = ast;
            if(this.checker.inWith) {
                identifier.type = this.anyType;
            } else {
                var typespace = this.inTypeRefTypeCheck;
                var idText = identifier.text;
                var originalIdText = idText;
                var isDynamicModuleName = TypeScript.isQuoted(identifier.text);
                var symbol = this.scope.find(idText, false, typespace);
                if(symbol == null && isDynamicModuleName) {
                    symbol = this.checker.findSymbolForDynamicModule(idText, this.currentScript.locationInfo.filename, function (id) {
                        return _this.scope.find(id, false, typespace);
                    });
                }
                if(!symbol) {
                    if(!identifier.isMissing()) {
                        this.checker.errorReporter.unresolvedSymbol(identifier, identifier.text);
                    }
                    identifier.type = this.anyType;
                } else {
                    if(TypeScript.optimizeModuleCodeGen && symbol && symbol.isType()) {
                        var symType = symbol.getType();
                        if(symType && (symbol).aliasLink && (symbol).onlyReferencedAsTypeRef) {
                            var modDecl = symType.symbol.declAST;
                            if(modDecl && TypeScript.hasFlag(modDecl.modFlags, TypeScript.ModuleFlags.IsDynamic)) {
                                (symbol).onlyReferencedAsTypeRef = this.inTypeRefTypeCheck;
                            }
                        }
                    }
                    if(symbol.declAST && symbol.declAST.nodeType == TypeScript.NodeType.FuncDecl && !(symbol.declAST).returnTypeAnnotation && (symbol.declAST).signature.typeCheckStatus == TypeScript.TypeCheckStatus.Started) {
                        (symbol.declAST).type.symbol.flags |= TypeScript.SymbolFlags.RecursivelyReferenced;
                        (symbol.declAST).signature.returnType.type = this.anyType;
                    }
                    this.setTypeFromSymbol(ast, symbol);
                    identifier.sym = symbol;
                    if(this.thisFnc) {
                        if(this.thisFnc.type && symbol.container != this.thisFnc.type.symbol) {
                            this.thisFnc.freeVariables[this.thisFnc.freeVariables.length] = symbol;
                        }
                    }
                }
            }
            return ast;
        };
        TypeFlow.prototype.typeCheckScript = function (script) {
            this.checker.locationInfo = script.locationInfo;
            this.scope = this.checker.globalScope;
            if(!script.topLevelMod) {
                this.addLocalsFromScope(this.scope, this.checker.gloMod, script.vars, this.checker.globals, true);
            }
            this.currentScript = script;
            script.bod = this.typeCheck(script.bod);
            this.currentScript = null;
            return script;
        };
        TypeFlow.prototype.typeCheckBitNot = function (ast) {
            var unex = ast;
            unex.operand = this.typeCheck(unex.operand);
            unex.type = this.doubleType;
            return unex;
        };
        TypeFlow.prototype.typeCheckUnaryNumberOperator = function (ast) {
            var unex = ast;
            unex.operand = this.typeCheck(unex.operand);
            unex.type = this.doubleType;
            return ast;
        };
        TypeFlow.prototype.typeCheckLogNot = function (ast) {
            var unex = ast;
            unex.operand = this.typeCheck(unex.operand);
            unex.type = this.booleanType;
            return unex;
        };
        TypeFlow.prototype.astIsWriteable = function (ast) {
            return TypeScript.hasFlag(ast.flags, TypeScript.ASTFlags.Writeable);
        };
        TypeFlow.prototype.typeCheckIncOrDec = function (ast) {
            var unex = ast;
            var lval = unex.operand;
            if(!this.astIsWriteable(unex)) {
                this.checker.errorReporter.valueCannotBeModified(unex);
                unex.type = this.doubleType;
            } else {
                unex = this.typeCheckUnaryNumberOperator(ast);
                if(unex.operand.type != this.checker.numberType && unex.operand.type != this.checker.anyType && !(unex.operand.type.typeFlags & TypeScript.TypeFlags.IsEnum)) {
                    this.checker.errorReporter.simpleError(ast, "'++' and '--' may only be applied to operands of type 'number' or 'any'");
                }
            }
            return unex;
        };
        TypeFlow.prototype.typeCheckBitwiseOperator = function (ast, assignment) {
            var binex = ast;
            var resultType = null;
            binex.operand1 = this.typeCheck(binex.operand1);
            binex.operand2 = this.typeCheck(binex.operand2);
            var leftType = binex.operand1.type;
            var rightType = binex.operand2.type;
            if(assignment && (!this.astIsWriteable(binex))) {
                this.checker.errorReporter.valueCannotBeModified(binex);
            }
            if(this.checker.styleSettings.bitwise) {
                this.checker.errorReporter.styleError(ast, "use of " + TypeScript.nodeTypeTable[binex.nodeType]);
            }
            if(this.checker.sourceIsSubtypeOfTarget(leftType, this.doubleType) && (this.checker.sourceIsSubtypeOfTarget(rightType, this.doubleType))) {
                resultType = this.doubleType;
            } else {
                if((leftType == this.booleanType) && (rightType == this.booleanType)) {
                    resultType = this.booleanType;
                } else {
                    if(leftType == this.anyType) {
                        if((rightType == this.anyType) || (rightType == this.doubleType) || (rightType == this.booleanType)) {
                            resultType = this.anyType;
                        }
                    } else {
                        if(rightType == this.anyType) {
                            if((leftType == this.anyType) || (leftType == this.doubleType) || (leftType == this.booleanType)) {
                                resultType = this.anyType;
                            }
                        }
                    }
                }
            }
            if(resultType == null) {
                resultType = this.anyType;
                this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType, binex.printLabel(), this.scope);
            }
            binex.type = resultType;
            return binex;
        };
        TypeFlow.prototype.typeCheckArithmeticOperator = function (ast, assignment) {
            var binex = ast;
            binex.operand1 = this.typeCheck(binex.operand1);
            binex.operand2 = this.typeCheck(binex.operand2);
            var leftType = binex.operand1.type;
            var rightType = binex.operand2.type;
            if(assignment && (!this.astIsWriteable(binex.operand1))) {
                this.checker.errorReporter.valueCannotBeModified(binex);
            }
            if(this.checker.styleSettings.bitwise && ((binex.nodeType == TypeScript.NodeType.And) || (binex.nodeType == TypeScript.NodeType.Or) || (binex.nodeType == TypeScript.NodeType.AsgAnd) || (binex.nodeType == TypeScript.NodeType.AsgOr))) {
                this.checker.errorReporter.styleError(ast, "use of " + TypeScript.nodeTypeTable[binex.nodeType]);
            }
            if(leftType == null || rightType == null) {
                this.checker.errorReporter.simpleError(binex, "Could not typecheck arithmetic operation.  Possible recursive typecheck error?");
                binex.type = this.anyType;
                return binex;
            }
            var nodeType = binex.nodeType;
            if(this.checker.isNullOrUndefinedType(leftType)) {
                leftType = rightType;
            }
            if(this.checker.isNullOrUndefinedType(rightType)) {
                rightType = leftType;
            }
            leftType = this.checker.widenType(leftType);
            rightType = this.checker.widenType(rightType);
            if(nodeType == TypeScript.NodeType.Add || nodeType == TypeScript.NodeType.AsgAdd) {
                if(leftType == this.checker.stringType || rightType == this.checker.stringType) {
                    binex.type = this.checker.stringType;
                } else {
                    if(leftType == this.checker.numberType && rightType == this.checker.numberType) {
                        binex.type = this.checker.numberType;
                    } else {
                        if(this.checker.sourceIsSubtypeOfTarget(leftType, this.checker.numberType) && this.checker.sourceIsSubtypeOfTarget(rightType, this.checker.numberType)) {
                            binex.type = this.checker.numberType;
                        } else {
                            if(leftType == this.checker.anyType || rightType == this.checker.anyType) {
                                binex.type = this.checker.anyType;
                            } else {
                                binex.type = this.anyType;
                                this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType, binex.printLabel(), this.scope);
                            }
                        }
                    }
                }
            } else {
                if(leftType == this.checker.numberType && rightType == this.checker.numberType) {
                    binex.type = this.checker.numberType;
                } else {
                    if(this.checker.sourceIsSubtypeOfTarget(leftType, this.checker.numberType) && this.checker.sourceIsSubtypeOfTarget(rightType, this.checker.numberType)) {
                        binex.type = this.checker.numberType;
                    } else {
                        if(leftType == this.checker.anyType || rightType == this.checker.anyType) {
                            binex.type = this.checker.numberType;
                        } else {
                            binex.type = this.anyType;
                            this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType, binex.printLabel(), this.scope);
                        }
                    }
                }
            }
            return binex;
        };
        TypeFlow.prototype.typeCheckDotOperator = function (ast) {
            var binex = ast;
            var leftIsFnc = false;
            binex.operand1 = this.typeCheck(binex.operand1);
            var leftType = binex.operand1.type;
            var leftScope = null;
            if(leftType) {
                if(leftType == this.anyType) {
                    binex.type = this.anyType;
                    return binex;
                } else {
                    if(leftType == this.stringType) {
                        if(this.stringInterfaceType) {
                            leftScope = this.stringInterfaceType.memberScope;
                        } else {
                            binex.type = this.anyType;
                            return binex;
                        }
                    } else {
                        if(leftType == this.doubleType) {
                            if(this.numberInterfaceType) {
                                leftScope = this.numberInterfaceType.memberScope;
                            } else {
                                binex.type = this.anyType;
                                return binex;
                            }
                        } else {
                            if(leftType == this.booleanType) {
                                if(this.booleanInterfaceType) {
                                    leftScope = this.booleanInterfaceType.memberScope;
                                } else {
                                    binex.type = this.anyType;
                                    return binex;
                                }
                            } else {
                                if((leftType.call || leftType.construct) && leftType.members == null) {
                                    if(this.functionInterfaceType) {
                                        leftScope = this.functionInterfaceType.memberScope;
                                    } else {
                                        binex.type = this.anyType;
                                        return binex;
                                    }
                                } else {
                                    if(leftType.elementType) {
                                        if(this.arrayInterfaceType) {
                                            var arrInstType = leftType.elementType.getArrayBase(this.arrayInterfaceType, this.checker);
                                            leftScope = arrInstType.memberScope;
                                        } else {
                                            binex.type = this.anyType;
                                            return binex;
                                        }
                                    } else {
                                        leftScope = leftType.memberScope;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if(leftScope == null) {
                this.checker.errorReporter.expectedClassOrInterface(binex);
                binex.type = this.anyType;
            } else {
                var propertyName = binex.operand2;
                var lhsIsEnclosingType = (this.thisClassNode && binex.operand1.type == this.thisClassNode.type.instanceType) || this.inTypeRefTypeCheck;
                var symbol = leftScope.find(propertyName.text, !lhsIsEnclosingType, this.inTypeRefTypeCheck);
                if(!symbol) {
                    if(this.objectInterfaceType && leftType) {
                        if(leftType.isReferenceType()) {
                            symbol = this.objectInterfaceType.memberScope.find(propertyName.text, false, this.inTypeRefTypeCheck);
                        }
                        if(!symbol) {
                            if(this.functionInterfaceType && (leftType.call || leftType.construct)) {
                                symbol = this.functionInterfaceType.memberScope.find(propertyName.text, false, this.inTypeRefTypeCheck);
                            }
                        }
                    }
                }
                if(!symbol || (!symbol.visible(leftScope, this.checker))) {
                    binex.type = this.anyType;
                    if(symbol == null) {
                        this.checker.errorReporter.simpleError(propertyName, "The property '" + propertyName.actualText + "' does not exist on value of type '" + leftType.getScopedTypeName(this.scope) + "'");
                    } else {
                        if(!this.inTypeRefTypeCheck) {
                            this.checker.errorReporter.simpleError(binex, "The property '" + propertyName.actualText + " on type '" + leftType.getScopedTypeName(this.scope) + "' is not visible");
                        }
                    }
                } else {
                    if(symbol.isVariable()) {
                        if(symbol.isInferenceSymbol()) {
                            var infSym = symbol;
                            if(infSym.declAST && !this.checker.typeStatusIsFinished(infSym.typeCheckStatus)) {
                                this.inScopeTypeCheckDecl(infSym.declAST);
                            }
                        }
                    }
                    propertyName.sym = symbol;
                    binex.type = symbol.getType();
                }
            }
            if(binex.type == null) {
                binex.type = this.anyType;
            }
            return binex;
        };
        TypeFlow.prototype.typeCheckBooleanOperator = function (ast) {
            var binex = ast;
            binex.operand1 = this.typeCheck(binex.operand1);
            binex.operand2 = this.typeCheck(binex.operand2);
            var leftType = binex.operand1.type;
            var rightType = binex.operand2.type;
            if((!(this.checker.sourceIsAssignableToTarget(leftType, rightType))) && (!(this.checker.sourceIsAssignableToTarget(rightType, leftType)))) {
                this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType, binex.printLabel(), this.scope);
            }
            binex.type = this.booleanType;
            return binex;
        };
        TypeFlow.prototype.typeCheckAsgOperator = function (ast) {
            var binex = ast;
            var applyTargetType = !binex.operand2.isParenthesized;
            binex.operand1 = this.typeCheck(binex.operand1);
            this.checker.typeCheckWithContextualType(binex.operand1.type, this.checker.inProvisionalTypecheckMode(), applyTargetType, binex.operand2);
            var leftType = binex.operand1.type;
            var rightType = binex.operand2.type;
            if(!(this.astIsWriteable(binex.operand1))) {
                this.checker.errorReporter.valueCannotBeModified(binex);
            }
            if(binex.operand1.nodeType == TypeScript.NodeType.Call) {
                var callEx = binex.operand1;
            }
            var preserveScope = false;
            var preservedContainedScope = null;
            if(binex.operand2.type) {
                preservedContainedScope = binex.operand2.type.containedScope;
                preserveScope = true;
            }
            binex.operand2 = this.castWithCoercion(binex.operand2, leftType, applyTargetType && !this.checker.inProvisionalTypecheckMode(), false);
            if(preserveScope && binex.operand2.type.containedScope == null) {
                binex.operand2.type.containedScope = preservedContainedScope;
            }
            binex.type = rightType;
            return binex;
        };
        TypeFlow.prototype.typeCheckIndex = function (ast) {
            var binex = ast;
            binex.operand1 = this.typeCheck(binex.operand1);
            binex.operand2 = this.typeCheck(binex.operand2);
            if(!this.checker.styleSettings.literalSubscript) {
                if(binex.operand2.nodeType == TypeScript.NodeType.QString) {
                    this.checker.errorReporter.styleError(ast, "use literal subscript ('.') notation instead)");
                }
            }
            var objExprType = binex.operand1.type;
            var indexExprType = binex.operand2.type;
            if(objExprType.elementType) {
                if(indexExprType == this.checker.anyType || indexExprType == this.checker.numberType || TypeScript.hasFlag(indexExprType.typeFlags, TypeScript.TypeFlags.IsEnum)) {
                    binex.type = objExprType.elementType;
                } else {
                    if(indexExprType == this.checker.stringType) {
                        binex.type = this.checker.anyType;
                    } else {
                        this.checker.errorReporter.simpleError(binex, "Illegal property access");
                        binex.type = this.checker.anyType;
                    }
                }
            } else {
                if(objExprType.index) {
                    if(indexExprType == this.checker.anyType || !((objExprType.index.flags & TypeScript.SignatureFlags.IsStringIndexer) || (objExprType.index.flags & TypeScript.SignatureFlags.IsNumberIndexer)) || ((objExprType.index.flags & TypeScript.SignatureFlags.IsStringIndexer) && indexExprType == this.checker.stringType) || ((objExprType.index.flags & TypeScript.SignatureFlags.IsNumberIndexer) && (indexExprType == this.checker.numberType || TypeScript.hasFlag(indexExprType.typeFlags, TypeScript.TypeFlags.IsEnum)))) {
                        var sig = this.resolveOverload(ast, objExprType.index);
                        if(sig) {
                            binex.type = sig.returnType.type;
                        } else {
                            binex.type = this.checker.anyType;
                        }
                    } else {
                        if(indexExprType == this.checker.stringType) {
                            binex.type = this.checker.anyType;
                        } else {
                            this.checker.errorReporter.simpleError(binex, "Illegal property access");
                            binex.type = this.checker.anyType;
                        }
                    }
                } else {
                    if((objExprType == this.checker.anyType || objExprType == this.checker.stringType || objExprType == this.checker.numberType || objExprType == this.checker.booleanType || objExprType.isReferenceType()) && (indexExprType == this.checker.anyType || indexExprType == this.checker.stringType || (indexExprType == this.checker.numberType || TypeScript.hasFlag(indexExprType.typeFlags, TypeScript.TypeFlags.IsEnum)))) {
                        binex.type = this.checker.anyType;
                    } else {
                        this.checker.errorReporter.simpleError(binex, "Illegal property access");
                        binex.type = this.checker.anyType;
                    }
                }
            }
            return binex;
        };
        TypeFlow.prototype.typeCheckInOperator = function (binex) {
            binex.operand1 = this.cast(this.typeCheck(binex.operand1), this.stringType);
            binex.operand2 = this.typeCheck(binex.operand2);
            if(!((binex.operand1.type == this.checker.anyType || binex.operand1.type == this.checker.stringType) && (binex.operand2.type == this.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand2.type, this.objectInterfaceType)))) {
                this.checker.errorReporter.simpleError(binex, "The in operator requires the left operand to be of type Any or the String primitive type, and the right operand to be of type Any or an object type");
            }
            binex.type = this.booleanType;
            return binex;
        };
        TypeFlow.prototype.typeCheckShift = function (binex, assignment) {
            binex.operand1 = this.cast(this.typeCheck(binex.operand1), this.doubleType);
            binex.operand2 = this.cast(this.typeCheck(binex.operand2), this.doubleType);
            if(assignment && (!(this.astIsWriteable(binex.operand1)))) {
                this.checker.errorReporter.valueCannotBeModified(binex);
            }
            binex.type = this.doubleType;
            return binex;
        };
        TypeFlow.prototype.typeCheckQMark = function (trinex) {
            trinex.operand1 = this.typeCheck(trinex.operand1);
            trinex.operand2 = this.typeCheck(trinex.operand2);
            trinex.operand3 = this.typeCheck(trinex.operand3);
            var leftType = trinex.operand2.type;
            var rightType = trinex.operand3.type;
            if(leftType == rightType) {
                trinex.type = leftType;
            } else {
                if(this.checker.sourceIsSubtypeOfTarget(leftType, rightType)) {
                    trinex.type = rightType;
                } else {
                    if(this.checker.sourceIsSubtypeOfTarget(rightType, leftType)) {
                        trinex.type = leftType;
                    } else {
                        trinex.type = this.anyType;
                        this.checker.errorReporter.incompatibleTypes(trinex, leftType, rightType, trinex.printLabel(), this.scope);
                    }
                }
            }
            return trinex;
        };
        TypeFlow.prototype.addFormals = function (container, signature, table) {
            var len = signature.parameters.length;
            for(var i = 0; i < len; i++) {
                var symbol = signature.parameters[i];
                symbol.container = container;
                table.add(symbol.name, symbol);
            }
        };
        TypeFlow.prototype.addLocalsFromScope = function (scope, container, vars, table, isModContainer) {
            var len = vars.members.length;
            var hasArgsDef = false;
            for(var i = 0; i < len; i++) {
                var local = vars.members[i];
                if(((local.sym == null) || (local.sym.kind() != TypeScript.SymbolKind.Field))) {
                    var result = null;
                    if((result = table.lookup(local.id.text)) == null) {
                        var localVar = new TypeScript.ValueLocation();
                        localVar.typeLink = new TypeScript.TypeLink();
                        var varSym = null;
                        if(TypeScript.hasFlag(local.varFlags, TypeScript.VarFlags.Static)) {
                            local.varFlags |= TypeScript.VarFlags.LocalStatic;
                            varSym = new TypeScript.FieldSymbol(local.id.text, local.minChar, this.checker.locationInfo.unitIndex, true, localVar);
                        } else {
                            varSym = new TypeScript.VariableSymbol(local.id.text, local.minChar, this.checker.locationInfo.unitIndex, localVar);
                        }
                        varSym.transferVarFlags(local.varFlags);
                        localVar.symbol = varSym;
                        varSym.declAST = local;
                        localVar.typeLink.ast = local.typeExpr;
                        this.checker.resolveTypeLink(scope, localVar.typeLink, false);
                        if((local.type == null) && (local.init == null)) {
                            local.type = this.anyType;
                        }
                        localVar.typeLink.type = local.type;
                        localVar.symbol.container = container;
                        local.sym = localVar.symbol;
                        table.add(local.id.text, varSym);
                        if(local.id.text == "arguments") {
                            hasArgsDef = true;
                        }
                    } else {
                        local.type = result.getType();
                        local.sym = result;
                    }
                }
            }
            if(!isModContainer) {
                if(!hasArgsDef) {
                    var argLoc = new TypeScript.ValueLocation();
                    argLoc.typeLink = new TypeScript.TypeLink();
                    var theArgSym = new TypeScript.VariableSymbol("arguments", vars.minChar, this.checker.locationInfo.unitIndex, argLoc);
                    if(!this.iargumentsInterfaceType) {
                        var argumentsSym = scope.find("IArguments", false, true);
                        if(argumentsSym) {
                            argumentsSym.flags |= TypeScript.SymbolFlags.CompilerGenerated;
                            this.iargumentsInterfaceType = argumentsSym.getType();
                        } else {
                            this.iargumentsInterfaceType = this.anyType;
                        }
                    }
                    argLoc.typeLink.type = this.iargumentsInterfaceType;
                    table.add("arguments", theArgSym);
                }
            }
        };
        TypeFlow.prototype.addConstructorLocalArgs = function (container, args, table, isClass) {
            if(args) {
                var len = args.members.length;
                for(var i = 0; i < len; i++) {
                    var local = args.members[i];
                    if((local.sym == null) || (isClass || (local.sym.kind() != TypeScript.SymbolKind.Field))) {
                        var result = null;
                        if((result = table.lookup(local.id.text)) == null) {
                            this.resolveBoundDecl(local);
                            var localVar = new TypeScript.ValueLocation();
                            localVar.typeLink = new TypeScript.TypeLink();
                            var varSym = new TypeScript.ParameterSymbol(local.id.text, local.minChar, this.checker.locationInfo.unitIndex, localVar);
                            varSym.declAST = local;
                            localVar.symbol = varSym;
                            localVar.typeLink.type = local.type;
                            localVar.symbol.container = container;
                            local.sym = localVar.symbol;
                            table.add(local.id.text, varSym);
                        } else {
                            local.type = result.getType();
                            local.sym = result;
                        }
                    }
                }
            }
        };
        TypeFlow.prototype.checkInitSelf = function (funcDecl) {
            if(!funcDecl.isMethod()) {
                var freeVars = funcDecl.freeVariables;
                for(var k = 0, len = freeVars.length; k < len; k++) {
                    var sym = freeVars[k];
                    if(sym.isInstanceProperty()) {
                        return true;
                    }
                }
            }
            var fns = funcDecl.scopes;
            var fnsLen = fns.members.length;
            for(var j = 0; j < fnsLen; j++) {
                var fn = fns.members[j];
                if(this.checkInitSelf(fn)) {
                    return true;
                }
            }
            return false;
        };
        TypeFlow.prototype.checkPromoteFreeVars = function (funcDecl, constructorSym) {
            var freeVars = funcDecl.freeVariables;
            for(var k = 0, len = freeVars.length; k < len; k++) {
                var sym = freeVars[k];
                if((!sym.isInstanceProperty()) && (sym.container == constructorSym)) {
                    TypeScript.instanceFilter.reset();
                    if(this.scope.search(TypeScript.instanceFilter, sym.name, false, false)) {
                        this.checker.errorReporter.simpleError(funcDecl, "Constructor-local variable shadows class property '" + sym.name + "'. To access the class property, use 'self." + sym.name + "'");
                    }
                    this.checker.errorReporter.simpleError(funcDecl, "Constructor-local variables may not be accessed from instance method bodies. Consider changing local variable '" + sym.name + "' to a class property");
                }
            }
        };
        TypeFlow.prototype.allReturnsAreVoid = function (funcDecl) {
            var allReturnsAreVoid = true;
            if(funcDecl.signature.returnType.type == null) {
                var preFindReturnExpressionTypes = function (ast, parent, walker) {
                    var go = true;
                    switch(ast.nodeType) {
                        case TypeScript.NodeType.FuncDecl: {
                            go = false;
                            break;

                        }
                        case TypeScript.NodeType.Return: {
                            var returnStmt = ast;
                            if(returnStmt.returnExpression) {
                                allReturnsAreVoid = false;
                                go = false;
                            }

                        }
                        default: {
                            break;

                        }
                    }
                    walker.options.goChildren = go;
                    walker.options.goNextSibling = go;
                    return ast;
                };
                TypeScript.getAstWalkerFactory().walk(funcDecl.bod, preFindReturnExpressionTypes);
            }
            return allReturnsAreVoid;
        };
        TypeFlow.prototype.classConstructorHasSuperCall = function (funcDecl) {
            var foundSuper = false;
            var preFindSuperCall = function (ast, parent, walker) {
                var go = true;
                switch(ast.nodeType) {
                    case TypeScript.NodeType.FuncDecl: {
                        go = false;
                        break;

                    }
                    case TypeScript.NodeType.Call: {
                        var call = ast;
                        if(call.target.nodeType == TypeScript.NodeType.Super) {
                            go = false;
                            foundSuper = true;
                            break;
                        }
                        break;

                    }
                    default: {
                        break;

                    }
                }
                walker.options.goChildren = go;
                return ast;
            };
            TypeScript.getAstWalkerFactory().walk(funcDecl.bod, preFindSuperCall);
            return foundSuper;
        };
        TypeFlow.prototype.baseListPrivacyErrorReporter = function (bases, i, declSymbol, extendsList, typeName, isModuleName) {
            var baseSymbol = bases.members[i].type.symbol;
            var declTypeString = (declSymbol.declAST.nodeType == TypeScript.NodeType.InterfaceDeclaration) ? "interface" : "class";
            var baseListTypeString = extendsList ? "extends" : "implements";
            var baseTypeString = (baseSymbol.declAST.nodeType == TypeScript.NodeType.InterfaceDeclaration) ? "interface" : "class";
            var typestring = "";
            if(isModuleName) {
                var quotestring = "";
                if(!TypeScript.isQuoted(typeName)) {
                    quotestring = "'";
                }
                typestring = " is using inaccessible module ";
                baseTypeString = " " + baseTypeString + " from private module " + quotestring + typeName + quotestring;
            } else {
                baseTypeString = " private " + baseTypeString + " '" + typeName + "'";
            }
            this.checker.errorReporter.simpleError(bases.members[i], "exported " + declTypeString + " '" + declSymbol.name + "' " + baseListTypeString + baseTypeString);
        };
        TypeFlow.prototype.typeCheckBaseListPrivacy = function (bases, declSymbol, extendsList) {
            var _this = this;
            if(bases) {
                var basesLen = bases.members.length;
                for(var i = 0; i < basesLen; i++) {
                    if(!bases.members[i].type || bases.members[i].type == this.checker.anyType) {
                        continue;
                    }
                    this.checkSymbolPrivacy(bases.members[i].type.symbol, declSymbol, function (typeName, isModuleName) {
                        return _this.baseListPrivacyErrorReporter(bases, i, declSymbol, extendsList, typeName, isModuleName);
                    });
                }
            }
        };
        TypeFlow.prototype.checkSymbolPrivacy = function (typeSymbol, declSymbol, errorCallback) {
            var externalModuleSymbol = null;
            var declSymbolPath = null;
            if(typeSymbol.isExternallyVisible(this.checker)) {
                var typeSymbolPath = typeSymbol.pathToRoot();
                declSymbolPath = declSymbol.pathToRoot();
                var typeSymbolLength = typeSymbolPath.length;
                var declSymbolPathLength = declSymbolPath.length;
                if(typeSymbolLength > 0) {
                    if(typeSymbolPath[typeSymbolLength - 1].getType().isModuleType() && (typeSymbolPath[typeSymbolLength - 1]).isDynamic && typeSymbolPath[typeSymbolLength - 1] != declSymbolPath[declSymbolPathLength - 1]) {
                        externalModuleSymbol = typeSymbolPath[typeSymbolLength - 1];
                    } else {
                        if(typeSymbolLength > 1) {
                            if(typeSymbolPath[typeSymbolLength - 2].getType().isModuleType() && (typeSymbolPath[typeSymbolLength - 2]).isDynamic && (declSymbolPathLength == 1 || typeSymbolPath[typeSymbolLength - 2] != declSymbolPath[declSymbolPathLength - 2])) {
                                externalModuleSymbol = typeSymbolPath[typeSymbolLength - 2];
                            }
                        }
                    }
                }
                if(externalModuleSymbol == null) {
                    return;
                }
            }
            var interfaceDecl = declSymbol.getInterfaceDeclFromSymbol(this.checker);
            if(interfaceDecl && !TypeScript.hasFlag(interfaceDecl.varFlags, TypeScript.VarFlags.Exported)) {
                return;
            }
            var checkVisibilitySymbol = declSymbol;
            var varDecl = declSymbol.getVarDeclFromSymbol();
            if(varDecl) {
                if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Private)) {
                    return;
                } else {
                    if(TypeScript.hasFlag(varDecl.varFlags, TypeScript.VarFlags.Public)) {
                        checkVisibilitySymbol = declSymbol.container;
                    }
                }
            }
            if(checkVisibilitySymbol.isExternallyVisible(this.checker)) {
                var privateSymbolName = typeSymbol.name;
                if(externalModuleSymbol != null) {
                    var prettyName = externalModuleSymbol.getPrettyNameOfDynamicModule(declSymbolPath);
                    if(prettyName != null) {
                        this.currentScript.AddExternallyVisibleImportedSymbol(prettyName.symbol, this.checker);
                        return;
                    } else {
                        privateSymbolName = externalModuleSymbol.prettyName;
                    }
                }
                errorCallback(privateSymbolName, typeSymbol.name != privateSymbolName);
            }
        };
        TypeFlow.prototype.checkTypePrivacy = function (type, declSymbol, errorCallback) {
            var _this = this;
            if(!(type && type.primitiveTypeClass == TypeScript.Primitive.None)) {
                return;
            }
            if(type.isArray()) {
                return this.checkTypePrivacy(type.elementType, declSymbol, errorCallback);
            }
            if(type.symbol && type.symbol.name && type.symbol.name != "_anonymous" && (((type.call == null) && (type.construct == null) && (type.index == null)) || (type.members && (!type.isClass())))) {
                return this.checkSymbolPrivacy(type.symbol, declSymbol, errorCallback);
            }
            if(type.members) {
                type.members.allMembers.map(function (key, s, unused) {
                    var sym = s;
                    if(!TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.BuiltIn)) {
                        _this.checkTypePrivacy(sym.getType(), declSymbol, errorCallback);
                    }
                }, null);
            }
            this.checkSignatureGroupPrivacy(type.call, declSymbol, errorCallback);
            this.checkSignatureGroupPrivacy(type.construct, declSymbol, errorCallback);
            this.checkSignatureGroupPrivacy(type.index, declSymbol, errorCallback);
        };
        TypeFlow.prototype.checkSignatureGroupPrivacy = function (sgroup, declSymbol, errorCallback) {
            if(sgroup) {
                var len = sgroup.signatures.length;
                for(var i = 0; i < sgroup.signatures.length; i++) {
                    var signature = sgroup.signatures[i];
                    if(len > 1 && signature == sgroup.definitionSignature) {
                        continue;
                    }
                    if(signature.returnType) {
                        this.checkTypePrivacy(signature.returnType.type, declSymbol, errorCallback);
                    }
                    var paramLen = signature.parameters.length;
                    for(var j = 0; j < paramLen; j++) {
                        var param = signature.parameters[j];
                        this.checkTypePrivacy(param.getType(), declSymbol, errorCallback);
                    }
                }
            }
        };
        TypeFlow.prototype.functionArgumentPrivacyErrorReporter = function (funcDecl, p, paramSymbol, typeName, isModuleName) {
            var isGetter = funcDecl.isAccessor() && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor);
            var isSetter = funcDecl.isAccessor() && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.SetAccessor);
            var isPublicFunc = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Public);
            var isContainerInterface = funcDecl.type.symbol.getInterfaceDeclFromSymbol(this.checker) != null;
            var typestring = "";
            if(isModuleName) {
                var quotestring = "";
                if(!TypeScript.isQuoted(typeName)) {
                    quotestring = "'";
                }
                typestring = " is using inaccessible module " + quotestring + typeName + quotestring;
            } else {
                typestring = " has or is using private type '" + typeName + "'";
            }
            if(!isContainerInterface) {
                if(funcDecl.isConstructor) {
                    this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], "exported class's constructor parameter '" + paramSymbol.name + "'" + typestring);
                } else {
                    if(isSetter) {
                        this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], (isPublicFunc ? "public" : "exported") + " setter parameter '" + paramSymbol.name + "'" + typestring);
                    } else {
                        if(!isGetter) {
                            this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], (isPublicFunc ? "public" : "exported") + " function parameter '" + paramSymbol.name + "'" + typestring);
                        }
                    }
                }
            } else {
                if(funcDecl.isConstructMember()) {
                    this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], "exported interface's constructor parameter '" + paramSymbol.name + "'" + typestring);
                } else {
                    if(funcDecl.isCallMember()) {
                        this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], "exported interface's call parameter '" + paramSymbol.name + "'" + typestring);
                    } else {
                        if(!funcDecl.isIndexerMember()) {
                            this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], "exported interface's function parameter '" + paramSymbol.name + "'" + typestring);
                        }
                    }
                }
            }
        };
        TypeFlow.prototype.returnTypePrivacyError = function (astError, funcDecl, typeName, isModuleName) {
            var isGetter = funcDecl.isAccessor() && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor);
            var isSetter = funcDecl.isAccessor() && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.SetAccessor);
            var isPublicFunc = TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Public);
            var isContainerInterface = funcDecl.type.symbol.getInterfaceDeclFromSymbol(this.checker) != null;
            var typestring = "";
            if(isModuleName) {
                var quotestring = "";
                if(!TypeScript.isQuoted(typeName)) {
                    quotestring = "'";
                }
                typestring = " is using inaccessible module " + quotestring + typeName + quotestring;
            } else {
                typestring = " has or is using private type '" + typeName + "'";
            }
            if(!isContainerInterface) {
                if(isGetter) {
                    this.checker.errorReporter.simpleError(astError, (isPublicFunc ? "public" : "exported") + " getter return type" + typestring);
                } else {
                    if(!isSetter) {
                        this.checker.errorReporter.simpleError(astError, (isPublicFunc ? "public" : "exported") + " function return type" + typestring);
                    }
                }
            } else {
                if(funcDecl.isConstructMember()) {
                    this.checker.errorReporter.simpleError(astError, "exported interface's constructor return type" + typestring);
                } else {
                    if(funcDecl.isCallMember()) {
                        this.checker.errorReporter.simpleError(astError, "exported interface's call return type" + typestring);
                    } else {
                        if(funcDecl.isIndexerMember()) {
                            this.checker.errorReporter.simpleError(astError, "exported interface's indexer return type" + typestring);
                        } else {
                            this.checker.errorReporter.simpleError(astError, "exported interface's function return type" + typestring);
                        }
                    }
                }
            }
        };
        TypeFlow.prototype.functionReturnTypePrivacyErrorReporter = function (funcDecl, signature, typeName, isModuleName) {
            var reportOnFuncDecl = false;
            if(funcDecl.returnTypeAnnotation != null && funcDecl.returnTypeAnnotation.type == signature.returnType.type) {
                this.returnTypePrivacyError(funcDecl.returnTypeAnnotation, funcDecl, typeName, isModuleName);
            }
            for(var i = 0; i < funcDecl.returnStatementsWithExpressions.length; i++) {
                if(funcDecl.returnStatementsWithExpressions[i].type == signature.returnType.type) {
                    this.returnTypePrivacyError(funcDecl.returnStatementsWithExpressions[i], funcDecl, typeName, isModuleName);
                } else {
                    reportOnFuncDecl = true;
                }
            }
            if(reportOnFuncDecl) {
                this.returnTypePrivacyError(funcDecl, funcDecl, typeName, isModuleName);
            }
        };
        TypeFlow.prototype.typeCheckFunction = function (funcDecl) {
            var _this = this;
            this.nestingLevel = 0;
            var fnType = funcDecl.type;
            var fgSym = fnType.symbol;
            var signature = funcDecl.signature;
            if(this.checker.typeStatusIsFinished(signature.typeCheckStatus)) {
                return funcDecl;
            } else {
                if(signature.typeCheckStatus == TypeScript.TypeCheckStatus.Started) {
                    if(!funcDecl.returnTypeAnnotation && funcDecl.bod && !funcDecl.isSignature() && !(funcDecl.isConstructor) && this.allReturnsAreVoid(funcDecl)) {
                        signature.returnType.type = this.voidType;
                        return funcDecl;
                    } else {
                        if(funcDecl.returnTypeAnnotation == null) {
                            if(this.checker.styleSettings.implicitAny) {
                                this.checker.errorReporter.styleError(funcDecl, "type implicitly set to 'any'");
                            }
                            signature.returnType.type = this.anyType;
                            fgSym.flags |= TypeScript.SymbolFlags.RecursivelyReferenced;
                        }
                        return funcDecl;
                    }
                }
            }
            signature.typeCheckStatus = TypeScript.TypeCheckStatus.Started;
            this.checker.addStartedPTO(signature);
            var prevScope = this.scope;
            var prevFnc = this.thisFnc;
            var prevMethodStatus = this.enclosingFncIsMethod;
            var prevClassNode = this.thisClassNode;
            this.enclosingFncIsMethod = funcDecl.isMethod() || funcDecl.isConstructor;
            this.thisFnc = funcDecl;
            var container = funcDecl.type.symbol;
            var prevThisType = this.thisType;
            var prevLocationInfo = this.checker.locationInfo;
            var funcTable = null;
            var acceptedContextualType = false;
            var targetParams = null;
            var targetReturnType = null;
            var isGetter = funcDecl.isAccessor() && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor);
            var isSetter = funcDecl.isAccessor() && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.SetAccessor);
            var accessorType = (isGetter || isSetter) && funcDecl.accessorSymbol ? funcDecl.accessorSymbol.getType() : null;
            var prevModDecl = this.checker.currentModDecl;
            if(funcDecl.isConstructor && !funcDecl.isOverload) {
                if(fnType.instanceType == null) {
                    this.checker.errorReporter.simpleError(funcDecl, "Malformed function body (is this a class named the same as an existing interface?)");
                    return funcDecl;
                }
                this.scope = fnType.instanceType.constructorScope;
                var ssb = this.scope;
                funcTable = ssb.valueMembers.allMembers;
            } else {
                if((funcDecl.isSpecialFn() && !(funcDecl.fncFlags & TypeScript.FncFlags.Signature)) || funcDecl.isOverload) {
                    funcTable = funcDecl.symbols;
                    if(!TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Static) && fnType.containedScope) {
                        this.scope = fnType.containedScope;
                    }
                } else {
                    if(funcDecl.bod) {
                        this.scope = fnType.containedScope;
                    }
                    var ssb = this.scope;
                    if(ssb && ssb.valueMembers) {
                        funcTable = ssb.valueMembers.allMembers;
                    }
                }
            }
            if(funcDecl.isConstructor && funcDecl.bod && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod)) {
                var hasBaseType = TypeScript.hasFlag(funcDecl.classDecl.type.instanceType.typeFlags, TypeScript.TypeFlags.HasBaseType);
                var noSuperCallAllowed = !hasBaseType || TypeScript.hasFlag(funcDecl.classDecl.type.instanceType.typeFlags, TypeScript.TypeFlags.HasBaseTypeOfObject);
                var superCallMustBeFirst = TypeScript.hasFlag((funcDecl.classDecl).varFlags, TypeScript.VarFlags.ClassSuperMustBeFirstCallInConstructor);
                if(noSuperCallAllowed && this.classConstructorHasSuperCall(funcDecl)) {
                    this.checker.errorReporter.simpleError(funcDecl, "Calls to 'super' constructor are not allowed in classes that either inherit directly from 'Object' or have no base class");
                } else {
                    if(hasBaseType) {
                        if(superCallMustBeFirst) {
                            if(!funcDecl.bod || !funcDecl.bod.members.length || !((funcDecl.bod.members[0].nodeType == TypeScript.NodeType.Call && (funcDecl.bod.members[0]).target.nodeType == TypeScript.NodeType.Super) || (TypeScript.hasFlag(funcDecl.bod.flags, TypeScript.ASTFlags.StrictMode) && funcDecl.bod.members.length > 1 && funcDecl.bod.members[1].nodeType == TypeScript.NodeType.Call && (funcDecl.bod.members[1]).target.nodeType == TypeScript.NodeType.Super))) {
                                this.checker.errorReporter.simpleError(funcDecl, "If a derived class contains initialized properties or constructor parameter properties, the first statement in the constructor body must be a call to the super constructor");
                            }
                        } else {
                            if(!this.classConstructorHasSuperCall(funcDecl)) {
                                this.checker.errorReporter.simpleError(funcDecl, "Constructors for derived classes must contain a call to the class's 'super' constructor");
                            }
                        }
                    }
                }
            }
            if(funcDecl.isMethod() && funcDecl.type.enclosingType) {
                var enclosingClassNode = null;
                if(funcDecl.type.enclosingType.symbol.declAST.nodeType == TypeScript.NodeType.FuncDecl) {
                    enclosingClassNode = (funcDecl.type.enclosingType.symbol.declAST).classDecl;
                } else {
                    if(funcDecl.type.enclosingType.symbol.declAST.nodeType == TypeScript.NodeType.ClassDeclaration) {
                        enclosingClassNode = funcDecl.type.enclosingType.symbol.declAST;
                    }
                }
                if(enclosingClassNode) {
                    this.thisClassNode = enclosingClassNode;
                }
            }
            if(fnType.enclosingType) {
                ; ;
                var enclosingSym = fnType.symbol.container;
                if(enclosingSym && enclosingSym.isType() && enclosingSym.getType().isClass()) {
                    enclosingSym = enclosingSym.container;
                }
                if(enclosingSym && enclosingSym.declAST && enclosingSym.declAST.nodeType == TypeScript.NodeType.ModuleDeclaration) {
                    this.checker.currentModDecl = enclosingSym.declAST;
                }
            }
            if(funcDecl.unitIndex > 0) {
                if(this.checker.units && (funcDecl.unitIndex < this.checker.units.length)) {
                    this.checker.locationInfo = this.checker.units[funcDecl.unitIndex];
                } else {
                    this.checker.locationInfo = TypeScript.unknownLocationInfo;
                }
            }
            if(fnType.enclosingType) {
                this.thisType = fnType.enclosingType;
            } else {
                this.thisType = prevThisType;
            }
            var paramLen = signature.parameters.length;
            if(!funcDecl.isConstructor && funcDecl.bod && !funcDecl.isSignature()) {
                var tmpParamScope = this.scope;
                var ssb = this.scope;
                if(!funcDecl.isMethod() && funcDecl.returnTypeAnnotation == null) {
                    if(prevScope && funcDecl.name && !funcDecl.name.isMissing()) {
                        var considerSym = prevScope.findAmbient(funcDecl.name.text, false, false);
                        if(considerSym && considerSym.declAST && considerSym.declAST.type) {
                            this.checker.setContextualType(considerSym.declAST.type, false);
                        }
                    }
                    if(this.checker.hasTargetType()) {
                        var candidateTypeContext = this.checker.getTargetTypeContext();
                        var candidateType = candidateTypeContext.contextualType;
                        if(this.checker.canContextuallyTypeFunction(candidateType, funcDecl, true)) {
                            var candidateSigs = candidateType.construct ? candidateType.construct : candidateType.call;
                            candidateTypeContext.targetSig = candidateSigs.signatures[0];
                            var candidateParams = candidateTypeContext.targetSig.parameters;
                            targetParams = candidateParams;
                            targetReturnType = candidateTypeContext.targetSig.returnType.type;
                            if(candidateTypeContext.targetSig.declAST) {
                                if(candidateTypeContext.targetSig.declAST.isConstructor) {
                                    funcDecl.isTargetTypedAsMethod = true;
                                } else {
                                    if(candidateTypeContext.targetSig.declAST.isMethod()) {
                                        funcDecl.isTargetTypedAsMethod = true;
                                    }
                                }
                            }
                            fgSym.type = candidateTypeContext.contextualType;
                            acceptedContextualType = true;
                        } else {
                            if(candidateType && funcDecl.isAccessor()) {
                                accessorType = candidateType;
                                candidateTypeContext.targetAccessorType = accessorType;
                            } else {
                                this.checker.killCurrentContextualType();
                            }
                        }
                    }
                }
                var paramTable = ssb.valueMembers;
                this.scope = new TypeScript.SymbolScopeBuilder(paramTable, null, null, null, prevScope, container);
                for(var p = 0; p < paramLen; p++) {
                    var symbol = signature.parameters[p];
                    var ast = symbol.declAST;
                    if(this.checker.hasTargetType() && (targetParams && (this.checker.getTargetTypeContext().targetSig.hasVariableArgList || p < targetParams.length))) {
                        var candidateTypeContext = this.checker.getTargetTypeContext();
                        var hasVarArgList = candidateTypeContext.targetSig.hasVariableArgList;
                        ast.type = hasVarArgList && p >= targetParams.length - 1 ? targetParams[targetParams.length - 1].getType().elementType : targetParams[p].getType();
                        ast.sym.setType(ast.type);
                        (ast.sym).typeCheckStatus = this.checker.getTypeCheckFinishedStatus();
                    } else {
                        this.typeCheck(ast);
                    }
                    if(isSetter && accessorType) {
                        ast = this.cast(ast, accessorType);
                    }
                    symbol.container = container;
                    this.checkTypePrivacy(symbol.getType(), container, function (typeName, isModuleName) {
                        return _this.functionArgumentPrivacyErrorReporter(funcDecl, p, symbol, typeName, isModuleName);
                    });
                    paramTable.publicMembers.add(symbol.name, symbol);
                }
                this.scope = tmpParamScope;
            } else {
                this.typeCheck(funcDecl.arguments);
                for(var p = 0; p < paramLen; p++) {
                    signature.parameters[p].parameter.typeLink.type = funcDecl.arguments.members[p].type;
                    this.checkTypePrivacy(signature.parameters[p].getType(), container, function (typeName, isModuleName) {
                        return _this.functionArgumentPrivacyErrorReporter(funcDecl, p, signature.parameters[p], typeName, isModuleName);
                    });
                    if((funcDecl.arguments.members[p]).parameterPropertySym) {
                        (funcDecl.arguments.members[p]).parameterPropertySym.setType(funcDecl.arguments.members[p].type);
                    }
                }
                if((funcDecl.fncFlags & TypeScript.FncFlags.IndexerMember)) {
                    if(!paramLen || paramLen > 1) {
                        this.checker.errorReporter.simpleError(funcDecl, "Index signatures may take one and only one parameter");
                    } else {
                        if(funcDecl.arguments.members[0].type == this.checker.numberType) {
                            fnType.index.flags |= TypeScript.SignatureFlags.IsNumberIndexer;
                        } else {
                            if(funcDecl.arguments.members[0].type == this.checker.stringType) {
                                fnType.index.flags |= TypeScript.SignatureFlags.IsStringIndexer;
                            } else {
                                this.checker.errorReporter.simpleError(funcDecl.arguments.members[0], "Index signatures may only take 'string' or 'number' as their parameter");
                            }
                        }
                    }
                }
            }
            if(funcDecl.bod && (!funcDecl.isSignature())) {
                if(!(funcDecl.isConstructor)) {
                    this.addFormals(container, signature, funcTable);
                } else {
                    this.addConstructorLocalArgs(funcDecl.type.symbol, funcDecl.arguments, funcTable, TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.ClassMethod));
                    if(this.thisClassNode && this.thisClassNode.extendsList) {
                        var tmpScope = this.scope;
                        var funcMembers = new TypeScript.ScopedMembers(funcTable);
                        this.scope = new TypeScript.FilteredSymbolScopeBuilder(funcMembers, prevScope, funcDecl.type.symbol, function (sym) {
                            return sym.kind() == TypeScript.SymbolKind.Parameter;
                        });
                        this.typeCheckBaseCalls(this.thisClassNode.extendsList);
                        this.scope = tmpScope;
                    }
                }
                var prevMod = this.checker.currentModDecl;
                if(funcDecl.type && funcDecl.type.symbol && !funcDecl.isMethod() && funcDecl.type.symbol.declModule) {
                    this.checker.currentModDecl = funcDecl.type.symbol.declModule;
                }
                if(acceptedContextualType) {
                    this.checker.setContextualType(null, this.checker.inProvisionalTypecheckMode());
                }
                this.typeCheck(funcDecl.bod);
                if(acceptedContextualType) {
                    this.checker.unsetContextualType();
                }
                this.checker.currentModDecl = prevMod;
                if(this.checker.checkControlFlow) {
                    var cfg = funcDecl.buildControlFlow();
                    if(this.checker.printControlFlowGraph) {
                        cfg.print(this.checker.errorReporter.outfile);
                    }
                    cfg.reportUnreachable(this.checker.errorReporter);
                    if(this.checker.checkControlFlowUseDef) {
                        cfg.useDef(this.checker.errorReporter, funcDecl.type.symbol);
                    }
                }
                if(funcDecl.isConstructor) {
                    var fns = funcDecl.scopes;
                    var fnsLen = fns.members.length;
                    var freeVars;
                    var sym;
                    var j = 0;
                    for(; j < fnsLen; j++) {
                        var fn = fns.members[j];
                        if(!fn.isSignature()) {
                            if(TypeScript.hasFlag(fn.fncFlags, TypeScript.FncFlags.Method) && (!TypeScript.hasFlag(fn.fncFlags, TypeScript.FncFlags.Static))) {
                                this.checkPromoteFreeVars(fn, funcDecl.type.symbol);
                            }
                        }
                    }
                }
            }
            this.scope = prevScope;
            this.thisFnc = prevFnc;
            this.thisClassNode = prevClassNode;
            this.enclosingFncIsMethod = prevMethodStatus;
            this.thisType = prevThisType;
            this.checker.locationInfo = prevLocationInfo;
            this.checker.currentModDecl = prevModDecl;
            signature.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();
            if(funcDecl.returnTypeAnnotation) {
                this.checkForVoidConstructor(funcDecl.returnTypeAnnotation.type, funcDecl.returnTypeAnnotation);
                if(signature.returnType.type == null) {
                    this.checker.resolveTypeLink(this.scope, signature.returnType, false);
                }
            } else {
                if(targetReturnType) {
                    signature.returnType.type = targetReturnType;
                }
            }
            if(!(fgSym.flags & TypeScript.SymbolFlags.RecursivelyReferenced) && funcDecl.returnStatementsWithExpressions.length > 0) {
                var collection = {
                    getLength: function () {
                        return funcDecl.returnStatementsWithExpressions.length;
                    },
                    setTypeAtIndex: function (index, type) {
                        funcDecl.returnStatementsWithExpressions[index].type = type;
                    },
                    getTypeAtIndex: function (index) {
                        return funcDecl.returnStatementsWithExpressions[index].type;
                    }
                };
                var bestCommonReturnType = funcDecl.returnStatementsWithExpressions[0].type;
                bestCommonReturnType = this.checker.findBestCommonType(bestCommonReturnType, null, collection, true);
                if(bestCommonReturnType) {
                    signature.returnType.type = this.checker.widenType(bestCommonReturnType);
                } else {
                    for(var i = 0; i < funcDecl.returnStatementsWithExpressions.length; i++) {
                        this.checker.errorReporter.simpleError(funcDecl.returnStatementsWithExpressions[i], "Incompatible return type");
                    }
                    signature.returnType.type = this.anyType;
                }
            }
            var onlyHasThrow = false;
            if(signature.returnType.type == null) {
                if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.HasReturnExpression)) {
                    if(this.checker.styleSettings.implicitAny) {
                        this.checker.errorReporter.styleError(funcDecl, "type implicitly set to 'any'");
                    }
                    signature.returnType.type = this.anyType;
                } else {
                    signature.returnType.type = this.voidType;
                }
            } else {
                if(signature.returnType.type == this.nullType || signature.returnType.type == this.checker.undefinedType) {
                    signature.returnType.type = this.anyType;
                } else {
                    if((signature.returnType.type != this.voidType && signature.returnType.type != this.checker.undefinedType && signature.returnType.type != this.anyType)) {
                        if(!funcDecl.isSignature() && !funcDecl.isConstructor && !TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.HasReturnExpression) && !TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.IsFatArrowFunction)) {
                            onlyHasThrow = (funcDecl.bod.members.length > 0) && (funcDecl.bod.members[0].nodeType == TypeScript.NodeType.Throw);
                            if(!onlyHasThrow) {
                                this.checker.errorReporter.simpleError(funcDecl.returnTypeAnnotation || funcDecl, "Function declared a non-void return type, but has no return expression");
                            }
                        }
                        this.checkTypePrivacy(signature.returnType.type, container, function (typeName, isModuleName) {
                            return _this.functionReturnTypePrivacyErrorReporter(funcDecl, signature, typeName, isModuleName);
                        });
                    }
                }
            }
            if(funcDecl.accessorSymbol) {
                var accessorType = funcDecl.accessorSymbol.getType();
                if(!onlyHasThrow && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor) && !TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.HasReturnExpression)) {
                    this.checker.errorReporter.simpleError(funcDecl, "Getters must return a value");
                }
                if(accessorType) {
                    if((TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor) && accessorType != signature.returnType.type) || (funcDecl.arguments.members.length > 0 && accessorType != funcDecl.arguments.members[0].type)) {
                        this.checker.errorReporter.simpleError(funcDecl, "Getter and setter types do not agree");
                    }
                } else {
                    if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor)) {
                        funcDecl.accessorSymbol.setType(signature.returnType.type);
                    } else {
                        if(funcDecl.arguments.members.length != 1) {
                            this.checker.errorReporter.simpleError(funcDecl, "Setters may have one and only one argument");
                        } else {
                            funcDecl.accessorSymbol.setType(funcDecl.arguments.members[0].type);
                        }
                    }
                }
            }
            this.typeCheckOverloadSignatures(fnType, funcDecl);
            return funcDecl;
        };
        TypeFlow.prototype.typeCheckBases = function (type) {
            var seenInterface = false;
            var bases = type.extendsList;
            var baseLinks = type.extendsTypeLinks;
            if(bases) {
                var len = bases.length;
                if(len > 0) {
                    type.typeFlags |= TypeScript.TypeFlags.HasBaseType;
                }
                for(var i = 0; i < len; i++) {
                    if(bases[i] == this.checker.anyType) {
                        baseLinks[i].type = null;
                        var oldErrors = this.checker.errorReporter.getCapturedErrors();
                        TypeScript.CompilerDiagnostics.assert(oldErrors.length == 0, "There shouldnt be any contextual errors when typechecking base type names");
                        this.checker.errorReporter.pushToErrorSink = true;
                        bases[i] = this.checker.resolveBaseTypeLink(baseLinks[i], type.containedScope);
                        this.checker.errorReporter.pushToErrorSink = false;
                        this.checker.errorReporter.freeCapturedErrors();
                    }
                    var base = bases[i];
                    var baseRef = baseLinks[i].ast;
                    var baseTypeOfObject = base.symbol && base.symbol.name == "Object" && base.symbol.container == this.checker.gloMod;
                    if(baseTypeOfObject) {
                        type.typeFlags |= TypeScript.TypeFlags.HasBaseTypeOfObject;
                    }
                    if(base.isClassInstance()) {
                        if(!(type.isClassInstance())) {
                            this.checker.errorReporter.simpleError(baseRef, "Interface base type must be interface");
                        } else {
                            if(seenInterface) {
                                this.checker.errorReporter.simpleError(baseRef, "Class may not follow interface as base type");
                            }
                        }
                    } else {
                        if(base.isModuleType()) {
                            this.checker.errorReporter.simpleError(baseRef, "Types may not be derived from module types");
                        } else {
                            if(base.members) {
                                if(!seenInterface) {
                                    seenInterface = true;
                                }
                            } else {
                                if(!(type.isClassInstance())) {
                                    this.checker.errorReporter.simpleError(baseRef, "Interface base type must be interface");
                                } else {
                                    this.checker.errorReporter.simpleError(baseRef, "Base type must be interface or class");
                                }
                                break;
                            }
                        }
                    }
                }
            }
        };
        TypeFlow.prototype.checkMembersImplementInterfaces = function (implementingType) {
            var instanceType = implementingType.getInstanceType();
            if(instanceType.implementsList) {
                var len = instanceType.implementsList.length;
                for(var i = 0; i < len; i++) {
                    var interfaceType = instanceType.implementsList[i];
                    var comparisonInfo = new TypeScript.TypeComparisonInfo();
                    if(!this.checker.sourceIsSubtypeOfTarget(instanceType, interfaceType, comparisonInfo)) {
                        var emsg = "Class '" + instanceType.getTypeName() + "' declares interface '" + interfaceType.getTypeName() + "' but does not implement it";
                        if(!comparisonInfo.message) {
                            this.checker.errorReporter.simpleErrorFromSym(instanceType.symbol, emsg);
                        } else {
                            this.checker.errorReporter.simpleErrorFromSym(instanceType.symbol, emsg + ": " + comparisonInfo.message);
                        }
                    }
                }
            }
        };
        TypeFlow.prototype.typeCheckBaseCalls = function (bases) {
            if(bases == null) {
                return;
            }
            var basesLen = bases.members.length;
            for(var i = 0; i < basesLen; i++) {
                var baseExpr = bases.members[i];
                var baseSymbol = null;
                if(baseExpr.nodeType == TypeScript.NodeType.Call) {
                    this.typeCheckNew(baseExpr);
                }
            }
        };
        TypeFlow.prototype.assertUniqueNamesInBaseTypes = function (names, type, classDecl, checkUnique) {
            var _this = this;
            if(type) {
                if(type.members) {
                    type.members.publicMembers.map(function (key, s, c) {
                        var sym = s;
                        var dup = names.lookup(sym.name);
                        if(dup) {
                            if(checkUnique) {
                                _this.checker.errorReporter.simpleError(classDecl, "duplicate member name in bases for " + classDecl.name.actualText + ": " + type.symbol.name + " and " + dup.container.name + " both contain member with name " + sym.name);
                            }
                        } else {
                            names.add(sym.name, sym);
                        }
                    }, null);
                }
                if(type.extendsList) {
                    var len = type.extendsList.length;
                    for(var i = 0; i < len; i++) {
                        if(!(type.extendsList[i].symbol.flags & TypeScript.SymbolFlags.RecursivelyReferenced)) {
                            this.assertUniqueNamesInBaseTypes(names, type.extendsList[i], classDecl, checkUnique);
                        }
                    }
                }
            }
        };
        TypeFlow.prototype.checkBaseTypeMemberInheritance = function (derivedType, derivedTypeDecl) {
            var _this = this;
            var instanceType = derivedType.getInstanceType();
            if(instanceType.extendsList == null) {
                return;
            }
            var len = instanceType.extendsList.length;
            if(len > 0) {
                var names = new TypeScript.StringHashTable();
                if(instanceType.isClassInstance()) {
                    for(var i = 0; i < len; i++) {
                        this.assertUniqueNamesInBaseTypes(names, instanceType.extendsList[i], derivedTypeDecl, i > 0);
                    }
                }
                if(instanceType.members) {
                    instanceType.members.publicMembers.map(function (key, s, c) {
                        var sym = s;
                        for(var j = 0; j < len; j++) {
                            var base = instanceType.extendsList[j];
                            if(base.memberScope == null) {
                                _this.checker.errorReporter.simpleError(derivedTypeDecl, "Base type '" + base.symbol.name + "' lacks an implementation.");
                            } else {
                                var bSym = base.memberScope.find(sym.name, false, false);
                                if(bSym) {
                                    var aType = sym.getType();
                                    var bType = bSym.getType();
                                    if(!(_this.checker.sourceIsSubtypeOfTarget(aType, bType))) {
                                        _this.checker.errorReporter.simpleErrorFromSym(sym, "Type of overridden member '" + sym.name + "' is not subtype of original member defined by type '" + bSym.container.name + "'");
                                    } else {
                                        if((sym.kind() == TypeScript.SymbolKind.Type) && (bSym.kind() == TypeScript.SymbolKind.Field)) {
                                            _this.checker.errorReporter.simpleErrorFromSym(sym, "Cannot override field '" + sym.name + "' with method");
                                        }
                                    }
                                }
                            }
                        }
                    }, null);
                }
            }
        };
        TypeFlow.prototype.typeCheckClass = function (classDecl) {
            var typeSymbol = classDecl.type.symbol;
            if(typeSymbol.typeCheckStatus == TypeScript.TypeCheckStatus.Finished) {
                return classDecl;
            } else {
                if(typeSymbol.typeCheckStatus == TypeScript.TypeCheckStatus.Started) {
                    return classDecl;
                } else {
                    typeSymbol.typeCheckStatus = TypeScript.TypeCheckStatus.Started;
                    this.checker.addStartedPTO(typeSymbol);
                }
            }
            var prevScope = this.scope;
            var svClassNode = this.thisClassNode;
            this.thisClassNode = classDecl;
            var classType = classDecl.type;
            this.typeCheckBases(classType.instanceType);
            this.typeCheckBaseListPrivacy(classDecl.extendsList, typeSymbol, true);
            this.typeCheckBaseListPrivacy(classDecl.implementsList, typeSymbol, false);
            var prevThisType = this.thisType;
            this.thisType = classType.instanceType;
            this.scope = classType.instanceType.containedScope;
            if(classDecl.constructorDecl) {
                this.scope = classType.instanceType.constructorScope;
                var ssb = this.scope;
                var funcTable = ssb.valueMembers.allMembers;
                this.addConstructorLocalArgs(classDecl.constructorDecl.type.symbol, classDecl.constructorDecl.arguments, funcTable, true);
            }
            this.typeCheck(classDecl.members);
            typeSymbol.typeCheckStatus = TypeScript.TypeCheckStatus.Finished;
            this.checkBaseTypeMemberInheritance(classType, classDecl);
            this.checkMembersImplementInterfaces(classType);
            this.typeCheckOverloadSignatures(classType, classDecl);
            this.typeCheckOverloadSignatures(classType.instanceType, classDecl);
            if(!classDecl.constructorDecl) {
                if(classDecl.extendsList && classDecl.extendsList.members.length && classDecl.extendsList.members[0].type && classDecl.extendsList.members[0].type.symbol.type.isClass()) {
                    TypeScript.cloneParentConstructGroupForChildType(classDecl.type, classDecl.extendsList.members[0].type.symbol.type);
                }
            }
            this.thisType = prevThisType;
            this.thisClassNode = svClassNode;
            this.scope = prevScope;
            return classDecl;
        };
        TypeFlow.prototype.typeCheckOverloadSignatures = function (type, ast) {
            if(type.call) {
                type.call.typeCheck(this.checker, ast, type.construct != null);
            }
            if(type.construct) {
                type.construct.typeCheck(this.checker, ast, false);
            }
            if(type.index) {
                type.index.typeCheck(this.checker, ast, false);
            }
        };
        TypeFlow.prototype.typeCheckInterface = function (interfaceDecl) {
            this.typeCheckBases(interfaceDecl.type);
            this.typeCheckBaseListPrivacy(interfaceDecl.extendsList, interfaceDecl.type.symbol, true);
            this.typeCheck(interfaceDecl.members);
            this.checkBaseTypeMemberInheritance(interfaceDecl.type, interfaceDecl);
            if(interfaceDecl.extendsList) {
                for(var i = 0; i < interfaceDecl.extendsList.members.length; i++) {
                    if(interfaceDecl.extendsList.members[i].type.call) {
                        if(interfaceDecl.type.call) {
                            interfaceDecl.type.call.signatures = interfaceDecl.type.call.signatures.concat(interfaceDecl.extendsList.members[i].type.call.signatures);
                        } else {
                            interfaceDecl.type.call = interfaceDecl.extendsList.members[i].type.call;
                        }
                    }
                    if(interfaceDecl.extendsList.members[i].type.construct) {
                        if(interfaceDecl.type.construct) {
                            interfaceDecl.type.construct.signatures = interfaceDecl.type.construct.signatures.concat(interfaceDecl.extendsList.members[i].type.construct.signatures);
                        } else {
                            interfaceDecl.type.construct = interfaceDecl.extendsList.members[i].type.construct;
                        }
                    }
                    if(interfaceDecl.extendsList.members[i].type.index) {
                        if(interfaceDecl.type.index) {
                            interfaceDecl.type.index.signatures = interfaceDecl.type.index.signatures.concat(interfaceDecl.extendsList.members[i].type.index.signatures);
                        } else {
                            interfaceDecl.type.index = interfaceDecl.extendsList.members[i].type.index;
                        }
                    }
                }
            }
            return interfaceDecl;
        };
        TypeFlow.prototype.typeCheckImportDecl = function (importDecl) {
            var mod = importDecl.alias.type;
            var sym = null;
            var prevInImportTC = this.inImportTypeCheck;
            this.inImportTypeCheck = true;
            this.typeCheck(importDecl.alias);
            mod = importDecl.alias.type;
            if(mod == null) {
                this.checker.errorReporter.simpleError(importDecl.alias, "Could not resolve module alias '" + importDecl.id.actualText + "'");
                mod = this.checker.anyType;
                (importDecl.id.sym).type = mod;
            }
            importDecl.id.type = mod;
            sym = mod.symbol;
            if(!mod.isModuleType()) {
                this.checker.errorReporter.simpleError(importDecl.alias, "A module cannot be aliased to a non-module type");
            } else {
                sym.type = mod;
                if(this.checker.typeFlow.currentScript && this.checker.typeFlow.currentScript.topLevelMod && this.checker.typeFlow.currentScript.topLevelMod.mod) {
                    this.checker.typeFlow.currentScript.topLevelMod.mod.importedModules.push(importDecl);
                }
                (importDecl.id.sym).type = mod;
                if(mod.symbol && mod.symbol.declAST) {
                    (mod.symbol.declAST).modFlags &= ~TypeScript.ModuleFlags.ShouldEmitModuleDecl;
                }
            }
            this.inImportTypeCheck = prevInImportTC;
            return importDecl;
        };
        TypeFlow.prototype.typeCheckModule = function (moduleDecl) {
            if(!moduleDecl.mod) {
                return moduleDecl;
            }
            if(this.currentScript) {
                this.currentScript.requiresGlobal = true;
            }
            var mod = moduleDecl.mod;
            var sym = null;
            var prevScope = this.scope;
            var prevThisType = this.thisType;
            var prevCurrentModDecl = this.checker.currentModDecl;
            this.checker.currentModDecl = moduleDecl;
            this.thisType = null;
            this.scope = mod.containedScope;
            this.typeCheck(moduleDecl.members);
            sym = mod.symbol;
            this.checker.currentModDecl = prevCurrentModDecl;
            this.thisType = prevThisType;
            this.scope = prevScope;
            moduleDecl.type = mod;
            if(sym) {
                sym.typeCheckStatus = TypeScript.TypeCheckStatus.Finished;
            }
            return moduleDecl;
        };
        TypeFlow.prototype.typeCheckFor = function (forStmt) {
            forStmt.init = this.typeCheck(forStmt.init);
            this.nestingLevel++;
            forStmt.cond = this.typeCheck(forStmt.cond);
            this.typeCheckCondExpr(forStmt.cond);
            forStmt.incr = this.typeCheck(forStmt.incr);
            this.nestingLevel--;
            forStmt.body = this.typeCheck(forStmt.body);
            this.typeCheckCompoundStmtBlock(forStmt.body, "for statement");
            forStmt.type = this.voidType;
            return forStmt;
        };
        TypeFlow.prototype.typeCheckWith = function (withStmt) {
            if(this.checker.errorsOnWith) {
                this.checker.errorReporter.simpleError(withStmt.expr, "All symbols within a 'with' block will be typed as 'any'");
            }
            withStmt.expr = this.typeCheck(withStmt.expr);
            this.checker.inWith = true;
            withStmt.body = this.typeCheck(withStmt.body);
            this.typeCheckCompoundStmtBlock(withStmt.body, "with statement");
            this.checker.inWith = false;
            return withStmt;
        };
        TypeFlow.prototype.typeCheckForIn = function (forInStmt) {
            forInStmt.obj = this.typeCheck(forInStmt.obj);
            forInStmt.lval = this.cast(this.typeCheck(forInStmt.lval), this.checker.stringType);
            if(forInStmt.lval.nodeType == TypeScript.NodeType.VarDecl) {
                var varDecl = forInStmt.lval;
                if(varDecl.typeExpr) {
                    this.checker.errorReporter.simpleError(varDecl, "Variable declarations for for/in expressions may not contain a type annotation");
                }
                if(varDecl.sym) {
                    varDecl.sym.setType(this.checker.stringType);
                }
            }
            forInStmt.body = this.typeCheck(forInStmt.body);
            this.typeCheckCompoundStmtBlock(forInStmt.body, "for in statement");
            return forInStmt;
        };
        TypeFlow.prototype.typeCheckWhile = function (whileStmt) {
            whileStmt.cond = this.typeCheck(whileStmt.cond);
            this.typeCheckCondExpr(whileStmt.cond);
            whileStmt.body = this.typeCheck(whileStmt.body);
            this.typeCheckCompoundStmtBlock(whileStmt.body, "while statement");
            whileStmt.type = this.voidType;
            return whileStmt;
        };
        TypeFlow.prototype.typeCheckDoWhile = function (doWhileStmt) {
            doWhileStmt.cond = this.typeCheck(doWhileStmt.cond);
            this.typeCheckCondExpr(doWhileStmt.cond);
            doWhileStmt.body = this.typeCheck(doWhileStmt.body);
            this.typeCheckCompoundStmtBlock(doWhileStmt.body, "do while statement");
            doWhileStmt.type = this.voidType;
            return doWhileStmt;
        };
        TypeFlow.prototype.typeCheckCondExpr = function (cond) {
            if(this.checker.styleSettings.assignmentInCond) {
                if((cond !== null) && (cond.nodeType >= TypeScript.NodeType.Asg) && (cond.nodeType <= TypeScript.NodeType.LastAsg)) {
                    this.checker.errorReporter.simpleError(cond, "top-level assignment statement in conditional expression");
                }
            }
        };
        TypeFlow.prototype.typeCheckCompoundStmtBlock = function (stmts, stmtType) {
            if(this.checker.styleSettings.blockInCompoundStmt && stmts) {
                if(stmts.nodeType != TypeScript.NodeType.Block) {
                    this.checker.errorReporter.styleError(stmts, stmtType + " requires a block");
                }
            }
        };
        TypeFlow.prototype.typeCheckIf = function (ifStmt) {
            ifStmt.cond = this.typeCheck(ifStmt.cond);
            this.typeCheckCondExpr(ifStmt.cond);
            ifStmt.thenBod = this.typeCheck(ifStmt.thenBod);
            ifStmt.elseBod = this.typeCheck(ifStmt.elseBod);
            this.typeCheckCompoundStmtBlock(ifStmt.thenBod, "if statement");
            this.typeCheckCompoundStmtBlock(ifStmt.elseBod, "if statement");
            ifStmt.type = this.voidType;
            return ifStmt;
        };
        TypeFlow.prototype.typeFromAccessorFuncDecl = function (funcDecl) {
            if(!funcDecl.isAccessor()) {
                return null;
            }
            if(TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.GetAccessor)) {
                return funcDecl.type.call.signatures[0].returnType.type;
            } else {
                return funcDecl.type.call.signatures[0].parameters[0].getType();
            }
        };
        TypeFlow.prototype.typeCheckObjectLit = function (objectLit) {
            var resultType = new TypeScript.Type();
            resultType.symbol = new TypeScript.TypeSymbol(this.checker.anon, objectLit.minChar, objectLit.limChar - objectLit.minChar, this.checker.locationInfo.unitIndex, resultType);
            resultType.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
            resultType.memberScope = new TypeScript.SymbolTableScope(resultType.members, null, null, null, null);
            var aggScope = new TypeScript.SymbolAggregateScope(resultType.symbol);
            aggScope.addParentScope(resultType.memberScope);
            aggScope.addParentScope(this.scope);
            resultType.containedScope = aggScope;
            var memberDecls = objectLit.operand;
            var prevThisType = this.thisType;
            var acceptTargetType = false;
            var targetType = null;
            if(this.checker.hasTargetType()) {
                targetType = this.checker.getTargetTypeContext().contextualType;
                if(targetType && targetType.symbol && !this.checker.typeStatusIsFinished(targetType.symbol.typeCheckStatus)) {
                    if(targetType.symbol.declAST) {
                        this.typeCheck(targetType.symbol.declAST);
                    }
                }
                acceptTargetType = true;
            }
            if(memberDecls) {
                for(var i = 0, len = memberDecls.members.length; i < len; i++) {
                    var binex = memberDecls.members[i];
                    var id = binex.operand1;
                    var text;
                    var targetMember = null;
                    var fieldSymbol = null;
                    if(id.nodeType == TypeScript.NodeType.Name) {
                        text = (id).text;
                    } else {
                        if(id.nodeType == TypeScript.NodeType.QString) {
                            var idText = (id).text;
                            text = idText.substring(1, idText.length - 1);
                        } else {
                            this.checker.errorReporter.simpleError(objectLit, "malformed object literal");
                            resultType = this.anyType;
                            break;
                        }
                    }
                    if(acceptTargetType && targetType.memberScope) {
                        targetMember = targetType.memberScope.find(text, false, false);
                    }
                    if(binex.operand2.nodeType == TypeScript.NodeType.FuncDecl && (binex.operand2).isAccessor()) {
                        var funcDecl = binex.operand2;
                        var accessorSym = resultType.members.publicMembers.lookup(text);
                        accessorSym = this.checker.createAccessorSymbol(funcDecl, accessorSym, resultType, true, false, resultType.memberScope, null);
                        funcDecl.accessorSymbol = accessorSym;
                        fieldSymbol = accessorSym;
                        if(id.nodeType == TypeScript.NodeType.Name) {
                            (id).sym = accessorSym;
                        }
                    }
                    this.checker.typeCheckWithContextualType(acceptTargetType && targetMember ? targetMember.getType() : null, false, acceptTargetType, binex.operand2);
                    if(acceptTargetType && targetMember) {
                        if((binex.operand2.type == this.anyType || this.checker.sourceIsAssignableToTarget(binex.operand2.type, targetMember.getType())) || (binex.operand2.nodeType == TypeScript.NodeType.FuncDecl && (binex.operand2).isAccessor() && this.typeFromAccessorFuncDecl(binex.operand2) == targetMember.getType())) {
                            binex.operand1.type = targetMember.getType();
                        }
                    } else {
                        binex.operand2.type = binex.operand2.type == this.checker.undefinedType ? this.anyType : binex.operand2.type;
                    }
                    if(fieldSymbol == null) {
                        var memberType = binex.operand2.type;
                        var field = new TypeScript.ValueLocation();
                        fieldSymbol = new TypeScript.FieldSymbol(text, id.minChar, this.checker.locationInfo.unitIndex, true, field);
                        fieldSymbol.flags |= TypeScript.SymbolFlags.Property;
                        field.symbol = fieldSymbol;
                        fieldSymbol.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();
                        field.typeLink = new TypeScript.TypeLink();
                        field.typeLink.type = memberType;
                        resultType.members.publicMembers.add(text, fieldSymbol);
                    }
                    fieldSymbol.isObjectLitField = true;
                }
            }
            this.thisType = prevThisType;
            objectLit.type = resultType;
            if(targetType) {
                objectLit.targetType = targetType;
            }
        };
        TypeFlow.prototype.typeCheckArrayLit = function (arrayLit) {
            var elements = arrayLit.operand;
            var elementType = this.anyType;
            var targetElementType = null;
            var comparisonInfo = new TypeScript.TypeComparisonInfo();
            comparisonInfo.onlyCaptureFirstError = true;
            if(this.checker.hasTargetType()) {
                var targetType = this.checker.getTargetTypeContext().contextualType;
                if(targetType.elementType) {
                    targetElementType = targetType.elementType;
                }
            }
            if(elements) {
                var prevInArrayElemTypeCheck = this.inArrayElementTypeCheck;
                this.inArrayElementTypeCheck = true;
                this.checker.typeCheckWithContextualType(targetElementType, this.checker.inProvisionalTypecheckMode(), targetElementType != null, elements);
                this.inArrayElementTypeCheck = prevInArrayElemTypeCheck;
                elementType = elements.members[0].type;
                var collection = {
                    getLength: function () {
                        return elements.members.length;
                    },
                    setTypeAtIndex: function (index, type) {
                        elements.members[index].type = type;
                    },
                    getTypeAtIndex: function (index) {
                        return elements.members[index].type;
                    }
                };
                elementType = this.checker.findBestCommonType(elementType, targetElementType, collection, false, comparisonInfo);
                if(elementType == this.checker.undefinedType || (!prevInArrayElemTypeCheck && elementType == this.nullType)) {
                    elementType = this.anyType;
                }
            }
            if(!elementType) {
                var emsg = "Incompatible types in array literal expression";
                if(!comparisonInfo.message) {
                    this.checker.errorReporter.simpleError(arrayLit, emsg);
                } else {
                    this.checker.errorReporter.simpleError(arrayLit, emsg + ": " + comparisonInfo.message);
                }
                elementType = this.anyType;
            } else {
                if(targetElementType) {
                    if(this.checker.sourceIsAssignableToTarget(elementType, targetElementType)) {
                        elementType = targetElementType;
                    }
                }
            }
            arrayLit.type = this.checker.makeArrayType(elementType);
        };
        TypeFlow.prototype.checkForVoidConstructor = function (type, ast) {
            if(type && type.construct && type.construct.signatures.length > 0) {
                for(var i = 0; i < type.construct.signatures.length; i++) {
                    if(type.construct.signatures[i].returnType.type == this.checker.voidType) {
                        this.checker.errorReporter.simpleError(ast, "Constructors may not have a return type of 'void'");
                        break;
                    }
                }
            }
        };
        TypeFlow.prototype.typeCheckReturn = function (returnStmt) {
            if(this.thisFnc) {
                var targetType = null;
                if(this.checker.hasTargetType()) {
                    var tcContext = this.checker.getTargetTypeContext();
                    var accessorType = tcContext.targetAccessorType;
                    if(accessorType) {
                        targetType = accessorType;
                    } else {
                        var targetSig = this.checker.getTargetTypeContext().targetSig;
                        if(targetSig && targetSig.returnType.type != this.voidType) {
                            targetType = targetSig.returnType.type;
                        }
                    }
                }
                if(returnStmt.returnExpression) {
                    this.thisFnc.fncFlags |= TypeScript.FncFlags.HasReturnExpression;
                    if(targetType == null && this.thisFnc.returnTypeAnnotation && this.thisFnc.returnTypeAnnotation.type && this.thisFnc.returnTypeAnnotation.type != this.voidType) {
                        targetType = this.thisFnc.returnTypeAnnotation.type;
                    }
                    this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), targetType != null, returnStmt.returnExpression);
                    var expectedReturnType = (this.thisFnc.returnTypeAnnotation && this.thisFnc.returnTypeAnnotation.type) ? this.thisFnc.returnTypeAnnotation.type : targetType;
                    if(expectedReturnType) {
                        if(expectedReturnType == this.voidType && returnStmt.returnExpression.type != this.voidType) {
                            this.checker.errorReporter.simpleError(returnStmt, "Return with value expression in void function");
                            returnStmt.type = returnStmt.returnExpression.type;
                        } else {
                            returnStmt.returnExpression = this.cast(returnStmt.returnExpression, expectedReturnType);
                            returnStmt.type = expectedReturnType;
                        }
                    } else {
                        if(targetType) {
                            if(returnStmt.returnExpression.type != this.voidType) {
                                returnStmt.returnExpression = this.cast(returnStmt.returnExpression, targetType);
                            } else {
                                returnStmt.returnExpression.type = targetType;
                            }
                        }
                        returnStmt.type = returnStmt.returnExpression.type;
                    }
                    this.thisFnc.returnStatementsWithExpressions[this.thisFnc.returnStatementsWithExpressions.length] = returnStmt;
                } else {
                    returnStmt.type = targetType == null ? this.checker.voidType : targetType;
                }
            }
            return returnStmt;
        };
        TypeFlow.prototype.typeCheckInstOf = function (ast) {
            var binex = ast;
            binex.operand1 = this.typeCheck(binex.operand1);
            binex.operand2 = this.typeCheck(binex.operand2);
            if(!((binex.operand1.type == this.checker.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand1.type, this.objectInterfaceType)) && (binex.operand2.type == this.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand2.type, this.functionInterfaceType)))) {
                this.checker.errorReporter.simpleError(ast, "The instanceof operator requires the left operand to be of type Any or an object type, and the right operand to be of type Any or a subtype of the Function interface type");
            }
            binex.type = this.booleanType;
            return binex;
        };
        TypeFlow.prototype.typeCheckCommaOperator = function (ast) {
            var binex = ast;
            binex.operand1 = this.typeCheck(binex.operand1);
            binex.operand2 = this.typeCheck(binex.operand2);
            binex.type = binex.operand2.type;
            return binex;
        };
        TypeFlow.prototype.typeCheckLogOr = function (binex) {
            binex.operand1 = this.typeCheck(binex.operand1);
            binex.operand2 = this.typeCheck(binex.operand2);
            var leftType = binex.operand1.type;
            var rightType = binex.operand2.type;
            if(leftType == this.checker.anyType || rightType == this.checker.anyType) {
                binex.type = this.checker.anyType;
            } else {
                if(leftType == this.checker.booleanType) {
                    if(rightType == this.checker.booleanType) {
                        binex.type = this.checker.booleanType;
                    } else {
                        binex.type = this.checker.anyType;
                    }
                } else {
                    if(leftType == this.checker.numberType) {
                        if(rightType == this.checker.numberType) {
                            binex.type = this.checker.numberType;
                        } else {
                            binex.type = this.checker.anyType;
                        }
                    } else {
                        if(leftType == this.checker.stringType) {
                            if(rightType == this.checker.stringType) {
                                binex.type = this.checker.stringType;
                            } else {
                                binex.type = this.checker.anyType;
                            }
                        } else {
                            if(this.checker.sourceIsSubtypeOfTarget(leftType, rightType)) {
                                binex.type = rightType;
                            } else {
                                if(this.checker.sourceIsSubtypeOfTarget(rightType, leftType)) {
                                    binex.type = leftType;
                                } else {
                                    binex.type = this.checker.anyType;
                                }
                            }
                        }
                    }
                }
            }
            return binex;
        };
        TypeFlow.prototype.typeCheckLogAnd = function (binex) {
            binex.operand1 = this.typeCheck(binex.operand1);
            binex.operand2 = this.typeCheck(binex.operand2);
            binex.type = binex.operand2.type;
            return binex;
        };
        TypeFlow.prototype.tryAddCandidates = function (signature, actuals, exactCandidates, conversionCandidates, comparisonInfo) {
            var lowerBound = signature.nonOptionalParameterCount;
            var upperBound = signature.parameters.length;
            var formalLen = lowerBound;
            var acceptable = false;
            if((actuals.length >= lowerBound) && (signature.hasVariableArgList || actuals.length <= upperBound)) {
                formalLen = (signature.hasVariableArgList ? signature.parameters.length : actuals.length);
                acceptable = true;
            }
            var repeatType = null;
            if(acceptable || signature.hasVariableArgList) {
                if(signature.hasVariableArgList) {
                    formalLen -= 1;
                    repeatType = (signature.parameters[formalLen]).parameter.typeLink.type;
                    repeatType = repeatType.elementType;
                    acceptable = actuals.length >= formalLen;
                }
                var len = actuals.length;
                var exact = acceptable;
                var convert = acceptable;
                for(var i = 0; i < len; i++) {
                    var typeA;
                    if(i < formalLen) {
                        typeA = (signature.parameters[i]).parameter.typeLink.type;
                    } else {
                        typeA = repeatType;
                    }
                    var typeB = actuals[i];
                    if(!typeA || !typeB || !(this.checker.typesAreIdentical(typeA, typeB))) {
                        exact = false;
                    }
                    if(!this.checker.sourceIsAssignableToTarget(typeB, typeA, comparisonInfo)) {
                        convert = false;
                    }
                    if(!(exact || convert)) {
                        break;
                    }
                }
                if(exact) {
                    exactCandidates[exactCandidates.length] = signature;
                } else {
                    if(convert && (exactCandidates.length == 0)) {
                        conversionCandidates[conversionCandidates.length] = signature;
                    }
                }
            }
        };
        TypeFlow.prototype.resolveOverload = function (application, group) {
            var rd = this.resolutionDataCache.getResolutionData();
            var actuals = rd.actuals;
            var exactCandidates = rd.exactCandidates;
            var conversionCandidates = rd.conversionCandidates;
            var candidate = null;
            var hasOverloads = group.signatures.length > 1;
            var comparisonInfo = new TypeScript.TypeComparisonInfo();
            var args = null;
            var target = null;
            if(application.nodeType == TypeScript.NodeType.Call || application.nodeType == TypeScript.NodeType.New) {
                var callEx = application;
                args = callEx.arguments;
                target = callEx.target;
                if(callEx.arguments) {
                    var len = callEx.arguments.members.length;
                    for(var i = 0; i < len; i++) {
                        actuals[i] = callEx.arguments.members[i].type;
                    }
                }
            } else {
                if(application.nodeType == TypeScript.NodeType.Index) {
                    var binExp = application;
                    target = binExp.operand1;
                    args = new TypeScript.ASTList();
                    args.members[0] = binExp.operand2;
                    actuals[0] = binExp.operand2.type;
                }
            }
            for(var j = 0, groupLen = group.signatures.length; j < groupLen; j++) {
                var signature = group.signatures[j];
                if(hasOverloads && signature == group.definitionSignature && !this.checker.canCallDefinitionSignature) {
                    continue;
                }
                if(!signature.returnType.type && signature.declAST && (signature.typeCheckStatus != TypeScript.TypeCheckStatus.Finished)) {
                    this.typeCheckFunction(signature.declAST);
                }
                this.tryAddCandidates(signature, actuals, exactCandidates, conversionCandidates, comparisonInfo);
            }
            if(exactCandidates.length == 0) {
                var applicableCandidates = this.checker.getApplicableSignatures(conversionCandidates, args, comparisonInfo);
                if(applicableCandidates.length > 0) {
                    var candidateInfo = this.checker.findMostApplicableSignature(applicableCandidates, args);
                    if(candidateInfo.ambiguous) {
                        this.checker.errorReporter.simpleError(target, "Ambiguous call expression - could not choose overload");
                    }
                    candidate = candidateInfo.sig;
                } else {
                    var emsg = "Supplied parameters do not match any signature of call target";
                    if(comparisonInfo.message) {
                        this.checker.errorReporter.simpleError(target, emsg + ":\n\t" + comparisonInfo.message);
                    } else {
                        this.checker.errorReporter.simpleError(target, emsg);
                    }
                }
            } else {
                if(exactCandidates.length > 1) {
                    var applicableSigs = [];
                    for(var i = 0; i < exactCandidates.length; i++) {
                        applicableSigs[i] = {
                            signature: exactCandidates[i],
                            hadProvisionalErrors: false
                        };
                    }
                    var candidateInfo = this.checker.findMostApplicableSignature(applicableSigs, args);
                    if(candidateInfo.ambiguous) {
                        this.checker.errorReporter.simpleError(target, "Ambiguous call expression - could not choose overload");
                    }
                    candidate = candidateInfo.sig;
                } else {
                    candidate = exactCandidates[0];
                }
            }
            this.resolutionDataCache.returnResolutionData(rd);
            return candidate;
        };
        TypeFlow.prototype.typeCheckNew = function (ast) {
            var callEx = ast;
            callEx.target = this.typeCheck(callEx.target);
            var target = callEx.target;
            if(target.type.construct || target.type.call) {
                this.preTypeCheckCallArgs(callEx.arguments);
            } else {
                callEx.arguments = this.typeCheck(callEx.arguments);
            }
            if(target.type == this.anyType) {
                callEx.type = this.anyType;
                callEx.arguments = this.typeCheck(callEx.arguments);
            } else {
                if(target.type.construct) {
                    var signature = this.resolveOverload(callEx, target.type.construct);
                    if(signature == null) {
                        callEx.type = this.anyType;
                    } else {
                        if(signature.returnType.type == this.voidType) {
                            callEx.type = this.anyType;
                            callEx.signature = signature;
                        } else {
                            callEx.type = signature.returnType.type;
                            callEx.signature = signature;
                        }
                    }
                } else {
                    if(target.type.call) {
                        var signature = this.resolveOverload(callEx, target.type.call);
                        if(signature == null) {
                            callEx.type = this.anyType;
                        } else {
                            if((signature.returnType.type == this.voidType) || (signature.returnType.type == this.anyType)) {
                                callEx.type = this.anyType;
                                callEx.signature = signature;
                            } else {
                                this.checker.errorReporter.simpleError(callEx.target, "new expression only valid on constructors");
                            }
                        }
                    } else {
                        if(target.type.elementType) {
                            callEx.type = target.type;
                        } else {
                            this.checker.errorReporter.invalidCall(callEx, callEx.nodeType, this.scope);
                            callEx.type = this.anyType;
                        }
                    }
                }
            }
            this.postTypeCheckCallArgs(callEx);
            return callEx;
        };
        TypeFlow.prototype.preTypeCheckCallArgs = function (args) {
            if(!args) {
                return;
            }
            for(var i = 0; i < args.members.length; i++) {
                switch(args.members[i].nodeType) {
                    case TypeScript.NodeType.FuncDecl:
                    case TypeScript.NodeType.ObjectLit:
                    case TypeScript.NodeType.ArrayLit: {
                        continue;

                    }
                    default: {
                        this.typeCheck(args.members[i]);
                        break;

                    }
                }
            }
        };
        TypeFlow.prototype.postTypeCheckCallArgs = function (callEx) {
            var acceptedTargetType = false;
            var i = 0;
            if(callEx.target && callEx.target.type && callEx.signature && callEx.arguments) {
                var sig = callEx.signature;
                if(sig && callEx.arguments.members.length >= sig.nonOptionalParameterCount) {
                    acceptedTargetType = true;
                    var targetType = null;
                    var nonVarArgFormalParamLength = sig.hasVariableArgList ? sig.parameters.length - 1 : sig.parameters.length;
                    var nonVarArgActualParamLength = callEx.arguments.members.length < nonVarArgFormalParamLength ? callEx.arguments.members.length : nonVarArgFormalParamLength;
                    for(i = 0; i < nonVarArgActualParamLength; i++) {
                        targetType = sig.parameters[i].getType();
                        switch(callEx.arguments.members[i].nodeType) {
                            case TypeScript.NodeType.FuncDecl:
                            case TypeScript.NodeType.ObjectLit:
                            case TypeScript.NodeType.ArrayLit: {
                                this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), !sig.parameters[i].declAST.isParenthesized, callEx.arguments.members[i]);
                                break;

                            }
                        }
                    }
                    if(sig.hasVariableArgList) {
                        var varArgParamIndex = sig.nonOptionalParameterCount - 1;
                        targetType = sig.parameters[varArgParamIndex].getType();
                        if(targetType) {
                            targetType = targetType.elementType;
                        }
                        var isParenthesized = !sig.parameters[varArgParamIndex].declAST.isParenthesized;
                        for(i = nonVarArgActualParamLength; i < callEx.arguments.members.length; i++) {
                            switch(callEx.arguments.members[i].nodeType) {
                                case TypeScript.NodeType.FuncDecl:
                                case TypeScript.NodeType.ObjectLit:
                                case TypeScript.NodeType.ArrayLit: {
                                    this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), isParenthesized, callEx.arguments.members[i]);
                                    break;

                                }
                            }
                        }
                    }
                }
            }
            if(!acceptedTargetType && callEx.arguments) {
                this.checker.killCurrentContextualType();
                for(i = 0; i < callEx.arguments.members.length; i++) {
                    switch(callEx.arguments.members[i].nodeType) {
                        case TypeScript.NodeType.FuncDecl:
                        case TypeScript.NodeType.ObjectLit:
                        case TypeScript.NodeType.ArrayLit: {
                            this.typeCheck(callEx.arguments.members[i]);
                            break;

                        }
                        default: {
                            continue;

                        }
                    }
                }
            }
        };
        TypeFlow.prototype.typeCheckCall = function (ast) {
            var callEx = ast;
            if(this.checker.styleSettings.newMustBeUsed && (ast.nodeType == TypeScript.NodeType.New)) {
                if(TypeScript.hasFlag(ast.flags, TypeScript.ASTFlags.IsStatement)) {
                    this.checker.errorReporter.styleError(ast, "use of new expression as a statement");
                }
            } else {
                if((!this.checker.styleSettings.evalOK) && (ast.nodeType == TypeScript.NodeType.Call)) {
                    if((callEx.target.nodeType == TypeScript.NodeType.Name) && ((callEx.target).text == "eval")) {
                        this.checker.errorReporter.styleError(callEx, "eval not permitted");
                    }
                }
            }
            if(callEx.target.nodeType == TypeScript.NodeType.FuncDecl) {
                (callEx.target).isInlineCallLiteral = true;
            }
            var prevInSuperCall = this.inSuperCall;
            if(callEx.target.nodeType == TypeScript.NodeType.Super) {
                this.inSuperCall = true;
            }
            callEx.target = this.typeCheck(callEx.target);
            this.preTypeCheckCallArgs(callEx.arguments);
            var target = callEx.target;
            if((target.type == null) || (target.type == this.anyType) || (this.functionInterfaceType && target.type == this.functionInterfaceType)) {
                callEx.type = this.anyType;
            } else {
                var fnType = target.type;
                if(fnType.call) {
                    var signature = this.resolveOverload(callEx, fnType.call);
                    if(signature == null) {
                        callEx.type = this.anyType;
                    } else {
                        callEx.type = signature.returnType.type;
                        callEx.signature = signature;
                    }
                } else {
                    if(callEx.target.nodeType == TypeScript.NodeType.Super && this.thisFnc && this.thisFnc.isConstructor && TypeScript.hasFlag(this.thisFnc.fncFlags, TypeScript.FncFlags.ClassMethod)) {
                        var signature = fnType.symbol.type.construct ? this.resolveOverload(callEx, fnType.symbol.type.construct) : null;
                        if(signature == null) {
                            callEx.type = this.anyType;
                        } else {
                            callEx.flags |= TypeScript.ASTFlags.ClassBaseConstructorCall;
                            callEx.type = signature.returnType.type;
                            callEx.signature = signature;
                        }
                    } else {
                        callEx.type = this.anyType;
                        this.checker.errorReporter.invalidCall(callEx, callEx.nodeType, this.scope);
                    }
                }
            }
            this.postTypeCheckCallArgs(callEx);
            this.inSuperCall = prevInSuperCall;
            return callEx;
        };
        TypeFlow.prototype.assignScopes = function (ast) {
            var script = ast;
            this.checker.locationInfo = script.locationInfo;
            var globalChain = new ScopeChain(this.checker.gloMod, null, this.globalScope);
            var context = new TypeScript.AssignScopeContext(globalChain, this, [
                this.checker.currentModDecl
            ]);
            TypeScript.getAstWalkerFactory().walk(ast, TypeScript.preAssignScopes, TypeScript.postAssignScopes, null, context);
        };
        TypeFlow.prototype.findMemberScope = function (enclosingScopeContext, matchFlag) {
            var enclosingScope = enclosingScopeContext.getScope();
            var pos = enclosingScopeContext.pos - enclosingScopeContext.getScriptFragmentPosition();
            var scriptFragment = enclosingScopeContext.getScriptFragment();
            var memContext = new TypeScript.MemberScopeContext(this, pos, matchFlag);
            memContext.scope = enclosingScope;
            if(scriptFragment.nodeType == TypeScript.NodeType.Name) {
                return scriptFragment.type.getMemberScope(this);
            } else {
                TypeScript.getAstWalkerFactory().walk(scriptFragment, TypeScript.preFindMemberScope, null, null, memContext);
                if(memContext.ast && enclosingScopeContext.enclosingClassDecl && memContext.ast.type == enclosingScopeContext.enclosingClassDecl.type.instanceType) {
                    enclosingScopeContext.publicsOnly = false;
                }
                if(memContext.type) {
                    return memContext.type.getMemberScope(this);
                } else {
                    return null;
                }
            }
        };
        TypeFlow.prototype.findMemberScopeAt = function (enclosingScopeContext) {
            return this.findMemberScope(enclosingScopeContext, TypeScript.ASTFlags.DotLHS);
        };
        TypeFlow.prototype.findMemberScopeAtFullAst = function (enclosingScopeContext) {
            var matchFlag = TypeScript.ASTFlags.DotLHS;
            var pos = enclosingScopeContext.pos;
            var astResult = null;
            var preFindMemberScopeFullAst = function (ast, parent, walker) {
                if(TypeScript.isValidAstNode(ast)) {
                    if(TypeScript.hasFlag(ast.flags, matchFlag) && (pos == ast.limChar || (pos - 1) == ast.limChar)) {
                        astResult = ast;
                        walker.options.stopWalk();
                    }
                    walker.options.goChildren = (ast.minChar <= pos) && (pos <= ast.limChar);
                }
                return ast;
            };
            var preFindMemberScopeFullAstFuzy = function (ast, parent, walker) {
                if(TypeScript.isValidAstNode(ast)) {
                    if(TypeScript.hasFlag(ast.flags, matchFlag) && ((ast.minChar < pos) && (pos <= ast.limChar))) {
                        astResult = ast;
                    }
                    walker.options.goChildren = (ast.minChar <= pos) && (pos <= ast.limChar);
                }
                return ast;
            };
            TypeScript.getAstWalkerFactory().walk(enclosingScopeContext.script, preFindMemberScopeFullAst);
            if(astResult == null) {
                TypeScript.getAstWalkerFactory().walk(enclosingScopeContext.script, preFindMemberScopeFullAstFuzy);
            }
            if(astResult && enclosingScopeContext.enclosingClassDecl && astResult.type == enclosingScopeContext.enclosingClassDecl.type.instanceType) {
                enclosingScopeContext.publicsOnly = false;
            }
            if(astResult && astResult.type) {
                return astResult.type.getMemberScope(this);
            } else {
                return null;
            }
        };
        return TypeFlow;
    })();
    TypeScript.TypeFlow = TypeFlow;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (Primitive) {
        Primitive._map = [];
        Primitive.None = 0;
        Primitive.Void = 1;
        Primitive.Double = 2;
        Primitive.String = 4;
        Primitive.Boolean = 8;
        Primitive.Any = 16;
        Primitive.Null = 32;
        Primitive.Undefined = 64;
    })(TypeScript.Primitive || (TypeScript.Primitive = {}));
    var Primitive = TypeScript.Primitive;
    var MemberName = (function () {
        function MemberName() {
            this.prefix = "";
            this.suffix = "";
        }
        MemberName.prototype.isString = function () {
            return false;
        };
        MemberName.prototype.isArray = function () {
            return false;
        };
        MemberName.prototype.toString = function () {
            return MemberName.memberNameToString(this);
        };
        MemberName.memberNameToString = function memberNameToString(memberName) {
            var result = memberName.prefix;
            if(memberName.isString()) {
                result += (memberName).text;
            } else {
                var ar = memberName;
                for(var index = 0; index < ar.entries.length; index++) {
                    result += MemberName.memberNameToString(ar.entries[index]);
                    result += ar.delim;
                }
            }
            result += memberName.suffix;
            return result;
        }
        MemberName.create = function create(arg1, arg2, arg3) {
            if(typeof arg1 == "string") {
                return new MemberNameString(arg1);
            } else {
                var result = new MemberNameArray();
                if(arg2) {
                    result.prefix = arg2;
                }
                if(arg3) {
                    result.suffix = arg3;
                }
                result.entries.push(arg1);
                return result;
            }
        }
        return MemberName;
    })();
    TypeScript.MemberName = MemberName;    
    var MemberNameString = (function (_super) {
        __extends(MemberNameString, _super);
        function MemberNameString(text) {
                _super.call(this);
            this.text = text;
        }
        MemberNameString.prototype.isString = function () {
            return true;
        };
        return MemberNameString;
    })(MemberName);
    TypeScript.MemberNameString = MemberNameString;    
    var MemberNameArray = (function (_super) {
        __extends(MemberNameArray, _super);
        function MemberNameArray() {
            _super.apply(this, arguments);

            this.delim = "";
            this.entries = [];
        }
        MemberNameArray.prototype.isArray = function () {
            return true;
        };
        MemberNameArray.prototype.add = function (entry) {
            this.entries.push(entry);
        };
        MemberNameArray.prototype.addAll = function (entries) {
            for(var i = 0; i < entries.length; i++) {
                this.entries.push(entries[i]);
            }
        };
        return MemberNameArray;
    })(MemberName);
    TypeScript.MemberNameArray = MemberNameArray;    
    var currentTypeID = -1;
    var Type = (function () {
        function Type() {
            this.typeID = currentTypeID++;
            this.construct = null;
            this.call = null;
            this.index = null;
            this.passTypeCreated = TypeScript.CompilerDiagnostics.analysisPass;
            this.primitiveTypeClass = Primitive.None;
            this.typeFlags = TypeScript.TypeFlags.None;
        }
        Type.prototype.baseClass = function () {
            if(this.extendsList && (this.extendsList.length > 0)) {
                return this.extendsList[0];
            } else {
                return null;
            }
        };
        Type.prototype.getArrayBase = function (arrInstType, checker) {
            return this.arrayCache.specialize(arrInstType, checker);
        };
        Type.prototype.isClass = function () {
            return this.instanceType != null;
        };
        Type.prototype.isArray = function () {
            return this.elementType != null;
        };
        Type.prototype.isClassInstance = function () {
            return this.symbol && !this.elementType && (this.symbol).type.isClass();
        };
        Type.prototype.getInstanceType = function () {
            if(this.isClass()) {
                return this.instanceType;
            } else {
                return this;
            }
        };
        Type.prototype.hasImplementation = function () {
            return TypeScript.hasFlag(this.typeFlags, TypeScript.TypeFlags.HasImplementation);
        };
        Type.prototype.setHasImplementation = function () {
            this.typeFlags |= TypeScript.TypeFlags.HasImplementation;
        };
        Type.prototype.isDouble = function () {
            return TypeScript.hasFlag(this.primitiveTypeClass, Primitive.Double);
        };
        Type.prototype.isString = function () {
            return TypeScript.hasFlag(this.primitiveTypeClass, Primitive.String);
        };
        Type.prototype.isBoolean = function () {
            return TypeScript.hasFlag(this.primitiveTypeClass, Primitive.Boolean);
        };
        Type.prototype.isNull = function () {
            return TypeScript.hasFlag(this.primitiveTypeClass, Primitive.Null);
        };
        Type.prototype.getTypeName = function () {
            return this.getMemberTypeName("", true, false, null);
        };
        Type.prototype.getScopedTypeName = function (scope) {
            return this.getMemberTypeName("", true, false, scope);
        };
        Type.prototype.getScopedTypeNameEx = function (scope) {
            return this.getMemberTypeNameEx("", true, false, scope);
        };
        Type.prototype.callCount = function () {
            var total = 0;
            if(this.call) {
                total += this.call.signatures.length;
            }
            if(this.construct) {
                total += this.construct.signatures.length;
            }
            if(this.index) {
                total += this.index.signatures.length;
            }
            return total;
        };
        Type.prototype.getMemberTypeName = function (prefix, topLevel, isElementType, scope) {
            var memberName = this.getMemberTypeNameEx(prefix, topLevel, isElementType, scope);
            return memberName.toString();
        };
        Type.prototype.getMemberTypeNameEx = function (prefix, topLevel, isElementType, scope) {
            if(this.elementType) {
                return MemberName.create(this.elementType.getMemberTypeNameEx(prefix, false, true, scope), "", "[]");
            } else {
                if(this.symbol && this.symbol.name && this.symbol.name != "_anonymous" && (((this.call == null) && (this.construct == null) && (this.index == null)) || (TypeScript.hasFlag(this.typeFlags, TypeScript.TypeFlags.BuildingName)) || (this.members && (!this.isClass())))) {
                    var tn = this.symbol.scopeRelativeName(scope);
                    return MemberName.create(tn == "null" ? "any" : tn);
                } else {
                    if(this.members || this.call || this.construct) {
                        if(TypeScript.hasFlag(this.typeFlags, TypeScript.TypeFlags.BuildingName)) {
                            return MemberName.create("this");
                        }
                        this.typeFlags |= TypeScript.TypeFlags.BuildingName;
                        var builder = "";
                        var allMemberNames = new MemberNameArray();
                        var curlies = isElementType || this.index != null;
                        var memCount = 0;
                        var delim = "; ";
                        if(this.members) {
                            this.members.allMembers.map(function (key, s, unused) {
                                var sym = s;
                                if(!TypeScript.hasFlag(sym.flags, TypeScript.SymbolFlags.BuiltIn)) {
                                    var typeNameMember = sym.getTypeNameEx(scope);
                                    if(typeNameMember.isArray() && (typeNameMember).delim == delim) {
                                        allMemberNames.addAll((typeNameMember).entries);
                                    } else {
                                        allMemberNames.add(typeNameMember);
                                    }
                                    memCount++;
                                    curlies = true;
                                }
                            }, null);
                        }
                        var signatureCount = this.callCount();
                        var j;
                        var len = 0;
                        var shortform = !curlies && signatureCount == 1 && topLevel;
                        if(this.call) {
                            allMemberNames.addAll(this.call.toStrings(prefix, shortform, scope));
                        }
                        if(this.construct) {
                            allMemberNames.addAll(this.construct.toStrings("new", shortform, scope));
                        }
                        if(this.index) {
                            allMemberNames.addAll(this.index.toStrings("", shortform, scope));
                        }
                        if((curlies) || ((signatureCount > 1) && topLevel)) {
                            allMemberNames.prefix = "{ ";
                            allMemberNames.suffix = "}";
                            allMemberNames.delim = delim;
                        } else {
                            if(allMemberNames.entries.length > 1) {
                                allMemberNames.delim = delim;
                            }
                        }
                        this.typeFlags &= (~TypeScript.TypeFlags.BuildingName);
                        if((signatureCount == 0) && (memCount == 0)) {
                            return MemberName.create("{}");
                        } else {
                            return allMemberNames;
                        }
                    } else {
                        return MemberName.create("{}");
                    }
                }
            }
        };
        Type.prototype.checkDecl = function (checker) {
            if(this.isClassInstance() || this.isClass()) {
                if(this.symbol.declAST) {
                    checker.typeFlow.inScopeTypeCheckDecl(this.symbol.declAST);
                }
            }
        };
        Type.prototype.getMemberScope = function (flow) {
            if(this == flow.anyType) {
                return null;
            } else {
                if(this.isDouble()) {
                    if(flow.numberInterfaceType) {
                        return flow.numberInterfaceType.memberScope;
                    } else {
                        return null;
                    }
                } else {
                    if(this.isBoolean()) {
                        if(flow.booleanInterfaceType) {
                            return flow.booleanInterfaceType.memberScope;
                        } else {
                            return null;
                        }
                    } else {
                        if(this == flow.stringType) {
                            if(flow.stringInterfaceType) {
                                return flow.stringInterfaceType.memberScope;
                            } else {
                                return null;
                            }
                        } else {
                            if(this.elementType) {
                                if(flow.arrayInterfaceType) {
                                    var arrInstType = this.elementType.getArrayBase(flow.arrayInterfaceType, flow.checker);
                                    return arrInstType.memberScope;
                                } else {
                                    return null;
                                }
                            } else {
                                return this.memberScope;
                            }
                        }
                    }
                }
            }
        };
        Type.prototype.isReferenceType = function () {
            return this.members || this.extendsList || this.construct || this.call || this.index || this.elementType;
        };
        Type.prototype.specializeType = function (pattern, replacement, checker, membersOnly) {
            if(pattern == this) {
                return replacement;
            }
            var result = this;
            if(membersOnly) {
                if(this.isReferenceType()) {
                    result = new Type();
                    if(this.members) {
                        result.members = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                        this.members.publicMembers.map(function (key, s, unused) {
                            var sym = s;
                            var bSym = sym.specializeType(pattern, replacement, checker);
                            result.members.addPublicMember(bSym.name, bSym);
                        }, null);
                        this.members.privateMembers.map(function (key, s, unused) {
                            var sym = s;
                            var bSym = sym.specializeType(pattern, replacement, checker);
                            result.members.addPrivateMember(bSym.name, bSym);
                        }, null);
                    }
                    if(this.ambientMembers) {
                        result.ambientMembers = new TypeScript.ScopedMembers(new TypeScript.DualStringHashTable(new TypeScript.StringHashTable(), new TypeScript.StringHashTable()));
                        this.ambientMembers.publicMembers.map(function (key, s, unused) {
                            var sym = s;
                            var bSym = sym.specializeType(pattern, replacement, checker);
                            result.ambientMembers.addPublicMember(bSym.name, bSym);
                        }, null);
                        this.ambientMembers.privateMembers.map(function (key, s, unused) {
                            var sym = s;
                            var bSym = sym.specializeType(pattern, replacement, checker);
                            result.ambientMembers.addPrivateMember(bSym.name, bSym);
                        }, null);
                    }
                    result.containedScope = checker.scopeOf(result);
                    result.memberScope = result.containedScope;
                }
            } else {
                if(this.elementType) {
                    if(this.elementType == pattern) {
                        result = checker.makeArrayType(replacement);
                    } else {
                        if(this.elementType.elementType == pattern) {
                            result = checker.makeArrayType(checker.makeArrayType(replacement));
                        }
                    }
                } else {
                    if(this.call) {
                        result = new Type();
                        result.call = this.call.specializeType(pattern, replacement, checker);
                    }
                }
            }
            return result;
        };
        Type.prototype.hasBase = function (baseType) {
            if(baseType == this) {
                return true;
            } else {
                if(this.extendsList) {
                    for(var i = 0, len = this.extendsList.length; i < len; i++) {
                        if(this.extendsList[i].hasBase(baseType)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        };
        Type.prototype.mergeOrdered = function (b, checker, acceptVoid, comparisonInfo) {
            if((this == checker.anyType) || (b == checker.anyType)) {
                return checker.anyType;
            } else {
                if(this == b) {
                    return this;
                } else {
                    if((b == checker.nullType) && this != checker.nullType) {
                        return this;
                    } else {
                        if((this == checker.nullType) && (b != checker.nullType)) {
                            return b;
                        } else {
                            if(acceptVoid && (b == checker.voidType) && this != checker.voidType) {
                                return this;
                            } else {
                                if(acceptVoid && (this == checker.voidType) && (b != checker.voidType)) {
                                    return b;
                                } else {
                                    if((b == checker.undefinedType) && this != checker.undefinedType) {
                                        return this;
                                    } else {
                                        if((this == checker.undefinedType) && (b != checker.undefinedType)) {
                                            return b;
                                        } else {
                                            if(this.elementType && b.elementType) {
                                                if(this.elementType == b.elementType) {
                                                    return this;
                                                } else {
                                                    var mergedET = this.elementType.mergeOrdered(b.elementType, checker, acceptVoid, comparisonInfo);
                                                    if(mergedET == null) {
                                                        return checker.makeArrayType(checker.anyType);
                                                    } else {
                                                        return checker.makeArrayType(mergedET);
                                                    }
                                                }
                                            } else {
                                                if(checker.sourceIsSubtypeOfTarget(this, b, comparisonInfo)) {
                                                    return b;
                                                } else {
                                                    if(checker.sourceIsSubtypeOfTarget(b, this, comparisonInfo)) {
                                                        return this;
                                                    } else {
                                                        return null;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        };
        Type.prototype.isModuleType = function () {
            return false;
        };
        Type.prototype.hasMembers = function () {
            return this.members != null;
        };
        Type.prototype.getAllEnclosedTypes = function () {
            return null;
        };
        Type.prototype.getAllAmbientEnclosedTypes = function () {
            return null;
        };
        Type.prototype.getPublicEnclosedTypes = function () {
            return null;
        };
        Type.prototype.getpublicAmbientEnclosedTypes = function () {
            return null;
        };
        Type.prototype.getDocComments = function () {
            if(this.elementType || !this.symbol) {
                return [];
            }
            if(this.isClassInstance() || this.isClass()) {
                if(this.symbol.declAST.nodeType == TypeScript.NodeType.FuncDecl) {
                    return (this.symbol.declAST).classDecl.getDocComments();
                } else {
                    return this.symbol.getDocComments();
                }
            }
            if(this.symbol.name && this.symbol.name != "_anonymous" && (((this.call == null) && (this.construct == null) && (this.index == null)) || this.members)) {
                return this.symbol.getDocComments();
            }
            return [];
        };
        return Type;
    })();
    TypeScript.Type = Type;    
    var ModuleType = (function (_super) {
        __extends(ModuleType, _super);
        function ModuleType(enclosedTypes, ambientEnclosedTypes) {
                _super.call(this);
            this.enclosedTypes = enclosedTypes;
            this.ambientEnclosedTypes = ambientEnclosedTypes;
            this.importedModules = [];
        }
        ModuleType.prototype.isModuleType = function () {
            return true;
        };
        ModuleType.prototype.hasMembers = function () {
            return this.members != null || this.enclosedTypes != null;
        };
        ModuleType.prototype.getAllEnclosedTypes = function () {
            return this.enclosedTypes;
        };
        ModuleType.prototype.getAllAmbientEnclosedTypes = function () {
            return this.ambientEnclosedTypes;
        };
        ModuleType.prototype.getPublicEnclosedTypes = function () {
            return null;
        };
        ModuleType.prototype.getpublicAmbientEnclosedTypes = function () {
            return null;
        };
        ModuleType.findDynamicModuleNameInHashTable = function findDynamicModuleNameInHashTable(moduleType, members) {
            var moduleName = null;
            members.map(function (key, s, c) {
                if(moduleName == null && !TypeScript.isQuoted(key)) {
                    var symbol = s;
                    var type = symbol.getType();
                    if(type == moduleType) {
                        moduleName = {
                            name: key,
                            symbol: symbol
                        };
                    }
                }
            }, null);
            return moduleName;
        }
        ModuleType.prototype.findDynamicModuleName = function (moduleType) {
            var moduleName = null;
            moduleName = ModuleType.findDynamicModuleNameInHashTable(moduleType, this.members.allMembers);
            if(moduleName == null) {
                moduleName = ModuleType.findDynamicModuleNameInHashTable(moduleType, this.ambientMembers.allMembers);
            }
            return moduleName;
        };
        return ModuleType;
    })(Type);
    TypeScript.ModuleType = ModuleType;    
    var TypeLink = (function () {
        function TypeLink() {
            this.type = null;
            this.ast = null;
        }
        return TypeLink;
    })();
    TypeScript.TypeLink = TypeLink;    
    function getTypeLink(ast, checker, autoVar) {
        var result = new TypeLink();
        result.ast = ast;
        if((ast == null) && (autoVar)) {
            result.type = checker.anyType;
        } else {
            result.type = null;
        }
        return result;
    }
    TypeScript.getTypeLink = getTypeLink;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    function stripQuotes(str) {
        return str.replace("\"", "").replace("'", "").replace("'", "").replace("\"", "");
    }
    TypeScript.stripQuotes = stripQuotes;
    function isQuoted(str) {
        return str.indexOf("\"") != -1 || str.indexOf("'") != -1 || str.indexOf("'") != -1 || str.indexOf("\"") != -1;
    }
    TypeScript.isQuoted = isQuoted;
    function quoteStr(str) {
        return "\"" + str + "\"";
    }
    TypeScript.quoteStr = quoteStr;
    function swapQuotes(str) {
        if(str.indexOf("\"") != -1) {
            str = str.replace("\"", "'");
            str = str.replace("\"", "'");
        } else {
            str = str.replace("'", "\"");
            str = str.replace("'", "\"");
        }
        return str;
    }
    TypeScript.swapQuotes = swapQuotes;
    function switchToForwardSlashes(path) {
        return path.replace(/\\/g, "/");
    }
    TypeScript.switchToForwardSlashes = switchToForwardSlashes;
    function trimModName(modName) {
        if(modName.length > 6 && modName.substring(modName.length - 6, modName.length) == ".d.str") {
            return modName.substring(0, modName.length - 6);
        }
        if(modName.length > 4 && modName.substring(modName.length - 4, modName.length) == ".str") {
            return modName.substring(0, modName.length - 4);
        }
        if(modName.length > 5 && modName.substring(modName.length - 5, modName.length) == ".d.ts") {
            return modName.substring(0, modName.length - 5);
        }
        if(modName.length > 3 && modName.substring(modName.length - 3, modName.length) == ".ts") {
            return modName.substring(0, modName.length - 3);
        }
        if(modName.length > 3 && modName.substring(modName.length - 3, modName.length) == ".js") {
            return modName.substring(0, modName.length - 3);
        }
        return modName;
    }
    TypeScript.trimModName = trimModName;
    function getDeclareFilePath(fname) {
        return isSTRFile(fname) ? changePathToDSTR(fname) : isTSFile(fname) ? changePathToDTS(fname) : changePathToDTS(fname);
    }
    TypeScript.getDeclareFilePath = getDeclareFilePath;
    function isFileOfExtension(fname, ext) {
        var invariantFname = fname.toLocaleUpperCase();
        var invariantExt = ext.toLocaleUpperCase();
        var extLength = invariantExt.length;
        return invariantFname.length > extLength && invariantFname.substring(invariantFname.length - extLength, invariantFname.length) == invariantExt;
    }
    function isJSFile(fname) {
        return isFileOfExtension(fname, ".js");
    }
    TypeScript.isJSFile = isJSFile;
    function isSTRFile(fname) {
        return isFileOfExtension(fname, ".str");
    }
    TypeScript.isSTRFile = isSTRFile;
    function isTSFile(fname) {
        return isFileOfExtension(fname, ".ts");
    }
    TypeScript.isTSFile = isTSFile;
    function isDSTRFile(fname) {
        return isFileOfExtension(fname, ".d.str");
    }
    TypeScript.isDSTRFile = isDSTRFile;
    function isDTSFile(fname) {
        return isFileOfExtension(fname, ".d.ts");
    }
    TypeScript.isDTSFile = isDTSFile;
    function getPrettyName(modPath, quote, treatAsFileName) {
        if (typeof quote === "undefined") { quote = true; }
        if (typeof treatAsFileName === "undefined") { treatAsFileName = false; }
        var modName = treatAsFileName ? switchToForwardSlashes(modPath) : trimModName(stripQuotes(modPath));
        var components = this.getPathComponents(modName);
        return components.length ? (quote ? quoteStr(components[components.length - 1]) : components[components.length - 1]) : modPath;
    }
    TypeScript.getPrettyName = getPrettyName;
    function getPathComponents(path) {
        return path.split("/");
    }
    TypeScript.getPathComponents = getPathComponents;
    function getRelativePathToFixedPath(fixedModFilePath, absoluteModPath) {
        absoluteModPath = switchToForwardSlashes(absoluteModPath);
        var modComponents = this.getPathComponents(absoluteModPath);
        var fixedModComponents = this.getPathComponents(fixedModFilePath);
        var joinStartIndex = 0;
        for(; joinStartIndex < modComponents.length && joinStartIndex < fixedModComponents.length; joinStartIndex++) {
            if(fixedModComponents[joinStartIndex] != modComponents[joinStartIndex]) {
                break;
            }
        }
        if(joinStartIndex != 0) {
            var relativePath = "";
            var relativePathComponents = modComponents.slice(joinStartIndex, modComponents.length);
            for(; joinStartIndex < fixedModComponents.length; joinStartIndex++) {
                if(fixedModComponents[joinStartIndex] != "") {
                    relativePath = relativePath + "../";
                }
            }
            return relativePath + relativePathComponents.join("/");
        }
        return absoluteModPath;
    }
    TypeScript.getRelativePathToFixedPath = getRelativePathToFixedPath;
    function quoteBaseName(modPath) {
        var modName = trimModName(stripQuotes(modPath));
        var path = getRootFilePath(modName);
        if(path == "") {
            return modPath;
        } else {
            var components = modName.split(path);
            var fileIndex = components.length > 1 ? 1 : 0;
            return quoteStr(components[fileIndex]);
        }
    }
    TypeScript.quoteBaseName = quoteBaseName;
    function changePathToSTR(modPath) {
        return trimModName(stripQuotes(modPath)) + ".str";
    }
    TypeScript.changePathToSTR = changePathToSTR;
    function changePathToDSTR(modPath) {
        return trimModName(stripQuotes(modPath)) + ".d.str";
    }
    TypeScript.changePathToDSTR = changePathToDSTR;
    function changePathToTS(modPath) {
        return trimModName(stripQuotes(modPath)) + ".ts";
    }
    TypeScript.changePathToTS = changePathToTS;
    function changePathToDTS(modPath) {
        return trimModName(stripQuotes(modPath)) + ".d.ts";
    }
    TypeScript.changePathToDTS = changePathToDTS;
    function isRelative(path) {
        return path.charAt(0) == ".";
    }
    TypeScript.isRelative = isRelative;
    function isRooted(path) {
        return path.charAt(0) == "\\" || path.charAt(0) == "/" || (path.indexOf(":\\") != -1) || (path.indexOf(":/") != -1);
    }
    TypeScript.isRooted = isRooted;
    function getRootFilePath(outFname) {
        if(outFname == "") {
            return outFname;
        } else {
            var isPath = outFname.indexOf("/") != -1;
            return isPath ? filePath(outFname) : "";
        }
    }
    TypeScript.getRootFilePath = getRootFilePath;
    function filePathComponents(fullPath) {
        fullPath = switchToForwardSlashes(fullPath);
        var components = getPathComponents(fullPath);
        return components.slice(0, components.length - 1);
    }
    TypeScript.filePathComponents = filePathComponents;
    function filePath(fullPath) {
        var path = filePathComponents(fullPath);
        return path.join("/") + "/";
    }
    TypeScript.filePath = filePath;
    function normalizeURL(url) {
        var hostDomainAndPortRegex = /^(https?:\/\/[\-\w\.]+(:\d+)?\/)(.*)$/i;
        var matches = hostDomainAndPortRegex.exec(url);
        if(matches) {
            var hostDomainAndPort = matches[1];
            var actualPath = matches[3];
            return hostDomainAndPort + normalizePath(actualPath);
        }
        return normalizePath(url);
    }
    TypeScript.normalizeURL = normalizeURL;
    TypeScript.pathNormalizeRegExp = /\//g;
    function normalizePath(path) {
        path = switchToForwardSlashes(path);
        var startedWithSep = path.charAt(0) === "/";
        var parts = this.getPathComponents(path);
        for(var i = 0; i < parts.length; i++) {
            if(parts[i] === "." || parts[i] === "") {
                parts.splice(i, 1);
                i--;
            }
            if(i > 0 && parts[i] === ".." && parts[i - 1] !== "..") {
                parts.splice(i - 1, 2);
                i -= 2;
            }
        }
        return (startedWithSep ? "/" : "") + parts.join("/");
    }
    TypeScript.normalizePath = normalizePath;
    function normalizeImportPath(path) {
        return normalizePath(path);
    }
    TypeScript.normalizeImportPath = normalizeImportPath;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var SourceUnit = (function () {
        function SourceUnit(path, content) {
            this.path = path;
            this.content = content;
            this.referencedFiles = null;
        }
        SourceUnit.prototype.getText = function (start, end) {
            return this.content.substring(start, end);
        };
        SourceUnit.prototype.getLength = function () {
            return this.content.length;
        };
        return SourceUnit;
    })();
    TypeScript.SourceUnit = SourceUnit;    
    var CompilationEnvironment = (function () {
        function CompilationEnvironment(compilationSettings, ioHost) {
            this.compilationSettings = compilationSettings;
            this.ioHost = ioHost;
            this.residentCode = [];
            this.code = [];
        }
        return CompilationEnvironment;
    })();
    TypeScript.CompilationEnvironment = CompilationEnvironment;    
    var CodeResolver = (function () {
        function CodeResolver(environment) {
            this.environment = environment;
            this.visited = {
            };
        }
        CodeResolver.prototype.resolveCode = function (referencePath, parentPath, performSearch, resolutionDispatcher) {
            var resolvedFile = {
                content: "",
                path: referencePath
            };
            var ioHost = this.environment.ioHost;
            var isRelativePath = TypeScript.isRelative(referencePath);
            var isRootedPath = isRelativePath ? false : TypeScript.isRooted(referencePath);
            var normalizedPath = isRelativePath ? ioHost.resolvePath(parentPath + "/" + referencePath) : (isRootedPath || !parentPath || performSearch ? referencePath : parentPath + "/" + referencePath);
            if(!TypeScript.isSTRFile(normalizedPath) && !TypeScript.isTSFile(normalizedPath)) {
                normalizedPath += ".ts";
            }
            normalizedPath = TypeScript.switchToForwardSlashes(TypeScript.stripQuotes(normalizedPath));
            var absoluteModuleID = this.environment.compilationSettings.useCaseSensitiveFileResolution ? normalizedPath : normalizedPath.toLocaleUpperCase();
            if(!this.visited[absoluteModuleID]) {
                if(isRelativePath || isRootedPath || !performSearch) {
                    try  {
                        TypeScript.CompilerDiagnostics.debugPrint("   Reading code from " + normalizedPath);
                        try  {
                            resolvedFile.content = ioHost.readFile(normalizedPath);
                        } catch (err) {
                            try  {
                                if(TypeScript.isSTRFile(normalizedPath)) {
                                    normalizedPath = TypeScript.changePathToTS(normalizedPath);
                                } else {
                                    if(TypeScript.isTSFile(normalizedPath)) {
                                        normalizedPath = TypeScript.changePathToSTR(normalizedPath);
                                    }
                                }
                                TypeScript.CompilerDiagnostics.debugPrint("   Reading code from " + normalizedPath);
                                resolvedFile.content = ioHost.readFile(normalizedPath);
                            } catch (err) {
                                normalizedPath = TypeScript.changePathToDSTR(normalizedPath);
                                TypeScript.CompilerDiagnostics.debugPrint("   Reading code from " + normalizedPath);
                                try  {
                                    resolvedFile.content = ioHost.readFile(normalizedPath);
                                } catch (err) {
                                    normalizedPath = TypeScript.changePathToDTS(normalizedPath);
                                    TypeScript.CompilerDiagnostics.debugPrint("   Reading code from " + normalizedPath);
                                    resolvedFile.content = ioHost.readFile(normalizedPath);
                                }
                            }
                        }
                        TypeScript.CompilerDiagnostics.debugPrint("   Found code at " + normalizedPath);
                        resolvedFile.path = normalizedPath;
                        this.visited[absoluteModuleID] = true;
                    } catch (err) {
                        TypeScript.CompilerDiagnostics.debugPrint("   Did not find code for " + referencePath);
                    }
                } else {
                    resolvedFile = ioHost.findFile(parentPath, normalizedPath);
                    if(!resolvedFile) {
                        if(TypeScript.isSTRFile(normalizedPath)) {
                            normalizedPath = TypeScript.changePathToTS(normalizedPath);
                        } else {
                            if(TypeScript.isTSFile(normalizedPath)) {
                                normalizedPath = TypeScript.changePathToSTR(normalizedPath);
                            }
                        }
                        resolvedFile = ioHost.findFile(parentPath, normalizedPath);
                    }
                    if(!resolvedFile) {
                        normalizedPath = TypeScript.changePathToDTS(normalizedPath);
                        resolvedFile = ioHost.findFile(parentPath, normalizedPath);
                        if(!resolvedFile) {
                            normalizedPath = TypeScript.changePathToDSTR(normalizedPath);
                            resolvedFile = ioHost.findFile(parentPath, normalizedPath);
                        }
                    }
                    if(resolvedFile) {
                        resolvedFile.path = TypeScript.switchToForwardSlashes(TypeScript.stripQuotes(resolvedFile.path));
                        TypeScript.CompilerDiagnostics.debugPrint(referencePath + " resolved to: " + resolvedFile.path);
                        resolvedFile.content = resolvedFile.content;
                        this.visited[absoluteModuleID] = true;
                    } else {
                        TypeScript.CompilerDiagnostics.debugPrint("Could not find " + referencePath);
                    }
                }
                if(resolvedFile && resolvedFile.content) {
                    var rootDir = ioHost.dirName(resolvedFile.path);
                    var sourceUnit = new SourceUnit(resolvedFile.path, resolvedFile.content);
                    var preProcessedFileInfo = TypeScript.preProcessFile(sourceUnit, this.environment.compilationSettings);
                    sourceUnit.referencedFiles = preProcessedFileInfo.referencedFiles;
                    for(var i = 0; i < preProcessedFileInfo.referencedFiles.length; i++) {
                        var referencedFile = preProcessedFileInfo.referencedFiles[i];
                        var normalizedPath = TypeScript.isRooted(referencedFile.path) ? referencedFile.path : rootDir + "/" + referencedFile.path;
                        normalizedPath = ioHost.resolvePath(normalizedPath);
                        if(referencePath == normalizedPath) {
                            resolutionDispatcher.postResolutionError(normalizedPath, "File contains reference to itself", null);
                            continue;
                        }
                        this.resolveCode(referencedFile.path, rootDir, false, resolutionDispatcher);
                    }
                    for(var i = 0; i < preProcessedFileInfo.importedFiles.length; i++) {
                        this.resolveCode(preProcessedFileInfo.importedFiles[i].path, rootDir, true, resolutionDispatcher);
                    }
                    resolutionDispatcher.postResolution(sourceUnit.path, sourceUnit);
                }
            }
        };
        return CodeResolver;
    })();
    TypeScript.CodeResolver = CodeResolver;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var StyleSettings = (function () {
        function StyleSettings() {
            this.bitwise = false;
            this.blockInCompoundStmt = false;
            this.eqeqeq = false;
            this.forin = false;
            this.emptyBlocks = true;
            this.newMustBeUsed = false;
            this.requireSemi = false;
            this.assignmentInCond = false;
            this.eqnull = false;
            this.evalOK = true;
            this.innerScopeDeclEscape = true;
            this.funcInLoop = true;
            this.reDeclareLocal = true;
            this.literalSubscript = true;
            this.implicitAny = false;
        }
        StyleSettings.prototype.setOption = function (opt, val) {
            var optExists = this[opt];
            if(optExists !== undefined) {
                this[opt] = val;
                return true;
            } else {
                return false;
            }
        };
        StyleSettings.prototype.parseOptions = function (str) {
            var opts = str.split(";");
            for(var i = 0, len = opts.length; i < len; i++) {
                var opt = opts[i];
                var val = true;
                var colonIndex = opt.lastIndexOf(":");
                if(colonIndex >= 0) {
                    var valStr = opt.substring(colonIndex + 1);
                    opt = opt.substring(0, colonIndex);
                    if(valStr == "off") {
                        val = false;
                    }
                }
                if(!this.setOption(opt, val)) {
                    return false;
                }
            }
            return true;
        };
        return StyleSettings;
    })();
    TypeScript.StyleSettings = StyleSettings;    
    var CompilationSettings = (function () {
        function CompilationSettings() {
            this.styleSettings = new StyleSettings();
            this.propagateConstants = false;
            this.minWhitespace = false;
            this.parseOnly = false;
            this.errorRecovery = false;
            this.emitComments = false;
            this.watch = false;
            this.exec = false;
            this.resolve = true;
            this.controlFlow = false;
            this.printControlFlow = false;
            this.controlFlowUseDef = false;
            this.errorOnWith = true;
            this.preprocess = true;
            this.canCallDefinitionSignature = false;
            this.inferPropertiesFromThisAssignment = false;
            this.useDefaultLib = true;
            this.codeGenTarget = TypeScript.CodeGenTarget.ES3;
            this.moduleGenTarget = TypeScript.ModuleGenTarget.Synchronous;
            this.outputOption = "";
            this.mapSourceFiles = false;
            this.generateDeclarationFiles = false;
            this.useCaseSensitiveFileResolution = false;
        }
        CompilationSettings.prototype.setStyleOptions = function (str) {
            this.styleSettings.parseOptions(str);
        };
        return CompilationSettings;
    })();
    TypeScript.CompilationSettings = CompilationSettings;    
    function getFileReferenceFromReferencePath(comment) {
        var referencesRegEx = /^(\/\/\/\s*<reference\s+path=)('|")(.+?)\2\s*(static=('|")(.+?)\2\s*)*\/>/igm;
        var match = referencesRegEx.exec(comment);
        if(match) {
            var path = TypeScript.normalizePath(match[3]);
            var adjustedPath = TypeScript.normalizePath(path);
            var isResident = match.length >= 7 && match[6] == "true";
            if(isResident) {
                TypeScript.CompilerDiagnostics.debugPrint(path + " is resident");
            }
            return {
                minChar: 0,
                limChar: 0,
                path: TypeScript.switchToForwardSlashes(adjustedPath),
                isResident: isResident
            };
        } else {
            return null;
        }
    }
    function getAdditionalDependencyPath(comment) {
        var amdDependencyRegEx = /^(\/\/\/\s*<amd-dependency\s+path=)('|")(.+?)\2\s*(static=('|")(.+?)\2\s*)*\/>/igm;
        var match = amdDependencyRegEx.exec(comment);
        if(match) {
            var path = match[3];
            return path;
        } else {
            return null;
        }
    }
    TypeScript.getAdditionalDependencyPath = getAdditionalDependencyPath;
    function getImplicitImport(comment) {
        var implicitImportRegEx = /^(\/\/\/\s*<implicit-import\s*)*\/>/igm;
        var match = implicitImportRegEx.exec(comment);
        if(match) {
            return true;
        }
        return false;
    }
    TypeScript.getImplicitImport = getImplicitImport;
    function getStyleSettings(comment, styleSettings) {
        var styleRegEx = /^(\/\/\/\s*<style\s+)(([a-zA-Z])+=('|").+('|"))\s*\/>/igm;
        var settings = styleRegEx.exec(comment);
        if(settings) {
            var settingsRegEx = /^([a-zA-Z]+=['"]on['|"])/igm;
            settings = settingsRegEx.exec(settings[2]);
            if(settings) {
                for(var i = 0; i < settings.length; i++) {
                    var setting = (settings[i]).split("=");
                    var on = "\"on\"";
                    switch(setting[0]) {
                        case "blockInCompoundStmt": {
                            styleSettings.blockInCompoundStmt = setting[1] == on;
                            break;

                        }
                        case "eqeqeq": {
                            styleSettings.eqeqeq = setting[1] == on;
                            break;

                        }
                        case "forin": {
                            styleSettings.forin = setting[1] == on;
                            break;

                        }
                        case "emptyBlocks": {
                            styleSettings.emptyBlocks = setting[1] == on;
                            break;

                        }
                        case "newMustBeUsed": {
                            styleSettings.newMustBeUsed = setting[1] == on;
                            break;

                        }
                        case "requireSemi": {
                            styleSettings.requireSemi = setting[1] == on;
                            break;

                        }
                        case "assignmentInCond": {
                            styleSettings.assignmentInCond = setting[1] == on;
                            break;

                        }
                        case "eqnull": {
                            styleSettings.eqnull = setting[1] == on;
                            break;

                        }
                        case "evalOK": {
                            styleSettings.evalOK = setting[1] == on;
                            break;

                        }
                        case "innerScopeDeclEscape": {
                            styleSettings.innerScopeDeclEscape = setting[1] == on;
                            break;

                        }
                        case "funcInLoop": {
                            styleSettings.funcInLoop = setting[1] == on;
                            break;

                        }
                        case "reDeclareLocal": {
                            styleSettings.reDeclareLocal = setting[1] == on;
                            break;

                        }
                        case "literalSubscript": {
                            styleSettings.literalSubscript = setting[1] == on;
                            break;

                        }
                        case "implicitAny": {
                            styleSettings.implicitAny = setting[1] == on;
                            break;

                        }
                    }
                }
            }
        }
    }
    TypeScript.getStyleSettings = getStyleSettings;
    function getReferencedFiles(sourceText) {
        var preProcessInfo = preProcessFile(sourceText, null, false);
        return preProcessInfo.referencedFiles;
    }
    TypeScript.getReferencedFiles = getReferencedFiles;
    function preProcessFile(sourceText, options, readImportFiles) {
        if (typeof options === "undefined") { options = new CompilationSettings(); }
        if (typeof readImportFiles === "undefined") { readImportFiles = true; }
        var scanner = new TypeScript.Scanner();
        scanner.resetComments();
        scanner.setSourceText(sourceText, TypeScript.LexMode.File);
        var tok = scanner.scan();
        var comments = [];
        var comment = null;
        var leftCurlies = [];
        var settings = options;
        var referencedFiles = [];
        var importedFiles = [];
        var isLibFile = false;
        while(tok.tokenId != TypeScript.TokenID.EndOfFile) {
            if(readImportFiles && tok.tokenId == TypeScript.TokenID.Import) {
                tok = scanner.scan();
                if(tok.tokenId == TypeScript.TokenID.Identifier || TypeScript.convertTokToID(tok, false)) {
                    tok = scanner.scan();
                    if(tok.tokenId == TypeScript.TokenID.Equals) {
                        tok = scanner.scan();
                        if(tok.tokenId == TypeScript.TokenID.Module) {
                            tok = scanner.scan();
                            if(tok.tokenId == TypeScript.TokenID.OpenParen) {
                                tok = scanner.scan();
                                if(tok.tokenId == TypeScript.TokenID.StringLiteral) {
                                    var ref = {
                                        minChar: scanner.startPos,
                                        limChar: scanner.pos,
                                        path: TypeScript.stripQuotes(TypeScript.switchToForwardSlashes(tok.getText())),
                                        isResident: false
                                    };
                                    importedFiles.push(ref);
                                }
                            }
                        }
                    }
                }
            }
            if(tok.tokenId == TypeScript.TokenID.OpenBrace) {
                leftCurlies.push(tok);
            }
            if(tok.tokenId == TypeScript.TokenID.CloseBrace) {
                leftCurlies.pop();
            }
            tok = scanner.scan();
        }
        comments = scanner.getComments();
        for(var iComment = 0; iComment < comments.length; iComment++) {
            comment = comments[iComment];
            if(!comment.isBlock) {
                var referencedCode = getFileReferenceFromReferencePath(comment.getText());
                if(referencedCode) {
                    referencedCode.minChar = comment.startPos;
                    referencedCode.limChar = referencedCode.minChar + comment.value.length;
                    referencedFiles.push(referencedCode);
                }
                if(settings) {
                    getStyleSettings(comment.getText(), settings.styleSettings);
                    var isNoLibRegex = /^(\/\/\/\s*<reference\s+no-default-lib=)('|")(.+?)\2\s*\/>/igm;
                    var isNoLibMatch = isNoLibRegex.exec(comment.getText());
                    if(isNoLibMatch) {
                        isLibFile = (isNoLibMatch[3] == "true");
                    }
                }
            }
        }
        return {
            settings: settings,
            referencedFiles: referencedFiles,
            importedFiles: importedFiles,
            isLibFile: isLibFile
        };
    }
    TypeScript.preProcessFile = preProcessFile;
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var IncrementalParser = (function () {
        function IncrementalParser(logger) {
            this.logger = logger;
            this.astLogger = new TypeScript.AstLogger(this.logger);
        }
        IncrementalParser.prototype.getEnclosingScopeContextIfSingleScopeEdit = function (previousScript, scriptId, newSourceText, editRange) {
            this.logger.log("checkEditsInsideSingleScope(\"" + scriptId + "\")");
            if(editRange === null) {
                throw new Error("editRange should be valid");
            }
            if(editRange.isUnknown()) {
                this.logger.log("  Bailing out because edit range is unknown");
                return null;
            }
            var scope1 = TypeScript.findEnclosingScopeAt(this.logger, previousScript, newSourceText, editRange.minChar, false);
            var scope2 = TypeScript.findEnclosingScopeAt(this.logger, previousScript, newSourceText, editRange.limChar, false);
            if(scope1 == null || scope2 == null) {
                this.logger.log("  Bailing out because containing scopes cannot be determined");
                return null;
            }
            if(scope1.scopeStartAST !== scope2.scopeStartAST) {
                this.logger.log("  Bailing out because edit overlaps 2 disctint scopes");
                return null;
            }
            var newScopeLength = scope1.scopeStartAST.limChar - scope1.scopeStartAST.minChar + editRange.delta;
            if(newScopeLength <= 0) {
                this.logger.log("  Bailing out because scope has been entirely removed from new source text");
                return null;
            }
            return scope1;
        };
        IncrementalParser.prototype.attemptIncrementalUpdateUnit = function (previousScript, scriptId, newSourceText, editRange) {
            this.logger.log("attemptIncrementalUpdateUnit(\"" + scriptId + "\")");
            if(editRange === null) {
                throw new Error("editRange should be valid");
            }
            var scope1 = this.getEnclosingScopeContextIfSingleScopeEdit(previousScript, scriptId, newSourceText, editRange);
            if(scope1 === null) {
                return null;
            }
            var newScopeLength = scope1.scopeStartAST.limChar - scope1.scopeStartAST.minChar + editRange.delta;
            if(newScopeLength >= newSourceText.getLength() / 2) {
                this.logger.log("  Bailing out because range of scope to reparse (" + newScopeLength + " characters) is greater than half the size of the source text");
                return null;
            }
            var parseErrors = [];
            var errorCapture = function (minChar, charLen, message, unitIndex) {
                parseErrors.push(new TypeScript.ErrorEntry(unitIndex, minChar, minChar + charLen, message));
            };
            var quickParseResult = TypeScript.quickParse(this.logger, scope1.scopeStartAST, newSourceText, scope1.scopeStartAST.minChar, scope1.scopeStartAST.minChar + newScopeLength, errorCapture);
            if(quickParseResult.endLexState != TypeScript.LexState.Start) {
                this.logger.log("  Bailing out because scope contains unterminated comment");
                return null;
            }
            var scriptFragment = quickParseResult.Script;
            if(scriptFragment.vars.members.length !== 0) {
                this.logger.log("  Bailing out because new source text defines variables");
                return null;
            }
            if(scriptFragment.bod.members.length !== 1) {
                this.logger.log("  Bailing out because new source text defines more than one scope (or none)");
                return null;
            }
            var oldScope = scope1.scopeStartAST;
            var newScope = scriptFragment.bod.members[0];
            if(oldScope.nodeType != newScope.nodeType) {
                this.logger.log("  Bailing out because new source text does not define the same scope type as the existing scope");
                return null;
            }
            if(!(oldScope).leftCurlyCount || !(oldScope).rightCurlyCount) {
                this.logger.log("  Bailing out because sopce doesn't have left/right curly count");
                return null;
            }
            if((oldScope).leftCurlyCount !== (newScope).leftCurlyCount) {
                this.logger.log("  Bailing out because new source text contains more (or fewer) left curly braces");
                return null;
            }
            if((oldScope).rightCurlyCount !== (newScope).rightCurlyCount) {
                this.logger.log("  Bailing out because new source text contains more (or fewer) right curly braces");
                return null;
            }
            if(newScope.minChar !== 0) {
                this.logger.log("  Bailing out because new function declaration does not start at position 0");
                return null;
            }
            if(newScope.limChar !== newScopeLength) {
                this.logger.log("  Bailing out because new function declaration does not end at the new end position");
                return null;
            }
            return TypeScript.UpdateUnitResult.singleScopeEdits(previousScript, scriptFragment, oldScope, newScope, editRange, parseErrors);
        };
        IncrementalParser.prototype.mergeTrees = function (updateResult) {
            var _this = this;
            TypeScript.timeFunction(this.logger, "mergeTrees()", function () {
                var editRange = new TypeScript.ScriptEditRange(updateResult.scope1.minChar, updateResult.scope1.limChar, updateResult.editRange.delta);
                _this.applyDeltaPosition(updateResult.script1, editRange.limChar, editRange.delta);
                _this.applyDeltaPosition(updateResult.script2, 0, editRange.minChar);
                _this.mergeLocationInfo(updateResult.script1, updateResult.script2, editRange);
                _this.replaceAST(updateResult.script1, updateResult.scope1, updateResult.scope2);
            });
        };
        IncrementalParser.prototype.replaceAST = function (script, oldAst, newAst) {
            var _this = this;
            var pre = function (cur, parent, walker) {
                if(cur === oldAst) {
                    newAst.preComments = cur.preComments;
                    newAst.postComments = cur.postComments;
                    _this.logger.log("replaced old AST node with new one in script AST");
                    walker.options.stopWalk();
                    return newAst;
                }
                if(TypeScript.isValidAstNode(cur)) {
                    if(cur.limChar < oldAst.minChar || cur.minChar > oldAst.limChar) {
                        walker.options.goChildren = false;
                    }
                }
                return cur;
            };
            TypeScript.getAstWalkerFactory().walk(script, pre);
        };
        IncrementalParser.prototype.mergeLocationInfo = function (script, partial, editRange) {
            var lineMap1 = script.locationInfo.lineMap;
            var lineMap2 = partial.locationInfo.lineMap;
            if(this.logger.information()) {
                this.logger.log("lineMap1 (before):");
                this.astLogger.logLinemap(lineMap1);
                this.logger.log("lineMap2 (quick parse):");
                this.astLogger.logLinemap(lineMap2);
                this.logger.log("EditRange=" + editRange);
            }
            var i1 = 2;
            var i2 = 2;
            var len1 = lineMap1.length;
            var len2 = lineMap2.length;
            while(i1 < len1) {
                if(lineMap1[i1] <= editRange.minChar) {
                    i1++;
                } else {
                    if(lineMap1[i1] >= editRange.limChar) {
                        lineMap1[i1] += editRange.delta;
                        i1++;
                    } else {
                        if(i2 < len2) {
                            lineMap1.splice(i1, 0, lineMap2[i2] + editRange.minChar);
                            i1++;
                            len1++;
                            i2++;
                        } else {
                            lineMap1.splice(i1, 1);
                            len1--;
                        }
                    }
                }
            }
            if(i2 < len2) {
                if(lineMap1[len1 - 1] >= (lineMap2[i2] + editRange.minChar)) {
                    i1 = 2;
                    while(i1 < len1 && i2 < len2) {
                        if(lineMap1[i1] < (lineMap2[i2] + editRange.minChar)) {
                            i1++;
                        } else {
                            lineMap1.splice(i1, 0, lineMap2[i2] + editRange.minChar);
                            i1++;
                            len1++;
                            i2++;
                        }
                    }
                }
                for(; i2 < len2; i2++) {
                    lineMap1.push(lineMap2[i2] + editRange.minChar);
                }
            }
            if(this.logger.information()) {
                this.logger.log("lineMap1 (after merge):");
                this.astLogger.logLinemap(lineMap1);
            }
        };
        IncrementalParser.prototype.applyDeltaPosition = function (ast, start, delta) {
            var applyDelta = function (ast) {
                if(ast.minChar !== -1 && ast.minChar >= start) {
                    ast.minChar += delta;
                }
                if(ast.limChar !== -1 && ast.limChar >= start) {
                    ast.limChar += delta;
                }
            };
            var applyDeltaToComments = function (comments) {
                if(comments && comments.length > 0) {
                    for(var i = 0; i < comments.length; i++) {
                        applyDelta(comments[i]);
                    }
                }
            };
            var pre = function (cur, parent, walker) {
                if(cur.limChar !== -1 && cur.limChar < start) {
                    walker.options.goChildren = false;
                }
                applyDelta(cur);
                applyDeltaToComments(cur.preComments);
                applyDeltaToComments(cur.postComments);
                return cur;
            };
            TypeScript.getAstWalkerFactory().walk(ast, pre);
        };
        return IncrementalParser;
    })();
    TypeScript.IncrementalParser = IncrementalParser;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    var DeclFileWriter = (function () {
        function DeclFileWriter(declFile) {
            this.declFile = declFile;
            this.onNewLine = true;
        }
        DeclFileWriter.prototype.Write = function (s) {
            this.declFile.Write(s);
            this.onNewLine = false;
        };
        DeclFileWriter.prototype.WriteLine = function (s) {
            this.declFile.WriteLine(s);
            this.onNewLine = true;
        };
        DeclFileWriter.prototype.Close = function () {
            this.declFile.Close();
        };
        return DeclFileWriter;
    })();
    TypeScript.DeclFileWriter = DeclFileWriter;    
    var DeclarationEmitter = (function () {
        function DeclarationEmitter(checker, emitOptions, errorReporter) {
            this.checker = checker;
            this.emitOptions = emitOptions;
            this.errorReporter = errorReporter;
            this.declFile = null;
            this.indenter = new TypeScript.Indenter();
            this.declarationContainerStack = [];
            this.isDottedModuleName = [];
            this.ignoreCallbackAst = null;
            this.singleDeclFile = null;
            this.varListCount = 0;
        }
        DeclarationEmitter.prototype.getAstDeclarationContainer = function () {
            return this.declarationContainerStack[this.declarationContainerStack.length - 1];
        };
        DeclarationEmitter.prototype.emitDottedModuleName = function () {
            return (this.isDottedModuleName.length == 0) ? false : this.isDottedModuleName[this.isDottedModuleName.length - 1];
        };
        DeclarationEmitter.prototype.setDeclarationFile = function (file) {
            this.declFile = new DeclFileWriter(file);
        };
        DeclarationEmitter.prototype.Close = function () {
            try  {
                this.declFile.Close();
            } catch (ex) {
                this.errorReporter.emitterError(null, ex.message);
            }
        };
        DeclarationEmitter.prototype.emitDeclarations = function (script) {
            TypeScript.AstWalkerWithDetailCallback.walk(script, this);
        };
        DeclarationEmitter.prototype.getIndentString = function (declIndent) {
            if (typeof declIndent === "undefined") { declIndent = false; }
            if(this.emitOptions.minWhitespace) {
                return "";
            } else {
                return this.indenter.getIndent();
            }
        };
        DeclarationEmitter.prototype.emitIndent = function () {
            this.declFile.Write(this.getIndentString());
        };
        DeclarationEmitter.prototype.canEmitSignature = function (declFlags, canEmitGlobalAmbientDecl, useDeclarationContainerTop) {
            if (typeof canEmitGlobalAmbientDecl === "undefined") { canEmitGlobalAmbientDecl = true; }
            if (typeof useDeclarationContainerTop === "undefined") { useDeclarationContainerTop = true; }
            var container;
            if(useDeclarationContainerTop) {
                container = this.getAstDeclarationContainer();
            } else {
                container = this.declarationContainerStack[this.declarationContainerStack.length - 2];
            }
            if(container.nodeType == TypeScript.NodeType.ModuleDeclaration && !TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.Exported)) {
                return false;
            }
            if(!canEmitGlobalAmbientDecl && container.nodeType == TypeScript.NodeType.Script && TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.Ambient)) {
                return false;
            }
            return true;
        };
        DeclarationEmitter.prototype.canEmitPrePostAstSignature = function (declFlags, astWithPrePostCallback, preCallback) {
            if(this.ignoreCallbackAst) {
                TypeScript.CompilerDiagnostics.assert(this.ignoreCallbackAst != astWithPrePostCallback, "Ignore Callback AST mismatch");
                this.ignoreCallbackAst = null;
                return false;
            } else {
                if(preCallback && !this.canEmitSignature(declFlags, true, preCallback)) {
                    this.ignoreCallbackAst = astWithPrePostCallback;
                    return false;
                }
            }
            return true;
        };
        DeclarationEmitter.prototype.getDeclFlagsString = function (declFlags, typeString) {
            var result = this.getIndentString();
            var accessorString = "";
            if(TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.GetAccessor)) {
                accessorString = "get ";
            } else {
                if(TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.SetAccessor)) {
                    accessorString = "set ";
                }
            }
            var container = this.getAstDeclarationContainer();
            if(container.nodeType == TypeScript.NodeType.ModuleDeclaration && TypeScript.hasFlag((container).modFlags, TypeScript.ModuleFlags.IsWholeFile) && TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.Exported)) {
                result += "export ";
            }
            if(TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.LocalStatic) || TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.Static)) {
                result += "static " + accessorString;
            } else {
                if(TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.Private)) {
                    result += "private " + accessorString;
                } else {
                    if(TypeScript.hasFlag(declFlags, TypeScript.DeclFlags.Public)) {
                        result += "public " + accessorString;
                    } else {
                        if(accessorString == "") {
                            result += typeString + " ";
                        } else {
                            result += accessorString;
                        }
                    }
                }
            }
            return result;
        };
        DeclarationEmitter.prototype.emitDeclFlags = function (declFlags, typeString) {
            this.declFile.Write(this.getDeclFlagsString(declFlags, typeString));
        };
        DeclarationEmitter.prototype.canEmitTypeAnnotationSignature = function (declFlag) {
            if (typeof declFlag === "undefined") { declFlag = TypeScript.DeclFlags.None; }
            return !TypeScript.hasFlag(declFlag, TypeScript.DeclFlags.Private);
        };
        DeclarationEmitter.prototype.pushDeclarationContainer = function (ast) {
            this.declarationContainerStack.push(ast);
        };
        DeclarationEmitter.prototype.popDeclarationContainer = function (ast) {
            TypeScript.CompilerDiagnostics.assert(ast != this.getAstDeclarationContainer(), 'Declaration container mismatch');
            this.declarationContainerStack.pop();
        };
        DeclarationEmitter.prototype.emitTypeNamesMember = function (memberName, emitIndent) {
            if (typeof emitIndent === "undefined") { emitIndent = false; }
            if(memberName.prefix == "{ ") {
                if(emitIndent) {
                    this.emitIndent();
                }
                this.declFile.WriteLine("{");
                this.indenter.increaseIndent();
                emitIndent = true;
            } else {
                if(memberName.prefix != "") {
                    if(emitIndent) {
                        this.emitIndent();
                    }
                    this.declFile.Write(memberName.prefix);
                    emitIndent = false;
                }
            }
            if(memberName.isString()) {
                if(emitIndent) {
                    this.emitIndent();
                }
                this.declFile.Write((memberName).text);
            } else {
                var ar = memberName;
                for(var index = 0; index < ar.entries.length; index++) {
                    this.emitTypeNamesMember(ar.entries[index], emitIndent);
                    if(ar.delim == "; ") {
                        this.declFile.WriteLine(";");
                    }
                }
            }
            if(memberName.suffix == "}") {
                this.indenter.decreaseIndent();
                this.emitIndent();
                this.declFile.Write(memberName.suffix);
            } else {
                this.declFile.Write(memberName.suffix);
            }
        };
        DeclarationEmitter.prototype.emitTypeSignature = function (type) {
            var containingScope = null;
            var declarationContainerAst = this.getAstDeclarationContainer();
            switch(declarationContainerAst.nodeType) {
                case TypeScript.NodeType.ModuleDeclaration:
                case TypeScript.NodeType.InterfaceDeclaration:
                case TypeScript.NodeType.FuncDecl: {
                    if(declarationContainerAst.type) {
                        containingScope = declarationContainerAst.type.containedScope;
                    }
                    break;

                }
                case TypeScript.NodeType.Script: {
                    var script = declarationContainerAst;
                    if(script.bod) {
                        containingScope = script.bod.enclosingScope;
                    }
                    break;

                }
                case TypeScript.NodeType.ClassDeclaration: {
                    if(declarationContainerAst.type) {
                        containingScope = declarationContainerAst.type.instanceType.containedScope;
                    }
                    break;

                }
                default: {
                    TypeScript.CompilerDiagnostics.debugPrint("Unknown containing scope");

                }
            }
            var typeNameMembers = type.getScopedTypeNameEx(containingScope);
            this.emitTypeNamesMember(typeNameMembers);
        };
        DeclarationEmitter.prototype.emitComment = function (comment) {
            var text = comment.getText();
            if(this.declFile.onNewLine) {
                this.emitIndent();
            } else {
                if(!comment.isBlockComment) {
                    this.declFile.WriteLine("");
                    this.emitIndent();
                }
            }
            this.declFile.Write(text[0]);
            for(var i = 1; i < text.length; i++) {
                this.declFile.WriteLine("");
                this.emitIndent();
                this.declFile.Write(text[i]);
            }
            if(comment.endsLine || !comment.isBlockComment) {
                this.declFile.WriteLine("");
            } else {
                this.declFile.Write(" ");
            }
        };
        DeclarationEmitter.prototype.emitDeclarationComments = function (astOrSymbol, endLine) {
            if (typeof endLine === "undefined") { endLine = true; }
            if(!this.emitOptions.emitComments) {
                return;
            }
            var declComments = astOrSymbol.getDocComments();
            if(declComments.length > 0) {
                for(var i = 0; i < declComments.length; i++) {
                    this.emitComment(declComments[i]);
                }
                if(endLine) {
                    if(!this.declFile.onNewLine) {
                        this.declFile.WriteLine("");
                    }
                } else {
                    if(this.declFile.onNewLine) {
                        this.emitIndent();
                    }
                }
            }
        };
        DeclarationEmitter.prototype.VarDeclCallback = function (pre, varDecl) {
            if(pre && this.canEmitSignature(TypeScript.ToDeclFlags(varDecl.varFlags), false)) {
                var interfaceMember = (this.getAstDeclarationContainer().nodeType == TypeScript.NodeType.InterfaceDeclaration);
                this.emitDeclarationComments(varDecl);
                if(!interfaceMember) {
                    if(this.varListCount >= 0) {
                        this.emitDeclFlags(TypeScript.ToDeclFlags(varDecl.varFlags), "var");
                        this.varListCount = -this.varListCount;
                    }
                    this.declFile.Write(varDecl.id.text);
                } else {
                    this.emitIndent();
                    this.declFile.Write(varDecl.id.text);
                    if(TypeScript.hasFlag(varDecl.id.flags, TypeScript.ASTFlags.OptionalName)) {
                        this.declFile.Write("?");
                    }
                }
                var type = null;
                if(varDecl.typeExpr && varDecl.typeExpr.type) {
                    type = varDecl.typeExpr.type;
                } else {
                    if(varDecl.sym) {
                        type = (varDecl.sym).getType();
                        if(type == this.checker.anyType) {
                            type = null;
                        }
                    }
                }
                if(type && this.canEmitTypeAnnotationSignature(TypeScript.ToDeclFlags(varDecl.varFlags))) {
                    this.declFile.Write(": ");
                    this.emitTypeSignature(type);
                }
                if(this.varListCount > 0) {
                    this.varListCount--;
                } else {
                    if(this.varListCount < 0) {
                        this.varListCount++;
                    }
                }
                if(this.varListCount < 0) {
                    this.declFile.Write(", ");
                } else {
                    this.declFile.WriteLine(";");
                }
            }
            return false;
        };
        DeclarationEmitter.prototype.BlockCallback = function (pre, block) {
            if(!block.isStatementBlock) {
                if(pre) {
                    this.varListCount = block.statements.members.length;
                } else {
                    this.varListCount = 0;
                }
                return true;
            }
            return false;
        };
        DeclarationEmitter.prototype.emitArgDecl = function (argDecl, funcDecl) {
            this.emitDeclarationComments(argDecl, false);
            this.declFile.Write(argDecl.id.text);
            if(argDecl.isOptionalArg()) {
                this.declFile.Write("?");
            }
            if((argDecl.typeExpr || argDecl.type != this.checker.anyType) && this.canEmitTypeAnnotationSignature(TypeScript.ToDeclFlags(funcDecl.fncFlags))) {
                this.declFile.Write(": ");
                this.emitTypeSignature(argDecl.type);
            }
        };
        DeclarationEmitter.prototype.FuncDeclCallback = function (pre, funcDecl) {
            if(!pre) {
                return false;
            }
            if(funcDecl.isAccessor()) {
                return this.emitPropertyAccessorSignature(funcDecl);
            }
            var isInterfaceMember = (this.getAstDeclarationContainer().nodeType == TypeScript.NodeType.InterfaceDeclaration);
            if(funcDecl.bod) {
                if(funcDecl.isConstructor) {
                    if(funcDecl.type.construct && funcDecl.type.construct.signatures.length > 1) {
                        return false;
                    }
                } else {
                    if(funcDecl.type.call && funcDecl.type.call.signatures.length > 1) {
                        return false;
                    }
                }
            } else {
                if(!isInterfaceMember && TypeScript.hasFlag(funcDecl.fncFlags, TypeScript.FncFlags.Private) && funcDecl.type.call && funcDecl.type.call.signatures.length > 1) {
                    var signatures = funcDecl.type.call.signatures;
                    var firstSignature = signatures[0].declAST;
                    if(firstSignature.bod) {
                        firstSignature = signatures[1].declAST;
                    }
                    if(firstSignature != funcDecl) {
                        return false;
                    }
                }
            }
            if(!this.canEmitSignature(TypeScript.ToDeclFlags(funcDecl.fncFlags), false)) {
                return false;
            }
            this.emitDeclarationComments(funcDecl);
            if(funcDecl.isConstructor) {
                this.emitIndent();
                this.declFile.Write("constructor");
            } else {
                var id = funcDecl.getNameText();
                if(!isInterfaceMember) {
                    this.emitDeclFlags(TypeScript.ToDeclFlags(funcDecl.fncFlags), "function");
                    this.declFile.Write(id);
                } else {
                    this.emitIndent();
                    if(funcDecl.isConstructMember()) {
                        this.declFile.Write("new");
                    } else {
                        if(!funcDecl.isCallMember() && !funcDecl.isIndexerMember()) {
                            this.declFile.Write(id);
                            if(TypeScript.hasFlag(funcDecl.name.flags, TypeScript.ASTFlags.OptionalName)) {
                                this.declFile.Write("? ");
                            }
                        }
                    }
                }
            }
            if(!funcDecl.isIndexerMember()) {
                this.declFile.Write("(");
            } else {
                this.declFile.Write("[");
            }
            this.indenter.increaseIndent();
            if(funcDecl.arguments) {
                var argsLen = funcDecl.arguments.members.length;
                if(funcDecl.variableArgList) {
                    argsLen--;
                }
                for(var i = 0; i < argsLen; i++) {
                    var argDecl = funcDecl.arguments.members[i];
                    this.emitArgDecl(argDecl, funcDecl);
                    if(i < (argsLen - 1)) {
                        this.declFile.Write(", ");
                    }
                }
            }
            if(funcDecl.variableArgList) {
                var lastArg = funcDecl.arguments.members[funcDecl.arguments.members.length - 1];
                if(funcDecl.arguments.members.length > 1) {
                    this.declFile.Write(", ...");
                } else {
                    this.declFile.Write("...");
                }
                this.emitArgDecl(lastArg, funcDecl);
            }
            this.indenter.decreaseIndent();
            if(!funcDecl.isIndexerMember()) {
                this.declFile.Write(")");
            } else {
                this.declFile.Write("]");
            }
            if(!funcDecl.isConstructor && (funcDecl.returnTypeAnnotation || funcDecl.signature.returnType.type != this.checker.anyType) && this.canEmitTypeAnnotationSignature(TypeScript.ToDeclFlags(funcDecl.fncFlags))) {
                this.declFile.Write(": ");
                this.emitTypeSignature(funcDecl.signature.returnType.type);
            }
            this.declFile.WriteLine(";");
            return false;
        };
        DeclarationEmitter.prototype.emitBaseList = function (bases, qual) {
            if(bases && (bases.members.length > 0)) {
                this.declFile.Write(" " + qual + " ");
                var basesLen = bases.members.length;
                for(var i = 0; i < basesLen; i++) {
                    var baseExpr = bases.members[i];
                    var baseSymbol = baseExpr.type.symbol;
                    var baseType = baseExpr.type;
                    if(i > 0) {
                        this.declFile.Write(", ");
                    }
                    this.emitTypeSignature(baseType);
                }
            }
        };
        DeclarationEmitter.prototype.emitPropertyAccessorSignature = function (funcDecl) {
            var accessorSymbol = funcDecl.accessorSymbol;
            if(accessorSymbol.getter && accessorSymbol.getter.declAST != funcDecl) {
                return false;
            }
            this.emitDeclarationComments(accessorSymbol);
            this.emitDeclFlags(TypeScript.ToDeclFlags(accessorSymbol.flags), "var");
            this.declFile.Write(funcDecl.name.text);
            var propertyType = accessorSymbol.getType();
            if(this.canEmitTypeAnnotationSignature(TypeScript.ToDeclFlags(accessorSymbol.flags))) {
                this.declFile.Write(" : ");
                this.emitTypeSignature(propertyType);
            }
            this.declFile.WriteLine(";");
            return false;
        };
        DeclarationEmitter.prototype.emitClassMembersFromConstructorDefinition = function (funcDecl) {
            if(funcDecl.arguments) {
                var argsLen = funcDecl.arguments.members.length;
                if(funcDecl.variableArgList) {
                    argsLen--;
                }
                for(var i = 0; i < argsLen; i++) {
                    var argDecl = funcDecl.arguments.members[i];
                    if(TypeScript.hasFlag(argDecl.varFlags, TypeScript.VarFlags.Property)) {
                        this.emitDeclarationComments(argDecl);
                        this.emitDeclFlags(TypeScript.ToDeclFlags(argDecl.varFlags), "var");
                        this.declFile.Write(argDecl.id.text);
                        if(argDecl.typeExpr && this.canEmitTypeAnnotationSignature(TypeScript.ToDeclFlags(argDecl.varFlags))) {
                            this.declFile.Write(": ");
                            this.emitTypeSignature(argDecl.type);
                        }
                        this.declFile.WriteLine(";");
                    }
                }
            }
        };
        DeclarationEmitter.prototype.ClassDeclarationCallback = function (pre, classDecl) {
            if(!this.canEmitPrePostAstSignature(TypeScript.ToDeclFlags(classDecl.varFlags), classDecl, pre)) {
                return false;
            }
            if(pre) {
                var className = classDecl.name.text;
                this.emitDeclarationComments(classDecl);
                this.emitDeclFlags(TypeScript.ToDeclFlags(classDecl.varFlags), "class");
                this.declFile.Write(className);
                this.emitBaseList(classDecl.extendsList, "extends");
                this.emitBaseList(classDecl.implementsList, "implements");
                this.declFile.WriteLine(" {");
                this.pushDeclarationContainer(classDecl);
                this.indenter.increaseIndent();
                if(classDecl.constructorDecl) {
                    this.emitClassMembersFromConstructorDefinition(classDecl.constructorDecl);
                }
            } else {
                this.indenter.decreaseIndent();
                this.popDeclarationContainer(classDecl);
                this.emitIndent();
                this.declFile.WriteLine("}");
            }
            return true;
        };
        DeclarationEmitter.prototype.InterfaceDeclarationCallback = function (pre, interfaceDecl) {
            if(!this.canEmitPrePostAstSignature(TypeScript.ToDeclFlags(interfaceDecl.varFlags), interfaceDecl, pre)) {
                return false;
            }
            if(pre) {
                var interfaceName = interfaceDecl.name.text;
                this.emitDeclarationComments(interfaceDecl);
                this.emitDeclFlags(TypeScript.ToDeclFlags(interfaceDecl.varFlags), "interface");
                this.declFile.Write(interfaceName);
                this.emitBaseList(interfaceDecl.extendsList, "extends");
                this.declFile.WriteLine(" {");
                this.indenter.increaseIndent();
                this.pushDeclarationContainer(interfaceDecl);
            } else {
                this.indenter.decreaseIndent();
                this.popDeclarationContainer(interfaceDecl);
                this.emitIndent();
                this.declFile.WriteLine("}");
            }
            return true;
        };
        DeclarationEmitter.prototype.ImportDeclarationCallback = function (pre, importDecl) {
            if(pre) {
                if((this.declarationContainerStack[0]).isExternallyVisibleSymbol(importDecl.id.sym)) {
                    this.emitDeclarationComments(importDecl);
                    this.emitIndent();
                    this.declFile.Write("import ");
                    this.declFile.Write(importDecl.id.text + " = ");
                    if(importDecl.isDynamicImport) {
                        this.declFile.WriteLine("module (" + importDecl.getAliasName() + ");");
                    } else {
                        this.declFile.WriteLine(importDecl.getAliasName() + ";");
                    }
                }
            }
            return false;
        };
        DeclarationEmitter.prototype.emitEnumSignature = function (moduleDecl) {
            if(!this.canEmitSignature(TypeScript.ToDeclFlags(moduleDecl.modFlags))) {
                return false;
            }
            this.emitDeclarationComments(moduleDecl);
            this.emitDeclFlags(TypeScript.ToDeclFlags(moduleDecl.modFlags), "enum");
            this.declFile.WriteLine(moduleDecl.name.text + " {");
            this.indenter.increaseIndent();
            var membersLen = moduleDecl.members.members.length;
            for(var j = 1; j < membersLen; j++) {
                var memberDecl = moduleDecl.members.members[j];
                if(memberDecl.nodeType == TypeScript.NodeType.VarDecl) {
                    this.emitDeclarationComments(memberDecl);
                    this.emitIndent();
                    this.declFile.WriteLine((memberDecl).id.text + ",");
                } else {
                    TypeScript.CompilerDiagnostics.assert(memberDecl.nodeType != TypeScript.NodeType.Asg, "We want to catch this");
                }
            }
            this.indenter.decreaseIndent();
            this.emitIndent();
            this.declFile.WriteLine("}");
            return false;
        };
        DeclarationEmitter.prototype.ModuleDeclarationCallback = function (pre, moduleDecl) {
            if(TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.IsWholeFile)) {
                if(TypeScript.hasFlag(moduleDecl.modFlags, TypeScript.ModuleFlags.IsDynamic)) {
                    if(pre) {
                        if(!this.emitOptions.outputMany) {
                            this.singleDeclFile = this.declFile;
                            TypeScript.CompilerDiagnostics.assert(this.indenter.indentAmt == 0, "Indent has to be 0 when outputing new file");
                            var declareFileName = this.emitOptions.mapOutputFileName(TypeScript.stripQuotes(moduleDecl.name.sym.name), TypeScript.TypeScriptCompiler.mapToDTSFileName);
                            var useUTF8InOutputfile = moduleDecl.containsUnicodeChar || (this.emitOptions.emitComments && moduleDecl.containsUnicodeCharInComment);
                            try  {
                                this.declFile = new DeclFileWriter(this.emitOptions.ioHost.createFile(declareFileName, useUTF8InOutputfile));
                            } catch (ex) {
                                this.errorReporter.emitterError(null, ex.message);
                            }
                        }
                        this.pushDeclarationContainer(moduleDecl);
                    } else {
                        if(!this.emitOptions.outputMany) {
                            TypeScript.CompilerDiagnostics.assert(this.singleDeclFile != this.declFile, "singleDeclFile cannot be null as we are going to revert back to it");
                            TypeScript.CompilerDiagnostics.assert(this.indenter.indentAmt == 0, "Indent has to be 0 when outputing new file");
                            try  {
                                this.declFile.Close();
                            } catch (ex) {
                                this.errorReporter.emitterError(null, ex.message);
                            }
                            this.declFile = this.singleDeclFile;
                        }
                        this.popDeclarationContainer(moduleDecl);
                    }
                }
                return true;
            }
            if(moduleDecl.isEnum()) {
                if(pre) {
                    this.emitEnumSignature(moduleDecl);
                }
                return false;
            }
            if(!this.canEmitPrePostAstSignature(TypeScript.ToDeclFlags(moduleDecl.modFlags), moduleDecl, pre)) {
                return false;
            }
            if(pre) {
                if(this.emitDottedModuleName()) {
                    this.dottedModuleEmit += ".";
                } else {
                    this.dottedModuleEmit = this.getDeclFlagsString(TypeScript.ToDeclFlags(moduleDecl.modFlags), "module");
                }
                this.dottedModuleEmit += moduleDecl.name.text;
                var isCurrentModuleDotted = (moduleDecl.members.members.length == 1 && moduleDecl.members.members[0].nodeType == TypeScript.NodeType.ModuleDeclaration && !(moduleDecl.members.members[0]).isEnum() && TypeScript.hasFlag((moduleDecl.members.members[0]).modFlags, TypeScript.ModuleFlags.Exported));
                var moduleDeclComments = moduleDecl.getDocComments();
                isCurrentModuleDotted = isCurrentModuleDotted && (moduleDeclComments == null || moduleDeclComments.length == 0);
                this.isDottedModuleName.push(isCurrentModuleDotted);
                this.pushDeclarationContainer(moduleDecl);
                if(!isCurrentModuleDotted) {
                    this.emitDeclarationComments(moduleDecl);
                    this.declFile.Write(this.dottedModuleEmit);
                    this.declFile.WriteLine(" {");
                    this.indenter.increaseIndent();
                }
            } else {
                if(!this.emitDottedModuleName()) {
                    this.indenter.decreaseIndent();
                    this.emitIndent();
                    this.declFile.WriteLine("}");
                }
                this.popDeclarationContainer(moduleDecl);
                this.isDottedModuleName.pop();
            }
            return true;
        };
        DeclarationEmitter.prototype.ScriptCallback = function (pre, script) {
            if(pre) {
                if(this.emitOptions.outputMany) {
                    for(var i = 0; i < script.referencedFiles.length; i++) {
                        var referencePath = script.referencedFiles[i].path;
                        var declareFileName;
                        if(TypeScript.isRooted(referencePath)) {
                            declareFileName = this.emitOptions.mapOutputFileName(referencePath, TypeScript.TypeScriptCompiler.mapToDTSFileName);
                        } else {
                            declareFileName = TypeScript.getDeclareFilePath(script.referencedFiles[i].path);
                        }
                        this.declFile.WriteLine('/// <reference path="' + declareFileName + '" />');
                    }
                }
                this.pushDeclarationContainer(script);
            } else {
                this.popDeclarationContainer(script);
            }
            return true;
        };
        DeclarationEmitter.prototype.DefaultCallback = function (pre, ast) {
            return !TypeScript.hasFlag(ast.flags, TypeScript.ASTFlags.IsStatement);
        };
        return DeclarationEmitter;
    })();
    TypeScript.DeclarationEmitter = DeclarationEmitter;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (UpdateUnitKind) {
        UpdateUnitKind._map = [];
        UpdateUnitKind._map[0] = "Unknown";
        UpdateUnitKind.Unknown = 0;
        UpdateUnitKind._map[1] = "NoEdits";
        UpdateUnitKind.NoEdits = 1;
        UpdateUnitKind._map[2] = "EditsInsideSingleScope";
        UpdateUnitKind.EditsInsideSingleScope = 2;
    })(TypeScript.UpdateUnitKind || (TypeScript.UpdateUnitKind = {}));
    var UpdateUnitKind = TypeScript.UpdateUnitKind;
    var ScriptEditRange = (function () {
        function ScriptEditRange(minChar, limChar, delta) {
            this.minChar = minChar;
            this.limChar = limChar;
            this.delta = delta;
        }
        ScriptEditRange.unknown = function unknown() {
            return new ScriptEditRange(-1, -1, -1);
        }
        ScriptEditRange.prototype.isUnknown = function () {
            return this.minChar === -1 && this.limChar === -1 && this.delta === -1;
        };
        ScriptEditRange.prototype.containsPosition = function (pos) {
            return (this.minChar <= pos && pos < this.limChar) || (this.minChar <= pos && pos < this.limChar + this.delta);
        };
        ScriptEditRange.prototype.toString = function () {
            return "editRange(minChar=" + this.minChar + ", limChar=" + this.limChar + ", delta=" + this.delta + ")";
        };
        return ScriptEditRange;
    })();
    TypeScript.ScriptEditRange = ScriptEditRange;    
    var UpdateUnitResult = (function () {
        function UpdateUnitResult(kind, unitIndex, script1, script2) {
            this.kind = kind;
            this.unitIndex = unitIndex;
            this.script1 = script1;
            this.script2 = script2;
            this.scope1 = null;
            this.scope2 = null;
            this.editRange = null;
            this.parseErrors = [];
        }
        UpdateUnitResult.noEdits = function noEdits(unitIndex) {
            return new UpdateUnitResult(UpdateUnitKind.NoEdits, unitIndex, null, null);
        }
        UpdateUnitResult.unknownEdits = function unknownEdits(script1, script2, parseErrors) {
            var result = new UpdateUnitResult(UpdateUnitKind.Unknown, script1.locationInfo.unitIndex, script1, script2);
            result.parseErrors = parseErrors;
            return result;
        }
        UpdateUnitResult.singleScopeEdits = function singleScopeEdits(script1, script2, scope1, scope2, editRange, parseErrors) {
            var result = new UpdateUnitResult(UpdateUnitKind.EditsInsideSingleScope, script1.locationInfo.unitIndex, script1, script2);
            result.scope1 = scope1;
            result.scope2 = scope2;
            result.editRange = editRange;
            result.parseErrors = parseErrors;
            return result;
        }
        return UpdateUnitResult;
    })();
    TypeScript.UpdateUnitResult = UpdateUnitResult;    
    var ErrorEntry = (function () {
        function ErrorEntry(unitIndex, minChar, limChar, message) {
            this.unitIndex = unitIndex;
            this.minChar = minChar;
            this.limChar = limChar;
            this.message = message;
        }
        return ErrorEntry;
    })();
    TypeScript.ErrorEntry = ErrorEntry;    
    TypeScript.defaultSettings = new TypeScript.CompilationSettings();
    var TypeScriptCompiler = (function () {
        function TypeScriptCompiler(errorOutput, logger, settings) {
            if (typeof logger === "undefined") { logger = new TypeScript.NullLogger(); }
            if (typeof settings === "undefined") { settings = TypeScript.defaultSettings; }
            this.errorOutput = errorOutput;
            this.logger = logger;
            this.settings = settings;
            this.parser = new TypeScript.Parser();
            this.typeFlow = null;
            this.scripts = new TypeScript.ASTList();
            this.units = new Array();
            this.errorReporter = new TypeScript.ErrorReporter(this.errorOutput);
            this.persistentTypeState = new TypeScript.PersistentGlobalTypeState(this.errorReporter);
            this.errorReporter.parser = this.parser;
            this.initTypeChecker(this.errorOutput);
            this.parser.style_requireSemi = this.settings.styleSettings.requireSemi;
            this.parser.style_funcInLoop = this.settings.styleSettings.funcInLoop;
            this.parser.inferPropertiesFromThisAssignment = this.settings.inferPropertiesFromThisAssignment;
            this.emitSettings = new TypeScript.EmitOptions(this.settings);
            TypeScript.codeGenTarget = settings.codeGenTarget;
        }
        TypeScriptCompiler.prototype.timeFunction = function (funcDescription, func) {
            return TypeScript.timeFunction(this.logger, funcDescription, func);
        };
        TypeScriptCompiler.prototype.initTypeChecker = function (errorOutput) {
            this.persistentTypeState.refreshPersistentState();
            this.typeChecker = new TypeScript.TypeChecker(this.persistentTypeState);
            this.typeChecker.errorReporter = this.errorReporter;
            this.typeChecker.checkControlFlow = this.settings.controlFlow;
            this.typeChecker.checkControlFlowUseDef = this.settings.controlFlowUseDef;
            this.typeChecker.printControlFlowGraph = this.settings.printControlFlow;
            this.typeChecker.errorsOnWith = this.settings.errorOnWith;
            this.typeChecker.styleSettings = this.settings.styleSettings;
            this.typeChecker.canCallDefinitionSignature = this.settings.canCallDefinitionSignature;
            this.errorReporter.checker = this.typeChecker;
            this.setErrorOutput(this.errorOutput);
        };
        TypeScriptCompiler.prototype.setErrorOutput = function (outerr) {
            this.errorOutput = outerr;
            this.errorReporter.setErrOut(outerr);
            this.parser.outfile = outerr;
        };
        TypeScriptCompiler.prototype.emitCommentsToOutput = function () {
            this.emitSettings = new TypeScript.EmitOptions(this.settings);
        };
        TypeScriptCompiler.prototype.setErrorCallback = function (fn) {
            this.parser.errorCallback = fn;
        };
        TypeScriptCompiler.prototype.updateUnit = function (prog, filename, setRecovery) {
            return this.updateSourceUnit(new TypeScript.StringSourceText(prog), filename, setRecovery);
        };
        TypeScriptCompiler.prototype.updateSourceUnit = function (sourceText, filename, setRecovery) {
            var _this = this;
            return this.timeFunction("updateSourceUnit(" + filename + ")", function () {
                var updateResult = _this.partialUpdateUnit(sourceText, filename, setRecovery);
                return _this.applyUpdateResult(updateResult);
            });
        };
        TypeScriptCompiler.prototype.applyUpdateResult = function (updateResult) {
            switch(updateResult.kind) {
                case UpdateUnitKind.NoEdits: {
                    return false;

                }
                case UpdateUnitKind.Unknown: {
                    this.scripts.members[updateResult.unitIndex] = updateResult.script2;
                    this.units[updateResult.unitIndex] = updateResult.script2.locationInfo;
                    for(var i = 0, len = updateResult.parseErrors.length; i < len; i++) {
                        var e = updateResult.parseErrors[i];
                        if(this.parser.errorCallback) {
                            this.parser.errorCallback(e.minChar, e.limChar - e.minChar, e.message, e.unitIndex);
                        }
                    }
                    return true;

                }
                case UpdateUnitKind.EditsInsideSingleScope: {
                    new TypeScript.IncrementalParser(this.logger).mergeTrees(updateResult);
                    return true;

                }
            }
        };
        TypeScriptCompiler.prototype.partialUpdateUnit = function (sourceText, filename, setRecovery) {
            var _this = this;
            return this.timeFunction("partialUpdateUnit(" + filename + ")", function () {
                for(var i = 0, len = _this.units.length; i < len; i++) {
                    if(_this.units[i].filename == filename) {
                        if((_this.scripts.members[i]).isResident) {
                            return UpdateUnitResult.noEdits(i);
                        }
                        if(setRecovery) {
                            _this.parser.setErrorRecovery(null);
                        }
                        var updateResult;
                        var parseErrors = [];
                        var errorCapture = function (minChar, charLen, message, unitIndex) {
                            parseErrors.push(new ErrorEntry(unitIndex, minChar, minChar + charLen, message));
                        };
                        var svErrorCallback = _this.parser.errorCallback;
                        if(svErrorCallback) {
                            _this.parser.errorCallback = errorCapture;
                        }
                        var oldScript = _this.scripts.members[i];
                        var newScript = _this.parser.parse(sourceText, filename, i);
                        if(svErrorCallback) {
                            _this.parser.errorCallback = svErrorCallback;
                        }
                        updateResult = UpdateUnitResult.unknownEdits(oldScript, newScript, parseErrors);
                        return updateResult;
                    }
                }
                throw new Error("Unknown file \"" + filename + "\"");
            });
        };
        TypeScriptCompiler.prototype.addUnit = function (prog, filename, keepResident, referencedFiles) {
            if (typeof keepResident === "undefined") { keepResident = false; }
            if (typeof referencedFiles === "undefined") { referencedFiles = []; }
            return this.addSourceUnit(new TypeScript.StringSourceText(prog), filename, keepResident, referencedFiles);
        };
        TypeScriptCompiler.prototype.addSourceUnit = function (sourceText, filename, keepResident, referencedFiles) {
            if (typeof referencedFiles === "undefined") { referencedFiles = []; }
            var _this = this;
            return this.timeFunction("addSourceUnit(" + filename + ", " + keepResident + ")", function () {
                var script = _this.parser.parse(sourceText, filename, _this.units.length, TypeScript.AllowedElements.Global);
                script.referencedFiles = referencedFiles;
                script.isResident = keepResident;
                _this.persistentTypeState.setCollectionMode(keepResident ? TypeScript.TypeCheckCollectionMode.Resident : TypeScript.TypeCheckCollectionMode.Transient);
                var index = _this.units.length;
                _this.units[index] = script.locationInfo;
                _this.typeChecker.collectTypes(script);
                _this.scripts.append(script);
                return script;
            });
        };
        TypeScriptCompiler.prototype.parseUnit = function (prog, filename) {
            return this.parseSourceUnit(new TypeScript.StringSourceText(prog), filename);
        };
        TypeScriptCompiler.prototype.parseSourceUnit = function (sourceText, filename) {
            this.parser.setErrorRecovery(this.errorOutput);
            var script = this.parser.parse(sourceText, filename, 0);
            var index = this.units.length;
            this.units[index] = script.locationInfo;
            this.typeChecker.collectTypes(script);
            this.scripts.append(script);
        };
        TypeScriptCompiler.prototype.typeCheck = function () {
            var _this = this;
            return this.timeFunction("typeCheck()", function () {
                var binder = new TypeScript.Binder(_this.typeChecker);
                _this.typeChecker.units = _this.units;
                binder.bind(_this.typeChecker.globalScope, _this.typeChecker.globals);
                binder.bind(_this.typeChecker.globalScope, _this.typeChecker.ambientGlobals);
                binder.bind(_this.typeChecker.globalScope, _this.typeChecker.globalTypes);
                binder.bind(_this.typeChecker.globalScope, _this.typeChecker.ambientGlobalTypes);
                _this.typeFlow = new TypeScript.TypeFlow(_this.logger, _this.typeChecker.globalScope, _this.parser, _this.typeChecker);
                var i = 0;
                var script = null;
                var len = _this.scripts.members.length;
                _this.persistentTypeState.setCollectionMode(TypeScript.TypeCheckCollectionMode.Resident);
                for(i = 0; i < len; i++) {
                    script = _this.scripts.members[i];
                    if(!script.isResident || script.hasBeenTypeChecked) {
                        continue;
                    }
                    _this.typeFlow.assignScopes(script);
                    _this.typeFlow.initLibs();
                }
                for(i = 0; i < len; i++) {
                    script = _this.scripts.members[i];
                    if(!script.isResident || script.hasBeenTypeChecked) {
                        continue;
                    }
                    _this.typeFlow.typeCheck(script);
                    script.hasBeenTypeChecked = true;
                }
                _this.persistentTypeState.setCollectionMode(TypeScript.TypeCheckCollectionMode.Transient);
                len = _this.scripts.members.length;
                for(i = 0; i < len; i++) {
                    script = _this.scripts.members[i];
                    if(script.isResident) {
                        continue;
                    }
                    _this.typeFlow.assignScopes(script);
                    _this.typeFlow.initLibs();
                }
                for(i = 0; i < len; i++) {
                    script = _this.scripts.members[i];
                    if(script.isResident) {
                        continue;
                    }
                    _this.typeFlow.typeCheck(script);
                }
                return null;
            });
        };
        TypeScriptCompiler.prototype.cleanASTTypesForReTypeCheck = function (ast) {
            function cleanASTType(ast, parent) {
                ast.type = null;
                if(ast.nodeType == TypeScript.NodeType.VarDecl) {
                    var vardecl = ast;
                    vardecl.sym = null;
                } else {
                    if(ast.nodeType == TypeScript.NodeType.ArgDecl) {
                        var argdecl = ast;
                        argdecl.sym = null;
                    } else {
                        if(ast.nodeType == TypeScript.NodeType.Name) {
                            var name = ast;
                            name.sym = null;
                        } else {
                            if(ast.nodeType == TypeScript.NodeType.FuncDecl) {
                                var funcdecl = ast;
                                funcdecl.signature = null;
                                funcdecl.freeVariables = new Array();
                                funcdecl.symbols = null;
                                funcdecl.accessorSymbol = null;
                                funcdecl.scopeType = null;
                            } else {
                                if(ast.nodeType == TypeScript.NodeType.ModuleDeclaration) {
                                    var modDecl = ast;
                                    modDecl.mod = null;
                                } else {
                                    if(ast.nodeType == TypeScript.NodeType.With) {
                                        (ast).withSym = null;
                                    } else {
                                        if(ast.nodeType == TypeScript.NodeType.Catch) {
                                            (ast).containedScope = null;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return ast;
            }
            TypeScript.getAstWalkerFactory().walk(ast, cleanASTType);
        };
        TypeScriptCompiler.prototype.cleanTypesForReTypeCheck = function () {
            var _this = this;
            return this.timeFunction("cleanTypesForReTypeCheck()", function () {
                for(var i = 0, len = _this.scripts.members.length; i < len; i++) {
                    var script = _this.scripts.members[i];
                    if((script).isResident) {
                        continue;
                    }
                    _this.cleanASTTypesForReTypeCheck(script);
                    _this.typeChecker.collectTypes(script);
                }
                return null;
            });
        };
        TypeScriptCompiler.prototype.attemptIncrementalTypeCheck = function (updateResult) {
            return this.timeFunction("attemptIncrementalTypeCheck()", function () {
                return false;
            });
        };
        TypeScriptCompiler.prototype.reTypeCheck = function () {
            var _this = this;
            return this.timeFunction("reTypeCheck()", function () {
                TypeScript.CompilerDiagnostics.analysisPass++;
                _this.initTypeChecker(_this.errorOutput);
                _this.persistentTypeState.setCollectionMode(TypeScript.TypeCheckCollectionMode.Transient);
                _this.cleanTypesForReTypeCheck();
                return _this.typeCheck();
            });
        };
        TypeScriptCompiler.prototype.isDynamicModuleCompilation = function () {
            for(var i = 0, len = this.scripts.members.length; i < len; i++) {
                var script = this.scripts.members[i];
                if(!script.isDeclareFile && script.topLevelMod != null) {
                    return true;
                }
            }
            return false;
        };
        TypeScriptCompiler.prototype.updateCommonDirectoryPath = function () {
            var commonComponents = [];
            var commonComponentsLength = -1;
            for(var i = 0, len = this.scripts.members.length; i < len; i++) {
                var script = this.scripts.members[i];
                if(script.emitRequired(this.emitSettings)) {
                    var fileName = script.locationInfo.filename;
                    var fileComponents = TypeScript.filePathComponents(fileName);
                    if(commonComponentsLength == -1) {
                        commonComponents = fileComponents;
                        commonComponentsLength = commonComponents.length;
                    } else {
                        var updatedPath = false;
                        for(var j = 0; j < commonComponentsLength && j < fileComponents.length; j++) {
                            if(commonComponents[j] != fileComponents[j]) {
                                commonComponentsLength = j;
                                updatedPath = true;
                                if(j == 0) {
                                    this.errorReporter.emitterError(null, "Cannot find the common subdirectory path for the input files");
                                    return;
                                }
                                break;
                            }
                        }
                        if(!updatedPath && fileComponents.length < commonComponentsLength) {
                            commonComponentsLength = fileComponents.length;
                        }
                    }
                }
            }
            this.emitSettings.commonDirectoryPath = commonComponents.slice(0, commonComponentsLength).join("/") + "/";
            if(this.emitSettings.outputOption.charAt(this.emitSettings.outputOption.length - 1) != "/") {
                this.emitSettings.outputOption += "/";
            }
        };
        TypeScriptCompiler.prototype.parseEmitOption = function (ioHost) {
            this.emitSettings.ioHost = ioHost;
            if(this.emitSettings.outputOption == "") {
                this.emitSettings.outputMany = true;
                this.emitSettings.commonDirectoryPath = "";
                return;
            }
            this.emitSettings.outputOption = TypeScript.switchToForwardSlashes(this.emitSettings.ioHost.resolvePath(this.emitSettings.outputOption));
            if(this.emitSettings.ioHost.directoryExists(this.emitSettings.outputOption)) {
                this.emitSettings.outputMany = true;
            } else {
                if(this.emitSettings.ioHost.fileExists(this.emitSettings.outputOption)) {
                    this.emitSettings.outputMany = false;
                } else {
                    this.emitSettings.outputMany = !TypeScript.isJSFile(this.emitSettings.outputOption);
                }
            }
            if(this.isDynamicModuleCompilation() && !this.emitSettings.outputMany) {
                this.errorReporter.emitterError(null, "Cannot compile dynamic modules when emitting into single file");
            }
            if(this.emitSettings.outputMany) {
                this.updateCommonDirectoryPath();
            }
        };
        TypeScriptCompiler.prototype.useUTF8ForFile = function (script) {
            if(this.emitSettings.outputMany) {
                return this.outputScriptToUTF8(script);
            } else {
                return this.outputScriptsToUTF8((this.scripts.members));
            }
        };
        TypeScriptCompiler.mapToDTSFileName = function mapToDTSFileName(fileName, wholeFileNameReplaced) {
            return TypeScript.getDeclareFilePath(fileName);
        }
        TypeScriptCompiler.prototype.canEmitDeclarations = function (script) {
            if(!this.settings.generateDeclarationFiles) {
                return false;
            }
            if(!!script && (script.isDeclareFile || script.isResident || script.bod == null)) {
                return false;
            }
            return true;
        };
        TypeScriptCompiler.prototype.emitDeclarationsUnit = function (script, reuseEmitter, declarationEmitter) {
            if(!this.canEmitDeclarations(script)) {
                return null;
            }
            if(!declarationEmitter) {
                var declareFileName = this.emitSettings.mapOutputFileName(script.locationInfo.filename, TypeScriptCompiler.mapToDTSFileName);
                var declareFile = this.createFile(declareFileName, this.useUTF8ForFile(script));
                declarationEmitter = new TypeScript.DeclarationEmitter(this.typeChecker, this.emitSettings, this.errorReporter);
                declarationEmitter.setDeclarationFile(declareFile);
            }
            declarationEmitter.emitDeclarations(script);
            if(!reuseEmitter) {
                declarationEmitter.Close();
                return null;
            } else {
                return declarationEmitter;
            }
        };
        TypeScriptCompiler.prototype.emitDeclarations = function () {
            if(!this.canEmitDeclarations()) {
                return;
            }
            if(this.errorReporter.hasErrors) {
                return;
            }
            if(this.scripts.members.length == 0) {
                return;
            }
            var declarationEmitter = null;
            for(var i = 0, len = this.scripts.members.length; i < len; i++) {
                var script = this.scripts.members[i];
                if(this.emitSettings.outputMany || declarationEmitter == null) {
                    declarationEmitter = this.emitDeclarationsUnit(script, !this.emitSettings.outputMany);
                } else {
                    this.emitDeclarationsUnit(script, true, declarationEmitter);
                }
            }
            if(declarationEmitter) {
                declarationEmitter.Close();
            }
        };
        TypeScriptCompiler.mapToFileNameExtension = function mapToFileNameExtension(extension, fileName, wholeFileNameReplaced) {
            if(wholeFileNameReplaced) {
                return fileName;
            } else {
                var splitFname = fileName.split(".");
                splitFname.pop();
                return splitFname.join(".") + extension;
            }
        }
        TypeScriptCompiler.mapToJSFileName = function mapToJSFileName(fileName, wholeFileNameReplaced) {
            return TypeScriptCompiler.mapToFileNameExtension(".js", fileName, wholeFileNameReplaced);
        }
        TypeScriptCompiler.prototype.emitUnit = function (script, reuseEmitter, emitter) {
            if(!script.emitRequired(this.emitSettings)) {
                return null;
            }
            var fname = script.locationInfo.filename;
            if(!emitter) {
                var outFname = this.emitSettings.mapOutputFileName(fname, TypeScriptCompiler.mapToJSFileName);
                var outFile = this.createFile(outFname, this.useUTF8ForFile(script));
                emitter = new TypeScript.Emitter(this.typeChecker, outFname, outFile, this.emitSettings, this.errorReporter);
                if(this.settings.mapSourceFiles) {
                    emitter.setSourceMappings(new TypeScript.SourceMapper(fname, outFname, outFile, this.createFile(outFname + TypeScript.SourceMapper.MapFileExtension, false), this.errorReporter));
                }
            } else {
                if(this.settings.mapSourceFiles) {
                    emitter.setSourceMappings(new TypeScript.SourceMapper(fname, emitter.emittingFileName, emitter.outfile, emitter.sourceMapper.sourceMapOut, this.errorReporter));
                }
            }
            this.typeChecker.locationInfo = script.locationInfo;
            emitter.emitJavascript(script, TypeScript.TokenID.Comma, false);
            if(!reuseEmitter) {
                emitter.Close();
                return null;
            } else {
                return emitter;
            }
        };
        TypeScriptCompiler.prototype.emit = function (ioHost) {
            this.parseEmitOption(ioHost);
            var emitter = null;
            for(var i = 0, len = this.scripts.members.length; i < len; i++) {
                var script = this.scripts.members[i];
                if(this.emitSettings.outputMany || emitter == null) {
                    emitter = this.emitUnit(script, !this.emitSettings.outputMany);
                } else {
                    this.emitUnit(script, true, emitter);
                }
            }
            if(emitter) {
                emitter.Close();
            }
        };
        TypeScriptCompiler.prototype.emitToOutfile = function (outputFile) {
            if(this.settings.mapSourceFiles) {
                throw Error("Cannot generate source map");
            }
            if(this.settings.generateDeclarationFiles) {
                throw Error("Cannot generate declaration files");
            }
            if(this.settings.outputOption != "") {
                throw Error("Cannot parse output option");
            }
            var emitter = emitter = new TypeScript.Emitter(this.typeChecker, "stdout", outputFile, this.emitSettings, this.errorReporter);
            ; ;
            for(var i = 0, len = this.scripts.members.length; i < len; i++) {
                var script = this.scripts.members[i];
                this.typeChecker.locationInfo = script.locationInfo;
                emitter.emitJavascript(script, TypeScript.TokenID.Comma, false);
            }
        };
        TypeScriptCompiler.prototype.emitAST = function (ioHost) {
            this.parseEmitOption(ioHost);
            var outFile = null;
            var context = null;
            for(var i = 0, len = this.scripts.members.length; i < len; i++) {
                var script = this.scripts.members[i];
                if(this.emitSettings.outputMany || context == null) {
                    var fname = this.units[i].filename;
                    var mapToTxtFileName = function (fileName, wholeFileNameReplaced) {
                        return TypeScriptCompiler.mapToFileNameExtension(".txt", fileName, wholeFileNameReplaced);
                    };
                    var outFname = this.emitSettings.mapOutputFileName(fname, mapToTxtFileName);
                    outFile = this.createFile(outFname, this.useUTF8ForFile(script));
                    context = new TypeScript.PrintContext(outFile, this.parser);
                }
                TypeScript.getAstWalkerFactory().walk(script, TypeScript.prePrintAST, TypeScript.postPrintAST, null, context);
                if(this.emitSettings.outputMany) {
                    try  {
                        outFile.Close();
                    } catch (e) {
                        this.errorReporter.emitterError(null, e.message);
                    }
                }
            }
            if(!this.emitSettings.outputMany) {
                try  {
                    outFile.Close();
                } catch (e) {
                    this.errorReporter.emitterError(null, e.message);
                }
            }
        };
        TypeScriptCompiler.prototype.outputScriptToUTF8 = function (script) {
            return script.containsUnicodeChar || (this.emitSettings.emitComments && script.containsUnicodeCharInComment);
        };
        TypeScriptCompiler.prototype.outputScriptsToUTF8 = function (scripts) {
            for(var i = 0, len = scripts.length; i < len; i++) {
                var script = scripts[i];
                if(this.outputScriptToUTF8(script)) {
                    return true;
                }
            }
            return false;
        };
        TypeScriptCompiler.prototype.createFile = function (fileName, useUTF8) {
            try  {
                return this.emitSettings.ioHost.createFile(fileName, useUTF8);
            } catch (ex) {
                this.errorReporter.emitterError(null, ex.message);
            }
        };
        return TypeScriptCompiler;
    })();
    TypeScript.TypeScriptCompiler = TypeScriptCompiler;    
    var ScopeEntry = (function () {
        function ScopeEntry(name, type, sym) {
            this.name = name;
            this.type = type;
            this.sym = sym;
        }
        return ScopeEntry;
    })();
    TypeScript.ScopeEntry = ScopeEntry;    
    var ScopeTraversal = (function () {
        function ScopeTraversal(compiler) {
            this.compiler = compiler;
        }
        ScopeTraversal.prototype.getScope = function (enclosingScopeContext) {
            if(enclosingScopeContext.enclosingObjectLit && enclosingScopeContext.isMemberCompletion) {
                return enclosingScopeContext.getObjectLiteralScope();
            } else {
                if(enclosingScopeContext.isMemberCompletion) {
                    if(enclosingScopeContext.useFullAst) {
                        return this.compiler.typeFlow.findMemberScopeAtFullAst(enclosingScopeContext);
                    } else {
                        return this.compiler.typeFlow.findMemberScopeAt(enclosingScopeContext);
                    }
                } else {
                    return enclosingScopeContext.getScope();
                }
            }
        };
        ScopeTraversal.prototype.getScopeEntries = function (enclosingScopeContext) {
            var scope = this.getScope(enclosingScopeContext);
            if(scope == null) {
                return [];
            }
            var inScopeNames = new TypeScript.StringHashTable();
            var allSymbolNames = scope.getAllSymbolNames(enclosingScopeContext.isMemberCompletion);
            for(var i = 0; i < allSymbolNames.length; i++) {
                var name = allSymbolNames[i];
                if(name == TypeScript.globalId || name == "_Core" || name == "_element") {
                    continue;
                }
                inScopeNames.add(name, "");
            }
            var svModuleDecl = this.compiler.typeChecker.currentModDecl;
            this.compiler.typeChecker.currentModDecl = enclosingScopeContext.deepestModuleDecl;
            var result = this.getTypeNamesForNames(enclosingScopeContext, inScopeNames.getAllKeys(), scope);
            this.compiler.typeChecker.currentModDecl = svModuleDecl;
            return result;
        };
        ScopeTraversal.prototype.getTypeNamesForNames = function (enclosingScopeContext, allNames, scope) {
            var result = [];
            var enclosingScope = enclosingScopeContext.getScope();
            for(var i = 0; i < allNames.length; i++) {
                var name = allNames[i];
                var publicsOnly = enclosingScopeContext.publicsOnly && enclosingScopeContext.isMemberCompletion;
                var symbol = scope.find(name, publicsOnly, false);
                if(symbol == null) {
                    symbol = scope.find(name, publicsOnly, true);
                }
                var displayThisMember = symbol && symbol.flags & TypeScript.SymbolFlags.Private ? symbol.container == scope.container : true;
                if(symbol) {
                    if(displayThisMember && !TypeScript.isQuoted(symbol.name) && !TypeScript.isRelative(symbol.name)) {
                        var typeName = symbol.getType().getScopedTypeName(enclosingScope);
                        result.push(new ScopeEntry(name, typeName, symbol));
                    }
                } else {
                    if(name == "true" || name == "false") {
                        result.push(new ScopeEntry(name, "bool", this.compiler.typeChecker.booleanType.symbol));
                    }
                }
            }
            return result;
        };
        return ScopeTraversal;
    })();
    TypeScript.ScopeTraversal = ScopeTraversal;    
})(TypeScript || (TypeScript = {}));
var TypeScript;
(function (TypeScript) {
    (function (CompilerDiagnostics) {
        CompilerDiagnostics.debug = false;
        CompilerDiagnostics.diagnosticWriter = null;
        CompilerDiagnostics.analysisPass = 0;
        function Alert(output) {
            if(CompilerDiagnostics.diagnosticWriter) {
                CompilerDiagnostics.diagnosticWriter.Alert(output);
            }
        }
        CompilerDiagnostics.Alert = Alert;
        function debugPrint(s) {
            if(CompilerDiagnostics.debug) {
                Alert(s);
            }
        }
        CompilerDiagnostics.debugPrint = debugPrint;
        function assert(condition, s) {
            if(CompilerDiagnostics.debug) {
                if(!condition) {
                    Alert(s);
                }
            }
        }
        CompilerDiagnostics.assert = assert;
    })(TypeScript.CompilerDiagnostics || (TypeScript.CompilerDiagnostics = {}));
    var CompilerDiagnostics = TypeScript.CompilerDiagnostics;
    var NullLogger = (function () {
        function NullLogger() { }
        NullLogger.prototype.information = function () {
            return false;
        };
        NullLogger.prototype.debug = function () {
            return false;
        };
        NullLogger.prototype.warning = function () {
            return false;
        };
        NullLogger.prototype.error = function () {
            return false;
        };
        NullLogger.prototype.fatal = function () {
            return false;
        };
        NullLogger.prototype.log = function (s) {
        };
        return NullLogger;
    })();
    TypeScript.NullLogger = NullLogger;    
    var LoggerAdapter = (function () {
        function LoggerAdapter(logger) {
            this.logger = logger;
            this._information = this.logger.information();
            this._debug = this.logger.debug();
            this._warning = this.logger.warning();
            this._error = this.logger.error();
            this._fatal = this.logger.fatal();
        }
        LoggerAdapter.prototype.information = function () {
            return this._information;
        };
        LoggerAdapter.prototype.debug = function () {
            return this._debug;
        };
        LoggerAdapter.prototype.warning = function () {
            return this._warning;
        };
        LoggerAdapter.prototype.error = function () {
            return this._error;
        };
        LoggerAdapter.prototype.fatal = function () {
            return this._fatal;
        };
        LoggerAdapter.prototype.log = function (s) {
            this.logger.log(s);
        };
        return LoggerAdapter;
    })();
    TypeScript.LoggerAdapter = LoggerAdapter;    
    var BufferedLogger = (function () {
        function BufferedLogger() {
            this.logContents = [];
        }
        BufferedLogger.prototype.information = function () {
            return false;
        };
        BufferedLogger.prototype.debug = function () {
            return false;
        };
        BufferedLogger.prototype.warning = function () {
            return false;
        };
        BufferedLogger.prototype.error = function () {
            return false;
        };
        BufferedLogger.prototype.fatal = function () {
            return false;
        };
        BufferedLogger.prototype.log = function (s) {
            this.logContents.push(s);
        };
        return BufferedLogger;
    })();
    TypeScript.BufferedLogger = BufferedLogger;    
    function timeFunction(logger, funcDescription, func) {
        var start = +new Date();
        var result = func();
        var end = +new Date();
        logger.log(funcDescription + " completed in " + (end - start) + " msec");
        return result;
    }
    TypeScript.timeFunction = timeFunction;
    function stringToLiteral(value, length) {
        var result = "";
        var addChar = function (index) {
            var ch = value.charCodeAt(index);
            switch(ch) {
                case 9: {
                    result += "\\t";
                    break;

                }
                case 10: {
                    result += "\\n";
                    break;

                }
                case 11: {
                    result += "\\v";
                    break;

                }
                case 12: {
                    result += "\\f";
                    break;

                }
                case 13: {
                    result += "\\r";
                    break;

                }
                case 34: {
                    result += "\\\"";
                    break;

                }
                case 39: {
                    result += "\\\'";
                    break;

                }
                case 92: {
                    result += "\\";
                    break;

                }
                default: {
                    result += value.charAt(index);

                }
            }
        };
        var tooLong = (value.length > length);
        if(tooLong) {
            var mid = length >> 1;
            for(var i = 0; i < mid; i++) {
                addChar(i);
            }
            result += "(...)";
            for(var i = value.length - mid; i < value.length; i++) {
                addChar(i);
            }
        } else {
            length = value.length;
            for(var i = 0; i < length; i++) {
                addChar(i);
            }
        }
        return result;
    }
    TypeScript.stringToLiteral = stringToLiteral;
})(TypeScript || (TypeScript = {}));
var IOUtils;
(function (IOUtils) {
    function createDirectoryStructure(ioHost, dirName) {
        if(ioHost.directoryExists(dirName)) {
            return;
        }
        var parentDirectory = ioHost.dirName(dirName);
        if(parentDirectory != "") {
            createDirectoryStructure(ioHost, parentDirectory);
        }
        ioHost.createDirectory(dirName);
    }
    function createFileAndFolderStructure(ioHost, fileName, useUTF8) {
        var path = ioHost.resolvePath(fileName);
        var dirName = ioHost.dirName(path);
        createDirectoryStructure(ioHost, dirName);
        return ioHost.createFile(path, useUTF8);
    }
    IOUtils.createFileAndFolderStructure = createFileAndFolderStructure;
    function throwIOError(message, error) {
        var errorMessage = message;
        if(error && error.message) {
            errorMessage += (" " + error.message);
        }
        throw new Error(errorMessage);
    }
    IOUtils.throwIOError = throwIOError;
})(IOUtils || (IOUtils = {}));

var IO = (function () {
    function getWindowsScriptHostIO() {
        var fso = new ActiveXObject("Scripting.FileSystemObject");
        var streamObjectPool = [];
        function getStreamObject() {
            if(streamObjectPool.length > 0) {
                return streamObjectPool.pop();
            } else {
                return new ActiveXObject("ADODB.Stream");
            }
        }
        function releaseStreamObject(obj) {
            streamObjectPool.push(obj);
        }
        var args = [];
        for(var i = 0; i < WScript.Arguments.length; i++) {
            args[i] = WScript.Arguments.Item(i);
        }
        return {
            readFile: function (path) {
                try  {
                    var streamObj = getStreamObject();
                    streamObj.Open();
                    streamObj.Type = 2;
                    streamObj.Charset = 'x-ansi';
                    streamObj.LoadFromFile(path);
                    var bomChar = streamObj.ReadText(2);
                    streamObj.Position = 0;
                    if((bomChar.charCodeAt(0) == 254 && bomChar.charCodeAt(1) == 255) || (bomChar.charCodeAt(0) == 255 && bomChar.charCodeAt(1) == 254)) {
                        streamObj.Charset = 'unicode';
                    } else {
                        if(bomChar.charCodeAt(0) == 239 && bomChar.charCodeAt(1) == 187) {
                            streamObj.Charset = 'utf-8';
                        }
                    }
                    var str = streamObj.ReadText(-1);
                    streamObj.Close();
                    releaseStreamObject(streamObj);
                    return str;
                } catch (err) {
                    IOUtils.throwIOError("Error reading file \"" + path + "\".", err);
                }
            },
            writeFile: function (path, contents) {
                var file = this.createFile(path);
                file.Write(contents);
                file.Close();
            },
            fileExists: function (path) {
                return fso.FileExists(path);
            },
            resolvePath: function (path) {
                return fso.GetAbsolutePathName(path);
            },
            dirName: function (path) {
                return fso.GetParentFolderName(path);
            },
            findFile: function (rootPath, partialFilePath) {
                var path = fso.GetAbsolutePathName(rootPath) + "/" + partialFilePath;
                while(true) {
                    if(fso.FileExists(path)) {
                        try  {
                            var content = this.readFile(path);
                            return {
                                content: content,
                                path: path
                            };
                        } catch (err) {
                        }
                    } else {
                        rootPath = fso.GetParentFolderName(fso.GetAbsolutePathName(rootPath));
                        if(rootPath == "") {
                            return null;
                        } else {
                            path = fso.BuildPath(rootPath, partialFilePath);
                        }
                    }
                }
            },
            deleteFile: function (path) {
                try  {
                    if(fso.FileExists(path)) {
                        fso.DeleteFile(path, true);
                    }
                } catch (e) {
                    IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e);
                }
            },
            createFile: function (path, useUTF8) {
                try  {
                    var streamObj = getStreamObject();
                    streamObj.Charset = useUTF8 ? 'utf-8' : 'x-ansi';
                    streamObj.Open();
                    return {
                        Write: function (str) {
                            streamObj.WriteText(str, 0);
                        },
                        WriteLine: function (str) {
                            streamObj.WriteText(str, 1);
                        },
                        Close: function () {
                            try  {
                                streamObj.SaveToFile(path, 2);
                            } catch (saveError) {
                                IOUtils.throwIOError("Couldn't write to file '" + path + "'.", saveError);
                            }finally {
                                if(streamObj.State != 0) {
                                    streamObj.Close();
                                }
                                releaseStreamObject(streamObj);
                            }
                        }
                    };
                } catch (creationError) {
                    IOUtils.throwIOError("Couldn't write to file '" + path + "'.", creationError);
                }
            },
            directoryExists: function (path) {
                return fso.FolderExists(path);
            },
            createDirectory: function (path) {
                try  {
                    if(!this.directoryExists(path)) {
                        fso.CreateFolder(path);
                    }
                } catch (e) {
                    IOUtils.throwIOError("Couldn't create directory '" + path + "'.", e);
                }
            },
            dir: function (path, spec, options) {
                options = options || {
                };
                function filesInFolder(folder, root) {
                    var paths = [];
                    var fc;
                    if(options.recursive) {
                        fc = new Enumerator(folder.subfolders);
                        for(; !fc.atEnd(); fc.moveNext()) {
                            paths = paths.concat(filesInFolder(fc.item(), root + "/" + fc.item().Name));
                        }
                    }
                    fc = new Enumerator(folder.files);
                    for(; !fc.atEnd(); fc.moveNext()) {
                        if(!spec || fc.item().Name.match(spec)) {
                            paths.push(root + "/" + fc.item().Name);
                        }
                    }
                    return paths;
                }
                var folder = fso.GetFolder(path);
                var paths = [];
                return filesInFolder(folder, path);
            },
            print: function (str) {
                WScript.StdOut.Write(str);
            },
            printLine: function (str) {
                WScript.Echo(str);
            },
            arguments: args,
            stderr: WScript.StdErr,
            stdout: WScript.StdOut,
            watchFile: null,
            run: function (source, filename) {
                try  {
                    eval(source);
                } catch (e) {
                    IOUtils.throwIOError("Error while executing file '" + filename + "'.", e);
                }
            },
            getExecutingFilePath: function () {
                return WScript.ScriptFullName;
            },
            quit: function (exitCode) {
                if (typeof exitCode === "undefined") { exitCode = 0; }
                try  {
                    WScript.Quit(exitCode);
                } catch (e) {
                }
            }
        };
    }
    ; ;
    function getNodeIO() {
        var _fs = require('fs');
        var _path = require('path');
        var _module = require('module');
        return {
            readFile: function (file) {
                try  {
                    var buffer = _fs.readFileSync(file);
                    switch(buffer[0]) {
                        case 254: {
                            if(buffer[1] == 255) {
                                var i = 0;
                                while((i + 1) < buffer.length) {
                                    var temp = buffer[i];
                                    buffer[i] = buffer[i + 1];
                                    buffer[i + 1] = temp;
                                    i += 2;
                                }
                                return buffer.toString("ucs2", 2);
                            }
                            break;

                        }
                        case 255: {
                            if(buffer[1] == 254) {
                                return buffer.toString("ucs2", 2);
                            }
                            break;

                        }
                        case 239: {
                            if(buffer[1] == 187) {
                                return buffer.toString("utf8", 3);
                            }

                        }
                    }
                    return buffer.toString();
                } catch (e) {
                    IOUtils.throwIOError("Error reading file \"" + file + "\".", e);
                }
            },
            writeFile: _fs.writeFileSync,
            deleteFile: function (path) {
                try  {
                    _fs.unlinkSync(path);
                } catch (e) {
                    IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e);
                }
            },
            fileExists: function (path) {
                return _fs.existsSync(path);
            },
            createFile: function (path, useUTF8) {
                function mkdirRecursiveSync(path) {
                    var stats = _fs.statSync(path);
                    if(stats.isFile()) {
                        IOUtils.throwIOError("\"" + path + "\" exists but isn't a directory.", null);
                    } else {
                        if(stats.isDirectory()) {
                            return;
                        } else {
                            mkdirRecursiveSync(_path.dirname(path));
                            _fs.mkdirSync(path, 509);
                        }
                    }
                }
                mkdirRecursiveSync(_path.dirname(path));
                try  {
                    var fd = _fs.openSync(path, 'w');
                } catch (e) {
                    IOUtils.throwIOError("Couldn't write to file '" + path + "'.", e);
                }
                return {
                    Write: function (str) {
                        _fs.writeSync(fd, str);
                    },
                    WriteLine: function (str) {
                        _fs.writeSync(fd, str + '\r\n');
                    },
                    Close: function () {
                        _fs.closeSync(fd);
                        fd = null;
                    }
                };
            },
            dir: function dir(path, spec, options) {
                options = options || {
                };
                function filesInFolder(folder) {
                    var paths = [];
                    var files = _fs.readdirSync(folder);
                    for(var i = 0; i < files.length; i++) {
                        var stat = _fs.statSync(folder + "/" + files[i]);
                        if(options.recursive && stat.isDirectory()) {
                            paths = paths.concat(filesInFolder(folder + "/" + files[i]));
                        } else {
                            if(stat.isFile() && (!spec || files[i].match(spec))) {
                                paths.push(folder + "/" + files[i]);
                            }
                        }
                    }
                    return paths;
                }
                return filesInFolder(path);
            },
            createDirectory: function (path) {
                try  {
                    if(!this.directoryExists(path)) {
                        _fs.mkdirSync(path);
                    }
                } catch (e) {
                    IOUtils.throwIOError("Couldn't create directory '" + path + "'.", e);
                }
            },
            directoryExists: function (path) {
                return _fs.existsSync(path) && _fs.lstatSync(path).isDirectory();
            },
            resolvePath: function (path) {
                return _path.resolve(path);
            },
            dirName: function (path) {
                return _path.dirname(path);
            },
            findFile: function (rootPath, partialFilePath) {
                var path = rootPath + "/" + partialFilePath;
                while(true) {
                    if(_fs.existsSync(path)) {
                        try  {
                            var content = this.readFile(path);
                            return {
                                content: content,
                                path: path
                            };
                        } catch (err) {
                        }
                    } else {
                        var parentPath = _path.resolve(rootPath, "..");
                        if(rootPath === parentPath) {
                            return null;
                        } else {
                            rootPath = parentPath;
                            path = _path.resolve(rootPath, partialFilePath);
                        }
                    }
                }
            },
            print: function (str) {
                process.stdout.write(str);
            },
            printLine: function (str) {
                process.stdout.write(str + '\n');
            },
            arguments: process.argv.slice(2),
            stderr: {
                Write: function (str) {
                    process.stderr.write(str);
                },
                WriteLine: function (str) {
                    process.stderr.write(str + '\n');
                },
                Close: function () {
                }
            },
            stdout: {
                Write: function (str) {
                    process.stdout.write(str);
                },
                WriteLine: function (str) {
                    process.stdout.write(str + '\n');
                },
                Close: function () {
                }
            },
            watchFile: function (filename, callback) {
                var firstRun = true;
                var processingChange = false;
                var fileChanged = function (curr, prev) {
                    if(!firstRun) {
                        if(curr.mtime < prev.mtime) {
                            return;
                        }
                        _fs.unwatchFile(filename, fileChanged);
                        if(!processingChange) {
                            processingChange = true;
                            callback(filename);
                            setTimeout(function () {
                                processingChange = false;
                            }, 100);
                        }
                    }
                    firstRun = false;
                    _fs.watchFile(filename, {
                        persistent: true,
                        interval: 500
                    }, fileChanged);
                };
                fileChanged();
                return {
                    filename: filename,
                    close: function () {
                        _fs.unwatchFile(filename, fileChanged);
                    }
                };
            },
            run: function (source, filename) {
                require.main.filename = filename;
                require.main.paths = _module._nodeModulePaths(_path.dirname(_fs.realpathSync(filename)));
                require.main._compile(source, filename);
            },
            getExecutingFilePath: function () {
                return process.mainModule.filename;
            },
            quit: process.exit
        };
    }
    ; ;
    if(typeof ActiveXObject === "function") {
        return getWindowsScriptHostIO();
    } else {
        if(typeof require === "function") {
            return getNodeIO();
        } else {
            return null;
        }
    }
})();
var OptionsParser = (function () {
    function OptionsParser(host) {
        this.host = host;
        this.DEFAULT_SHORT_FLAG = "-";
        this.DEFAULT_LONG_FLAG = "--";
        this.unnamed = [];
        this.options = [];
    }
    OptionsParser.prototype.findOption = function (arg) {
        for(var i = 0; i < this.options.length; i++) {
            if(arg === this.options[i].short || arg === this.options[i].name) {
                return this.options[i];
            }
        }
        return null;
    };
    OptionsParser.prototype.printUsage = function () {
        this.host.printLine("Syntax:   tsc [options] [file ..]");
        this.host.printLine("");
        this.host.printLine("Examples: tsc hello.ts");
        this.host.printLine("          tsc --out foo.js foo.ts");
        this.host.printLine("          tsc @args.txt");
        this.host.printLine("");
        this.host.printLine("Options:");
        var output = [];
        var maxLength = 0;
        this.options = this.options.sort(function (a, b) {
            var aName = a.name.toLowerCase();
            var bName = b.name.toLowerCase();
            if(aName > bName) {
                return 1;
            } else {
                if(aName < bName) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });
        for(var i = 0; i < this.options.length; i++) {
            var option = this.options[i];
            if(option.experimental) {
                continue;
            }
            if(!option.usage) {
                break;
            }
            var usageString = "  ";
            var type = option.type ? " " + option.type.toUpperCase() : "";
            if(option.short) {
                usageString += this.DEFAULT_SHORT_FLAG + option.short + type + ", ";
            }
            usageString += this.DEFAULT_LONG_FLAG + option.name + type;
            output.push([
                usageString, 
                option.usage
            ]);
            if(usageString.length > maxLength) {
                maxLength = usageString.length;
            }
        }
        output.push([
            "  @<file>", 
            "Insert command line options and files from a file."
        ]);
        for(var i = 0; i < output.length; i++) {
            this.host.printLine(output[i][0] + (new Array(maxLength - output[i][0].length + 3)).join(" ") + output[i][1]);
        }
    };
    OptionsParser.prototype.option = function (name, config, short) {
        if(!config) {
            config = short;
            short = null;
        }
        config.name = name;
        config.short = short;
        config.flag = false;
        this.options.push(config);
    };
    OptionsParser.prototype.flag = function (name, config, short) {
        if(!config) {
            config = short;
            short = null;
        }
        config.name = name;
        config.short = short;
        config.flag = true;
        this.options.push(config);
    };
    OptionsParser.prototype.parseString = function (argString) {
        var position = 0;
        var tokens = argString.match(/\s+|"|[^\s"]+/g);
        function peek() {
            return tokens[position];
        }
        function consume() {
            return tokens[position++];
        }
        function consumeQuotedString() {
            var value = '';
            consume();
            var token = peek();
            while(token && token !== '"') {
                consume();
                value += token;
                token = peek();
            }
            consume();
            return value;
        }
        var args = [];
        var currentArg = '';
        while(position < tokens.length) {
            var token = peek();
            if(token === '"') {
                currentArg += consumeQuotedString();
            } else {
                if(token.match(/\s/)) {
                    if(currentArg.length > 0) {
                        args.push(currentArg);
                        currentArg = '';
                    }
                    consume();
                } else {
                    consume();
                    currentArg += token;
                }
            }
        }
        if(currentArg.length > 0) {
            args.push(currentArg);
        }
        this.parse(args);
    };
    OptionsParser.prototype.parse = function (args) {
        var position = 0;
        function consume() {
            return args[position++];
        }
        while(position < args.length) {
            var current = consume();
            var match = current.match(/^(--?|@)(.*)/);
            var value = null;
            if(match) {
                if(match[1] === '@') {
                    this.parseString(this.host.readFile(match[2]));
                } else {
                    var arg = match[2];
                    var option = this.findOption(arg);
                    if(option === null) {
                        this.host.printLine("Unknown option '" + arg + "'");
                        this.host.printLine("Use the '--help' flag to see options");
                    } else {
                        if(!option.flag) {
                            value = consume();
                        }
                        option.set(value);
                    }
                }
            } else {
                this.unnamed.push(current);
            }
        }
    };
    return OptionsParser;
})();
var CommandLineHost = (function () {
    function CommandLineHost(compilationSettings) {
        this.compilationSettings = compilationSettings;
        this.pathMap = {
        };
        this.resolvedPaths = {
        };
    }
    CommandLineHost.prototype.getPathIdentifier = function (path) {
        return this.compilationSettings.useCaseSensitiveFileResolution ? path : path.toLocaleUpperCase();
    };
    CommandLineHost.prototype.isResolved = function (path) {
        return this.resolvedPaths[this.getPathIdentifier(this.pathMap[path])] != undefined;
    };
    CommandLineHost.prototype.resolveCompilationEnvironment = function (preEnv, resolver, traceDependencies) {
        var _this = this;
        var resolvedEnv = new TypeScript.CompilationEnvironment(preEnv.compilationSettings, preEnv.ioHost);
        var nCode = preEnv.code.length;
        var path = "";
        var postResolutionError = function (errorFile, errorMessage) {
            TypeScript.CompilerDiagnostics.debugPrint("Could not resolve file '" + errorFile + "'" + (errorMessage == "" ? "" : ": " + errorMessage));
        };
        var resolutionDispatcher = {
            postResolutionError: postResolutionError,
            postResolution: function (path, code) {
                var pathId = _this.getPathIdentifier(path);
                if(!_this.resolvedPaths[pathId]) {
                    resolvedEnv.code.push(code);
                    _this.resolvedPaths[pathId] = true;
                }
            }
        };
        for(var i = 0; i < nCode; i++) {
            path = TypeScript.switchToForwardSlashes(preEnv.ioHost.resolvePath(preEnv.code[i].path));
            this.pathMap[preEnv.code[i].path] = path;
            resolver.resolveCode(path, "", false, resolutionDispatcher);
        }
        return resolvedEnv;
    };
    return CommandLineHost;
})();
var BatchCompiler = (function () {
    function BatchCompiler(ioHost) {
        this.ioHost = ioHost;
        this.resolvedEnvironment = null;
        this.hasResolveErrors = false;
        this.compilerVersion = "0.8.2.0";
        this.printedVersion = false;
        this.compilationSettings = new TypeScript.CompilationSettings();
        this.compilationEnvironment = new TypeScript.CompilationEnvironment(this.compilationSettings, this.ioHost);
    }
    BatchCompiler.prototype.resolve = function () {
        var resolver = new TypeScript.CodeResolver(this.compilationEnvironment);
        var commandLineHost = new CommandLineHost(this.compilationSettings);
        var ret = commandLineHost.resolveCompilationEnvironment(this.compilationEnvironment, resolver, true);
        this.hasResolveErrors = false;
        for(var i = 0; i < this.compilationEnvironment.code.length; i++) {
            if(!commandLineHost.isResolved(this.compilationEnvironment.code[i].path)) {
                this.hasResolveErrors = true;
                var path = this.compilationEnvironment.code[i].path;
                if(!TypeScript.isSTRFile(path) && !TypeScript.isDSTRFile(path) && !TypeScript.isTSFile(path) && !TypeScript.isDTSFile(path)) {
                    this.ioHost.stderr.WriteLine("Unknown extension for file: \"" + path + "\". Only .ts and .d.ts extensions are allowed.");
                } else {
                    this.ioHost.stderr.WriteLine("Error reading file \"" + path + "\": File not found");
                }
            }
        }
        return ret;
    };
    BatchCompiler.prototype.compile = function () {
        var _this = this;
        var compiler;
        compiler = new TypeScript.TypeScriptCompiler(this.ioHost.stderr, new TypeScript.NullLogger(), this.compilationSettings);
        compiler.setErrorOutput(this.ioHost.stderr);
        compiler.setErrorCallback(function (minChar, charLen, message, unitIndex) {
            compiler.errorReporter.hasErrors = true;
            var fname = _this.resolvedEnvironment.code[unitIndex].path;
            var lineCol = {
                line: -1,
                col: -1
            };
            compiler.parser.getSourceLineCol(lineCol, minChar);
            var msg = fname + " (" + lineCol.line + "," + (lineCol.col + 1) + "): " + message;
            if(_this.compilationSettings.errorRecovery) {
                _this.ioHost.stderr.WriteLine(msg);
            } else {
                throw new SyntaxError(msg);
            }
        });
        if(this.compilationSettings.emitComments) {
            compiler.emitCommentsToOutput();
        }
        var consumeUnit = function (code, addAsResident) {
            try  {
                if(!_this.compilationSettings.resolve) {
                    code.content = _this.ioHost.readFile(code.path);
                    if(_this.compilationSettings.generateDeclarationFiles) {
                        TypeScript.CompilerDiagnostics.assert(code.referencedFiles == null, "With no resolve option, referenced files need to null");
                        code.referencedFiles = TypeScript.getReferencedFiles(code);
                    }
                }
                if(code.content) {
                    if(_this.compilationSettings.parseOnly) {
                        compiler.parseUnit(code.content, code.path);
                    } else {
                        if(_this.compilationSettings.errorRecovery) {
                            compiler.parser.setErrorRecovery(_this.ioHost.stderr);
                        }
                        compiler.addUnit(code.content, code.path, addAsResident, code.referencedFiles);
                    }
                }
            } catch (err) {
                compiler.errorReporter.hasErrors = true;
                _this.ioHost.stderr.WriteLine(err.message);
            }
        };
        for(var iCode = 0; iCode < this.resolvedEnvironment.code.length; iCode++) {
            if(!this.compilationSettings.parseOnly || (iCode > 0)) {
                consumeUnit(this.resolvedEnvironment.code[iCode], false);
            }
        }
        var emitterIOHost = {
            createFile: function (fileName, useUTF8) {
                return IOUtils.createFileAndFolderStructure(_this.ioHost, fileName, useUTF8);
            },
            directoryExists: this.ioHost.directoryExists,
            fileExists: this.ioHost.fileExists,
            resolvePath: this.ioHost.resolvePath
        };
        try  {
            if(!this.compilationSettings.parseOnly) {
                compiler.typeCheck();
                compiler.emit(emitterIOHost);
                compiler.emitDeclarations();
            } else {
                compiler.emitAST(emitterIOHost);
            }
        } catch (err) {
            compiler.errorReporter.hasErrors = true;
            if(err.message != "EmitError") {
                throw err;
            }
        }
        return compiler.errorReporter.hasErrors;
    };
    BatchCompiler.prototype.run = function () {
        for(var i = 0; i < this.compilationEnvironment.code.length; i++) {
            var unit = this.compilationEnvironment.code[i];
            var outputFileName = unit.path;
            if(TypeScript.isTSFile(outputFileName)) {
                outputFileName = outputFileName.replace(/\.ts$/, ".js");
            } else {
                if(TypeScript.isSTRFile(outputFileName)) {
                    outputFileName = outputFileName.replace(/\.str$/, ".js");
                }
            }
            if(this.ioHost.fileExists(outputFileName)) {
                var unitRes = this.ioHost.readFile(outputFileName);
                this.ioHost.run(unitRes, outputFileName);
            }
        }
    };
    BatchCompiler.prototype.batchCompile = function () {
        var _this = this;
        TypeScript.CompilerDiagnostics.diagnosticWriter = {
            Alert: function (s) {
                _this.ioHost.printLine(s);
            }
        };
        var code;
        var opts = new OptionsParser(this.ioHost);
        opts.option('out', {
            usage: 'Concatenate and emit output to single file | Redirect output structure to the directory',
            type: 'file|directory',
            set: function (str) {
                _this.compilationSettings.outputOption = str;
            }
        });
        opts.option('style', {
            usage: 'Select style checking options (examples --style requireSemi:off or --style "eqeqeq;bitwise:off")',
            experimental: true,
            set: function (str) {
                _this.compilationSettings.setStyleOptions(str);
            }
        });
        opts.flag('sourcemap', {
            usage: 'Generates corresponding .map file',
            set: function () {
                _this.compilationSettings.mapSourceFiles = true;
            }
        });
        opts.flag('declaration', {
            usage: 'Generates corresponding .d.ts file',
            set: function () {
                _this.compilationSettings.generateDeclarationFiles = true;
            }
        });
        if(this.ioHost.watchFile) {
            opts.flag('watch', {
                usage: 'Watch output files',
                set: function () {
                    _this.compilationSettings.watch = true;
                }
            }, 'w');
        }
        opts.flag('exec', {
            usage: 'Execute the script after compilation',
            set: function () {
                _this.compilationSettings.exec = true;
            }
        }, 'e');
        opts.flag('parse', {
            usage: 'Parse only',
            experimental: true,
            set: function () {
                _this.compilationSettings.parseOnly = true;
            }
        });
        opts.flag('minw', {
            usage: 'Minimize whitespace',
            experimental: true,
            set: function () {
                _this.compilationSettings.minWhitespace = true;
            }
        }, 'mw');
        opts.flag('const', {
            usage: 'Propagate constants to emitted code',
            experimental: true,
            set: function () {
                _this.compilationSettings.propagateConstants = true;
            }
        });
        opts.flag('errorrecovery', {
            usage: 'Enable error recovery',
            experimental: true,
            set: function () {
                _this.compilationSettings.errorRecovery = true;
            }
        }, 'er');
        opts.flag('comments', {
            usage: 'Emit comments to output',
            set: function () {
                _this.compilationSettings.emitComments = true;
            }
        }, 'c');
        opts.flag('cflow', {
            usage: 'Control flow',
            experimental: true,
            set: function () {
                _this.compilationSettings.controlFlow = true;
            }
        });
        opts.flag('cflowp', {
            usage: 'Print control flow',
            experimental: true,
            set: function () {
                _this.compilationSettings.controlFlow = true;
                _this.compilationSettings.printControlFlow = true;
            }
        });
        opts.flag('cflowu', {
            usage: 'Print Use Def control flow',
            experimental: true,
            set: function () {
                _this.compilationSettings.controlFlow = true;
                _this.compilationSettings.controlFlowUseDef = true;
            }
        });
        opts.flag('noerroronwith', {
            usage: 'Allow with statements',
            experimental: true,
            set: function () {
                _this.compilationSettings.errorOnWith = false;
            }
        });
        opts.flag('noresolve', {
            usage: 'Skip resolution and preprocessing',
            experimental: true,
            set: function () {
                _this.compilationSettings.resolve = false;
                _this.compilationSettings.preprocess = false;
            }
        });
        opts.flag('debug', {
            usage: 'Print debug output',
            experimental: true,
            set: function () {
                TypeScript.CompilerDiagnostics.debug = true;
            }
        });
        opts.flag('canCallDefinitionSignature', {
            usage: 'Allows you to call the definition signature of an overload group',
            experimental: true,
            set: function () {
                _this.compilationSettings.canCallDefinitionSignature = true;
            }
        });
        opts.flag('nooptimizemodules', {
            usage: 'Do not optimize module codegen',
            experimental: true,
            set: function () {
                TypeScript.optimizeModuleCodeGen = false;
            }
        });
        opts.flag('nolib', {
            usage: 'Do not include a default lib.d.ts with global declarations',
            set: function () {
                _this.compilationSettings.useDefaultLib = false;
            }
        });
        opts.flag('inferProperties', {
            usage: 'Infer class properties from top-level assignments to \'this\'',
            experimental: true,
            set: function () {
                _this.compilationSettings.inferPropertiesFromThisAssignment = true;
            }
        });
        opts.option('target', {
            usage: 'Specify ECMAScript target version: "ES3" (default), or "ES5"',
            type: 'VER',
            set: function (type) {
                type = type.toLowerCase();
                if(type === 'es3') {
                    _this.compilationSettings.codeGenTarget = TypeScript.CodeGenTarget.ES3;
                } else {
                    if(type === 'es5') {
                        _this.compilationSettings.codeGenTarget = TypeScript.CodeGenTarget.ES5;
                    } else {
                        _this.ioHost.printLine("ECMAScript target version '" + type + "' not supported.  Using default 'ES3' code generation");
                    }
                }
            }
        });
        opts.option('module', {
            usage: 'Specify module code generation: "commonjs" (default) or "amd"',
            type: 'kind',
            set: function (type) {
                type = type.toLowerCase();
                if(type === 'commonjs' || type === 'node') {
                    TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Synchronous;
                } else {
                    if(type === 'amd') {
                        TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Asynchronous;
                    } else {
                        _this.ioHost.printLine("Module code generation '" + type + "' not supported.  Using default 'commonjs' code generation");
                    }
                }
            }
        });
        var printedUsage = false;
        opts.flag('help', {
            usage: 'Print this message',
            set: function () {
                _this.printVersion();
                opts.printUsage();
                printedUsage = true;
            }
        }, 'h');
        opts.flag('useCaseSensitiveFileResolution', {
            usage: 'Force file resolution to be case sensitive',
            experimental: true,
            set: function () {
                _this.compilationSettings.useCaseSensitiveFileResolution = true;
            }
        });
        opts.flag('version', {
            usage: 'Print the compiler\'s version: ' + this.compilerVersion,
            set: function () {
                _this.printVersion();
            }
        }, 'v');
        opts.parse(this.ioHost.arguments);
        if(this.compilationSettings.useDefaultLib) {
            var compilerFilePath = this.ioHost.getExecutingFilePath();
            var binDirPath = this.ioHost.dirName(compilerFilePath);
            var libStrPath = this.ioHost.resolvePath(binDirPath + "/lib.d.ts");
            code = new TypeScript.SourceUnit(libStrPath, null);
            this.compilationEnvironment.code.push(code);
        }
        for(var i = 0; i < opts.unnamed.length; i++) {
            code = new TypeScript.SourceUnit(opts.unnamed[i], null);
            this.compilationEnvironment.code.push(code);
        }
        if(this.compilationEnvironment.code.length == (this.compilationSettings.useDefaultLib ? 1 : 0)) {
            if(!printedUsage && !this.printedVersion) {
                this.printVersion();
                opts.printUsage();
                this.ioHost.quit(1);
            }
            return;
        }
        var sourceFiles = [];
        if(this.compilationSettings.watch) {
            sourceFiles = this.compilationEnvironment.code.slice(0);
        }
        this.resolvedEnvironment = this.compilationSettings.resolve ? this.resolve() : this.compilationEnvironment;
        var hasCompileErrors = this.compile();
        var hasErrors = hasCompileErrors || this.hasResolveErrors;
        if(!hasErrors) {
            if(this.compilationSettings.exec) {
                this.run();
            }
        }
        if(this.compilationSettings.watch) {
            this.watchFiles(sourceFiles);
        } else {
            this.ioHost.quit(hasErrors ? 1 : 0);
        }
    };
    BatchCompiler.prototype.printVersion = function () {
        if(!this.printedVersion) {
            this.ioHost.printLine("Version " + this.compilerVersion);
            this.printedVersion = true;
        }
    };
    BatchCompiler.prototype.watchFiles = function (soruceFiles) {
        var _this = this;
        if(!this.ioHost.watchFile) {
            this.ioHost.printLine("Error: Current host does not support -w[atch] option");
            return;
        }
        var resolvedFiles = [];
        var watchers = {
        };
        var addWatcher = function (filename) {
            if(!watchers[filename]) {
                var watcher = _this.ioHost.watchFile(filename, onWatchedFileChange);
                watchers[filename] = watcher;
            } else {
                throw new Error("Cannot watch file, it is already watched.");
            }
        };
        var removeWatcher = function (filename) {
            if(watchers[filename]) {
                watchers[filename].close();
                delete watchers[filename];
            } else {
                throw new Error("Cannot stop watching file, it is not being watched.");
            }
        };
        var onWatchedFileChange = function () {
            _this.compilationEnvironment.code = soruceFiles;
            _this.resolvedEnvironment = _this.compilationSettings.resolve ? _this.resolve() : _this.compilationEnvironment;
            var oldFiles = resolvedFiles;
            var newFiles = [];
            _this.resolvedEnvironment.code.forEach(function (sf) {
                return newFiles.push(sf.path);
            });
            newFiles = newFiles.sort();
            var i = 0, j = 0;
            while(i < oldFiles.length && j < newFiles.length) {
                var compareResult = oldFiles[i].localeCompare(newFiles[j]);
                if(compareResult == 0) {
                    i++;
                    j++;
                } else {
                    if(compareResult < 0) {
                        removeWatcher(oldFiles[i]);
                        i++;
                    } else {
                        addWatcher(newFiles[j]);
                        j++;
                    }
                }
            }
            for(var k = i; k < oldFiles.length; k++) {
                removeWatcher(oldFiles[k]);
            }
            for(var k = j; k < newFiles.length; k++) {
                addWatcher(newFiles[k]);
            }
            resolvedFiles = newFiles;
            ; ;
            _this.ioHost.printLine("");
            _this.ioHost.printLine("Recompiling (" + new Date() + "): ");
            resolvedFiles.forEach(function (f) {
                return _this.ioHost.printLine("    " + f);
            });
            var hasCompileErrors = _this.compile();
            var hasErrors = hasCompileErrors || _this.hasResolveErrors;
            if(!hasErrors) {
                if(_this.compilationSettings.exec) {
                    _this.run();
                }
            }
        };
        this.ioHost.stderr = this.ioHost.stdout;
        this.resolvedEnvironment.code.forEach(function (sf) {
            resolvedFiles.push(sf.path);
            addWatcher(sf.path);
        });
        resolvedFiles.sort();
    };
    return BatchCompiler;
})();

////////////////////////////////////////////////////////////////////////
// typescript-input.js
////////////////////////////////////////////////////////////////////////

var compiler_input = "//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\nmodule TypeScript {\n    export class AstLogger {\n\n        constructor (public logger: ILogger) { }\n\n        public logScript(script: TypeScript.Script): void {\n            this.logLinemap(script.locationInfo.lineMap);\n\n            var stack: AST[]= [];\n\n            var pre = (cur: TypeScript.AST, parent: TypeScript.AST) => {\n                stack.push(cur);\n                var indent = (stack.length - 1) * 2;\n                this.logComments(script, cur.preComments, indent);\n                this.logNode(script, cur, indent);\n                this.logComments(script, cur.postComments, indent);\n                return cur;\n            }\n\n            var post = (cur: TypeScript.AST, parent: TypeScript.AST) => {\n                stack.pop();\n                return cur;\n            }\n\n            TypeScript.getAstWalkerFactory().walk(script, pre, post);\n        }\n\n\n        public logNode(script: TypeScript.Script, cur: TypeScript.AST, indent: number) {\n            var msg = this.addPadding(\"\", indent, \"| \", true);\n\n            msg = msg.concat(\"+ \" + cur.treeViewLabel());\n            msg = this.addPadding(msg, 70, \" \", false);\n\n            msg = msg + this.addLineColumn(script, cur.minChar);\n            msg = this.addPadding(msg, 80, \" \", false);\n\n            msg = msg + \"=> \";\n            msg = msg + this.addLineColumn(script, cur.limChar);\n            msg = this.addPadding(msg, 102, \" \", false);\n\n            msg = msg.concat(\"[\" + this.addPadding(cur.minChar.toString(), 1, \" \", true) + \", \" + this.addPadding(cur.limChar.toString(), 1, \" \", true) + \"]\");\n\n            msg = this.addPadding(msg, 115, \" \", false);\n            msg = msg.concat(\"sym=\" + (<any>cur).sym);\n\n            msg = this.addPadding(msg, 135, \" \", false);\n            msg = msg.concat(\"type=\" + (cur.type === null ? \"null\" : cur.type.getTypeName()));\n            this.logger.log(msg);\n        }\n\n        private logComments(script: TypeScript.Script, comments: TypeScript.AST[], indent: number) {\n            if (comments == null)\n                return;\n\n            for (var i = 0; i < comments.length; i++) {\n                this.logNode(script, comments[i], indent);\n            }\n        }\n\n        public logLinemap(linemap: number[]) {\n            var result = \"[\";\n            for (var i = 0; i < linemap.length; i++) {\n                if (i > 0)\n                    result += \",\";\n                result += linemap[i];\n            }\n            result += \"]\";\n            this.logger.log(\"linemap: \" + result);\n        }\n\n        private addPadding(s: string, targetLength: number, paddingString: string, leftPadding: bool): string {\n            var result = (leftPadding ? \"\" : s);\n            for (var i = s.length; i < targetLength; i++) {\n                result = result + paddingString;\n            }\n            result = result + (leftPadding ? s : \"\");\n            return result;\n        }\n\n        private addLineColumn(script: TypeScript.Script, position: number): string {\n            // just for calling getSourceLineColFromMap\n            var lineInfo = {\n                line: -1,\n                col: -1\n            }\n            TypeScript.getSourceLineColFromMap(lineInfo, position, script.locationInfo.lineMap);\n\n            if (lineInfo.col !== -1) {\n                lineInfo.col++; //TODO: function above seems to consider line as 1-based, and column as 0-based\n            }\n\n            return \"(\" + lineInfo.line + \", \" + lineInfo.col + \")\";\n        }\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export function lastOf(items: any[]): any {\n        return (items === null || items.length === 0) ? null : items[items.length - 1];\n    }\n\n    export function max(a: number, b: number): number {\n        return a >= b ? a : b;\n    }\n\n    export function min(a: number, b: number): number {\n        return a <= b ? a : b;\n    }\n\n    //\n    // Helper class representing a path from a root ast node to a (grand)child ast node.\n    // This is helpful as our tree don't have parents.\n    //\n    export class AstPath {\n        public asts: TypeScript.AST[] = [];\n        public top: number = -1;\n\n        static reverseIndexOf(items: any[], index: number): any {\n            return (items === null || items.length <= index) ? null : items[items.length - index - 1];\n        }\n\n        public clone(): AstPath {\n            var clone = new AstPath();\n            clone.asts = this.asts.map((value) => { return value; });\n            clone.top = this.top;\n            return clone;\n        }\n\n        public pop(): TypeScript.AST {\n            var head = this.ast();\n            this.up();\n\n            while (this.asts.length > this.count()) {\n                this.asts.pop();\n            }\n            return head;\n        }\n\n        public push(ast: TypeScript.AST) {\n            while (this.asts.length > this.count()) {\n                this.asts.pop();\n            }\n            this.top = this.asts.length;\n            this.asts.push(ast);\n        }\n\n        public up() {\n            if (this.top <= -1)\n                throw new Error(\"Invalid call to 'up'\");\n            this.top--;\n        }\n\n        public down() {\n            if (this.top == this.ast.length - 1)\n                throw new Error(\"Invalid call to 'down'\");\n            this.top++;\n        }\n\n        public nodeType(): TypeScript.NodeType {\n            if (this.ast() == null)\n                return TypeScript.NodeType.None;\n            return this.ast().nodeType;\n        }\n\n        public ast() {\n            return <TypeScript.AST>AstPath.reverseIndexOf(this.asts, this.asts.length - (this.top + 1));\n        }\n\n        public parent() {\n            return <TypeScript.AST>AstPath.reverseIndexOf(this.asts, this.asts.length - this.top);\n        }\n\n        public count() {\n            return this.top + 1;\n        }\n\n        public get(index: number): TypeScript.AST {\n            return this.asts[index];\n        }\n\n        public isNameOfClass(): bool {\n            if (this.ast() === null || this.parent() === null)\n                return false;\n\n            return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n                (this.parent().nodeType === TypeScript.NodeType.ClassDeclaration) &&\n                ((<TypeScript.InterfaceDeclaration>this.parent()).name === this.ast());\n        }\n\n        public isNameOfInterface(): bool {\n            if (this.ast() === null || this.parent() === null)\n                return false;\n\n            return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n                (this.parent().nodeType === TypeScript.NodeType.InterfaceDeclaration) &&\n                ((<TypeScript.InterfaceDeclaration>this.parent()).name === this.ast());\n        }\n\n        public isNameOfArgument(): bool {\n            if (this.ast() === null || this.parent() === null)\n                return false;\n\n            return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n                (this.parent().nodeType === TypeScript.NodeType.ArgDecl) &&\n                ((<TypeScript.ArgDecl>this.parent()).id === this.ast());\n        }\n\n        public isNameOfVariable(): bool {\n            if (this.ast() === null || this.parent() === null)\n                return false;\n\n            return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n                (this.parent().nodeType === TypeScript.NodeType.VarDecl) &&\n                ((<TypeScript.VarDecl>this.parent()).id === this.ast());\n        }\n\n        public isNameOfModule(): bool {\n            if (this.ast() === null || this.parent() === null)\n                return false;\n\n            return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n                (this.parent().nodeType === TypeScript.NodeType.ModuleDeclaration) &&\n                ((<TypeScript.ModuleDeclaration>this.parent()).name === this.ast());\n        }\n\n        public isNameOfFunction(): bool {\n            if (this.ast() === null || this.parent() === null)\n                return false;\n\n            return (this.ast().nodeType === TypeScript.NodeType.Name) &&\n                (this.parent().nodeType === TypeScript.NodeType.FuncDecl) &&\n                ((<TypeScript.FuncDecl>this.parent()).name === this.ast());\n        }\n\n        public isChildOfScript(): bool {\n            var ast = lastOf(this.asts);\n            return this.count() >= 3 &&\n                this.asts[this.top] === ast &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.Script;\n        }\n\n        public isChildOfModule(): bool {\n            var ast = lastOf(this.asts);\n            return this.count() >= 3 &&\n                this.asts[this.top] === ast &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.ModuleDeclaration;\n        }\n\n        public isChildOfClass(): bool {\n            var ast = lastOf(this.asts);\n            return this.count() >= 3 &&\n                this.asts[this.top] === ast &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.ClassDeclaration;\n        }\n\n        public isArgumentOfClassConstructor(): bool {\n            var ast = lastOf(this.asts);\n            return this.count() >= 5 &&\n                this.asts[this.top] === ast &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.FuncDecl &&\n                this.asts[this.top - 3].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 4].nodeType === TypeScript.NodeType.ClassDeclaration &&\n                ((<TypeScript.FuncDecl>this.asts[this.top - 2]).isConstructor) &&\n                ((<TypeScript.FuncDecl>this.asts[this.top - 2]).arguments === this.asts[this.top - 1]) &&\n                ((<TypeScript.ClassDeclaration>this.asts[this.top - 4]).constructorDecl === this.asts[this.top - 2]);\n        }\n\n        public isChildOfInterface(): bool {\n            var ast = lastOf(this.asts);\n            return this.count() >= 3 &&\n                this.asts[this.top] === ast &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.InterfaceDeclaration;\n        }\n\n        public isTopLevelImplicitModule() {\n            return this.count() >= 1 &&\n                this.asts[this.top].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n                TypeScript.hasFlag((<TypeScript.ModuleDeclaration>this.asts[this.top]).modFlags, TypeScript.ModuleFlags.IsWholeFile);\n        }\n\n        public isBodyOfTopLevelImplicitModule() {\n            return this.count() >= 2 &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n                 (<TypeScript.ModuleDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0] &&\n                TypeScript.hasFlag((<TypeScript.ModuleDeclaration>this.asts[this.top - 1]).modFlags, TypeScript.ModuleFlags.IsWholeFile);\n        }\n\n        public isBodyOfScript(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Script &&\n                 (<TypeScript.Script>this.asts[this.top - 1]).bod == this.asts[this.top - 0];\n        }\n\n        public isBodyOfSwitch(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Switch &&\n                 (<TypeScript.SwitchStatement>this.asts[this.top - 1]).caseList == this.asts[this.top - 0];\n        }\n\n        public isBodyOfModule(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.ModuleDeclaration &&\n                 (<TypeScript.ModuleDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0];\n        }\n\n        public isBodyOfClass(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.ClassDeclaration &&\n                 (<TypeScript.ClassDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0];\n        }\n\n        public isBodyOfFunction(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.FuncDecl &&\n                 (<TypeScript.FuncDecl>this.asts[this.top - 1]).bod == this.asts[this.top - 0];\n        }\n\n        public isBodyOfInterface(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.InterfaceDeclaration &&\n                 (<TypeScript.InterfaceDeclaration>this.asts[this.top - 1]).members == this.asts[this.top - 0];\n        }\n\n        public isBodyOfBlock(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Block &&\n                (<TypeScript.Block>this.asts[this.top - 1]).statements == this.asts[this.top - 0];\n        }\n\n        public isBodyOfFor(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.For &&\n                (<TypeScript.ForStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isBodyOfCase(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Case &&\n                (<TypeScript.CaseStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isBodyOfTry(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Try &&\n                (<TypeScript.Try>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isBodyOfCatch(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Catch &&\n                (<TypeScript.Catch>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isBodyOfDoWhile(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.DoWhile &&\n                (<TypeScript.DoWhileStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isBodyOfWhile(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.While &&\n                (<TypeScript.WhileStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isBodyOfForIn(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.ForIn &&\n                (<TypeScript.ForInStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isBodyOfWith(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.With &&\n                (<TypeScript.WithStatement>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isBodyOfFinally(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Finally &&\n                (<TypeScript.Finally>this.asts[this.top - 1]).body == this.asts[this.top - 0];\n        }\n\n        public isCaseOfSwitch(): bool {\n            return this.count() >= 3 &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.Switch &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                (<TypeScript.SwitchStatement>this.asts[this.top - 2]).caseList == this.asts[this.top - 1];\n        }\n\n        public isDefaultCaseOfSwitch(): bool {\n            return this.count() >= 3 &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.Switch &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                (<TypeScript.SwitchStatement>this.asts[this.top - 2]).caseList == this.asts[this.top - 1] &&\n                (<TypeScript.SwitchStatement>this.asts[this.top - 2]).defaultCase == this.asts[this.top - 0];\n        }\n\n        public isListOfObjectLit(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.ObjectLit &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n                (<TypeScript.UnaryExpression>this.asts[this.top - 1]).operand == this.asts[this.top - 0];\n        }\n\n        public isBodyOfObjectLit(): bool {\n            return this.isListOfObjectLit();\n        }\n\n        public isEmptyListOfObjectLit(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.ObjectLit &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n                (<TypeScript.UnaryExpression>this.asts[this.top - 1]).operand == this.asts[this.top - 0] &&\n                (<TypeScript.ASTList>this.asts[this.top - 0]).members.length == 0;\n        }\n\n        public isMemberOfObjectLit(): bool {\n            return this.count() >= 3 &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.ObjectLit &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.Member &&\n                (<TypeScript.UnaryExpression>this.asts[this.top - 2]).operand == this.asts[this.top - 1];\n        }\n\n        public isNameOfMemberOfObjectLit(): bool {\n            return this.count() >= 4 &&\n                this.asts[this.top - 3].nodeType === TypeScript.NodeType.ObjectLit &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.Name &&\n                (<TypeScript.UnaryExpression>this.asts[this.top - 3]).operand == this.asts[this.top - 2];\n        }\n\n        public isListOfArrayLit(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.ArrayLit &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n                (<TypeScript.UnaryExpression>this.asts[this.top - 1]).operand == this.asts[this.top - 0];\n        }\n\n        public isTargetOfMember(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n                (<TypeScript.BinaryExpression>this.asts[this.top - 1]).operand1 === this.asts[this.top - 0];\n        }\n\n        public isMemberOfMember(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Member &&\n                (<TypeScript.BinaryExpression>this.asts[this.top - 1]).operand2 === this.asts[this.top - 0];\n        }\n\n        public isItemOfList(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List;\n            //(<Tools.ASTList>this.asts[this.top - 1]).operand2 === this.asts[this.top - 0];\n        }\n\n        public isThenOfIf(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.If &&\n                (<TypeScript.IfStatement>this.asts[this.top - 1]).thenBod == this.asts[this.top - 0];\n        }\n\n        public isElseOfIf(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.If &&\n                (<TypeScript.IfStatement>this.asts[this.top - 1]).elseBod == this.asts[this.top - 0];\n        }\n\n        public isBodyOfDefaultCase(): bool {\n            return this.isBodyOfCase();\n        }\n\n        public isSingleStatementList(): bool {\n            return this.count() >= 1 &&\n                this.asts[this.top].nodeType === TypeScript.NodeType.List &&\n                (<TypeScript.ASTList>this.asts[this.top]).members.length === 1;\n        }\n\n        public isArgumentListOfFunction(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.FuncDecl &&\n                (<TypeScript.FuncDecl>this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n        }\n\n        public isArgumentOfFunction(): bool {\n            return this.count() >= 3 &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 2].nodeType === TypeScript.NodeType.FuncDecl &&\n                (<TypeScript.FuncDecl>this.asts[this.top - 2]).arguments === this.asts[this.top - 1];\n        }\n\n        public isArgumentListOfCall(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.Call &&\n                (<TypeScript.CallExpression>this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n        }\n\n        public isArgumentListOfNew(): bool {\n            return this.count() >= 2 &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.List &&\n                this.asts[this.top - 1].nodeType === TypeScript.NodeType.New &&\n                (<TypeScript.CallExpression>this.asts[this.top - 1]).arguments === this.asts[this.top - 0];\n        }\n\n        public isSynthesizedBlock(): bool {\n            return this.count() >= 1 &&\n                this.asts[this.top - 0].nodeType === TypeScript.NodeType.Block &&\n                (<TypeScript.Block>this.asts[this.top - 0]).isStatementBlock === false;\n        }\n    }\n\n    export function isValidAstNode(ast: TypeScript.ASTSpan): bool {\n        if (ast === null)\n            return false;\n\n        if (ast.minChar === -1 || ast.limChar === -1)\n            return false;\n\n        return true;\n    }\n\n    export class AstPathContext {\n        public path = new TypeScript.AstPath();\n    }\n\n    export enum GetAstPathOptions {\n        Default = 0,\n        EdgeInclusive = 1,\n        //We need this options dealing with an AST coming from an incomplete AST. For example:\n        //     class foo { // r\n        // If we ask for the AST at the position after the \"r\" character, we won't see we are \n        // inside a comment, because the \"class\" AST node has a limChar corresponding to the position of \n        // the \"{\" character, meaning we don't traverse the tree down to the stmt list of the class, meaning\n        // we don't find the \"precomment\" attached to the errorneous empty stmt.\n        //TODO: It would be nice to be able to get rid of this.\n        DontPruneSearchBasedOnPosition = 1 << 1,\n    }\n\n    ///\n    /// Return the stack of AST nodes containing \"position\"\n    ///\n    export function getAstPathToPosition(script: TypeScript.AST, pos: number, options = GetAstPathOptions.Default): TypeScript.AstPath {\n        var lookInComments = (comments: TypeScript.Comment[]) => {\n            if (comments && comments.length > 0) {\n                for (var i = 0; i < comments.length; i++) {\n                    var minChar = comments[i].minChar;\n                    var limChar = comments[i].limChar;\n                    if (!comments[i].isBlockComment) {\n                        limChar++; // For single line comments, include 1 more character (for the newline)\n                    }\n                    if (pos >= minChar && pos < limChar) {\n                        ctx.path.push(comments[i]);\n                    }\n                }\n            }\n        }\n\n        var pre = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: IAstWalker) {\n            if (isValidAstNode(cur)) {\n\n                // Add \"cur\" to the stack if it contains our position\n                // For \"identifier\" nodes, we need a special case: A position equal to \"limChar\" is\n                // valid, since the position corresponds to a caret position (in between characters)\n                // For example:\n                //  bar\n                //  0123\n                // If \"position == 3\", the caret is at the \"right\" of the \"r\" character, which should be considered valid\n                var inclusive =\n                    hasFlag(options, GetAstPathOptions.EdgeInclusive) ||\n                    cur.nodeType === TypeScript.NodeType.Name ||\n                    pos === script.limChar; // Special \"EOF\" case\n\n                var minChar = cur.minChar;\n                var limChar = cur.limChar + (inclusive ? 1 : 0)\n                if (pos >= minChar && pos < limChar) {\n\n                    // TODO: Since AST is sometimes not correct wrt to position, only add \"cur\" if it's better\n                    //       than top of the stack.\n                    var previous = ctx.path.ast();\n                    if (previous == null || (cur.minChar >= previous.minChar && cur.limChar <= previous.limChar)) {\n                        ctx.path.push(cur);\n                    }\n                    else {\n                        //logger.log(\"TODO: Ignoring node because minChar, limChar not better than previous node in stack\");\n                    }\n                }\n\n                // The AST walker skips comments, but we might be in one, so check the pre/post comments for this node manually\n                if (pos < limChar) {\n                    lookInComments(cur.preComments);\n                }\n                if (pos >= minChar) {\n                    lookInComments(cur.postComments);\n                }\n\n                if (!hasFlag(options, GetAstPathOptions.DontPruneSearchBasedOnPosition)) {\n                    // Don't go further down the tree if pos is outside of [minChar, limChar]\n                    walker.options.goChildren = (minChar <= pos && pos <= limChar);\n                }\n            }\n            return cur;\n        }\n\n        var ctx = new AstPathContext();\n        TypeScript.getAstWalkerFactory().walk(script, pre, null, null, ctx);\n        return ctx.path;\n    }\n\n    //\n    // Find a source text offset that is safe for lexing tokens at the given position.\n    // This is used when \"position\" might be inside a comment or string, etc.\n    //\n    export function getTokenizationOffset(script: TypeScript.Script, position: number): number {\n        var bestOffset = 0;\n        var pre = (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker): TypeScript.AST => {\n            if (TypeScript.isValidAstNode(cur)) {\n                // Did we find a closer offset?\n                if (cur.minChar <= position) {\n                    bestOffset = max(bestOffset, cur.minChar);\n                }\n\n                // Stop the walk if this node is not related to \"minChar\"\n                if (cur.minChar > position || cur.limChar < bestOffset) {\n                    walker.options.goChildren = false;\n                }\n            }\n\n            return cur;\n        }\n\n        TypeScript.getAstWalkerFactory().walk(script, pre);\n        return bestOffset;\n    }\n\n    ///\n    /// Simple function to Walk an AST using a simple callback function.\n    ///\n    export function walkAST(ast: TypeScript.AST, callback: (path: AstPath, walker: TypeScript.IAstWalker) => void ): void {\n        var pre = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n            var path: TypeScript.AstPath = walker.state;\n            path.push(cur);\n            callback(path, walker);\n            return cur;\n        }\n        var post = function (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n            var path: TypeScript.AstPath = walker.state;\n            path.pop();\n            return cur;\n        }\n\n        var path = new AstPath();\n        TypeScript.getAstWalkerFactory().walk(ast, pre, post, null, path);\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export class ASTSpan {\n        public minChar: number = -1;  // -1 = \"undefined\" or \"compiler generated\"\n        public limChar: number = -1;  // -1 = \"undefined\" or \"compiler generated\"   \n    }\n\n    export class AST extends ASTSpan {\n        public type: Type = null;\n        public flags = ASTFlags.Writeable;\n\n        // REVIEW: for diagnostic purposes\n        public passCreated: number = CompilerDiagnostics.analysisPass;\n\n        public preComments: Comment[] = null;\n        public postComments: Comment[] = null;\n        private docComments: Comment[] = null;\n\n        public isParenthesized = false;\n\n        constructor (public nodeType: NodeType) {\n            super();\n        }\n\n        public isExpression() { return false; }\n\n        public isStatementOrExpression() { return false; }\n\n        public isCompoundStatement() { return false; }\n\n        public isLeaf() { return this.isStatementOrExpression() && (!this.isCompoundStatement()); }\n        \n        public isDeclaration() { return false; }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            switch (this.nodeType) {\n                case NodeType.Error:\n                case NodeType.EmptyExpr:\n                    this.type = typeFlow.anyType;\n                    break;\n                case NodeType.This:\n                    return typeFlow.typeCheckThis(this);\n                case NodeType.Null:\n                    this.type = typeFlow.nullType;\n                    break;\n                case NodeType.False:\n                case NodeType.True:\n                    this.type = typeFlow.booleanType;\n                    break;\n                case NodeType.Super:\n                    return typeFlow.typeCheckSuper(this);\n                case NodeType.EndCode:\n                case NodeType.Empty:\n                case NodeType.Void:\n                    this.type = typeFlow.voidType;\n                    break;\n                default:\n                    throw new Error(\"please implement in derived class\");\n            }\n            return this;\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            switch (this.nodeType) {\n                case NodeType.This:\n                    emitter.recordSourceMappingStart(this);\n                    if (emitter.thisFnc && (hasFlag(emitter.thisFnc.fncFlags, FncFlags.IsFatArrowFunction))) {\n                        emitter.writeToOutput(\"_this\");\n                    }\n                    else {\n                        emitter.writeToOutput(\"this\");\n                    }\n                    emitter.recordSourceMappingEnd(this);\n                    break;\n                case NodeType.Null:\n                    emitter.recordSourceMappingStart(this);\n                    emitter.writeToOutput(\"null\");\n                    emitter.recordSourceMappingEnd(this);\n                    break;\n                case NodeType.False:\n                    emitter.recordSourceMappingStart(this);\n                    emitter.writeToOutput(\"false\");\n                    emitter.recordSourceMappingEnd(this);\n                    break;\n                case NodeType.True:\n                    emitter.recordSourceMappingStart(this);\n                    emitter.writeToOutput(\"true\");\n                    emitter.recordSourceMappingEnd(this);\n                    break;\n                case NodeType.Super:\n                    emitter.recordSourceMappingStart(this);\n                    emitter.emitSuperReference();\n                    emitter.recordSourceMappingEnd(this);\n                    break;\n                case NodeType.EndCode:\n                case NodeType.Error:\n                case NodeType.EmptyExpr:\n                    break;\n                case NodeType.Empty:\n                    emitter.recordSourceMappingStart(this);\n                    emitter.recordSourceMappingEnd(this);\n                    break;\n                case NodeType.Void:\n                    emitter.recordSourceMappingStart(this);\n                    emitter.writeToOutput(\"void \");\n                    emitter.recordSourceMappingEnd(this);\n                    break;\n                default:\n                    throw new Error(\"please implement in derived class\");\n            }\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public print(context: PrintContext) {\n            context.startLine();\n            var lineCol = { line: -1, col: -1 };\n            var limLineCol = { line: -1, col: -1 };\n            if (context.parser !== null) {\n                context.parser.getSourceLineCol(lineCol, this.minChar);\n                context.parser.getSourceLineCol(limLineCol, this.limChar);\n                context.write(\"(\" + lineCol.line + \",\" + lineCol.col + \")--\" +\n                              \"(\" + limLineCol.line + \",\" + limLineCol.col + \"): \");\n            }\n            var lab = this.printLabel();\n            if (hasFlag(this.flags, ASTFlags.Error)) {\n                lab += \" (Error)\";\n            }\n            context.writeLine(lab);\n        }\n\n        public printLabel() {\n            if (nodeTypeTable[this.nodeType] !== undefined) {\n                return nodeTypeTable[this.nodeType];\n            }\n            else {\n                return (<any>NodeType)._map[this.nodeType];\n            }\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            // by default, AST adds itself to current basic block and does not check its children\n            context.walker.options.goChildren = false;\n            context.addContent(this);\n        }\n\n        public netFreeUses(container: Symbol, freeUses: StringHashTable) {\n        }\n\n        public treeViewLabel() {\n            return (<any>NodeType)._map[this.nodeType];\n        }\n\n        public static getResolvedIdentifierName(name: string): string {\n            if (!name) return \"\";\n\n            var resolved = \"\";\n            var start = 0;\n            var i = 0;\n            while(i <= name.length - 6) {\n                // Look for escape sequence \\uxxxx\n                if (name.charAt(i) == '\\\\' && name.charAt(i+1) == 'u') {\n                    var charCode = parseInt(name.substr(i + 2, 4), 16);\n                    resolved += name.substr(start, i - start);\n                    resolved += String.fromCharCode(charCode);\n                    i += 6;\n                    start = i;\n                    continue;\n                } \n                i++;\n            }\n            // Append remaining string\n            resolved += name.substring(start);\n            return resolved;\n        }\n\n        public getDocComments() : Comment[] {\n            if (!this.isDeclaration() || !this.preComments || this.preComments.length == 0) {\n                return [];\n            }\n\n            if (!this.docComments) {\n                var preCommentsLength = this.preComments.length;\n                var docComments: Comment[] = [];\n                for (var i = preCommentsLength - 1; i >= 0; i--) {\n                    if (this.preComments[i].isDocComment()) {\n                        var prevDocComment = docComments.length > 0 ? docComments[docComments.length - 1] : null;\n                        if (prevDocComment == null || // If the help comments were not yet set then this is the comment\n                             (this.preComments[i].limLine == prevDocComment.minLine ||\n                              this.preComments[i].limLine + 1 == prevDocComment.minLine)) { // On same line or next line\n                            docComments.push(this.preComments[i]);\n                            continue;\n                        }\n                    }\n                    break;\n                }\n\n                this.docComments = docComments.reverse();\n            }\n\n            return this.docComments;\n        }\n    }\n\n    export class IncompleteAST extends AST {\n        constructor (min: number, lim: number) {\n            super(NodeType.Error);\n\n            this.minChar = min;\n            this.limChar = lim;\n        }\n    }\n\n    export class ASTList extends AST {\n        public enclosingScope: SymbolScope = null;\n        public members: AST[] = new AST[];\n\n        constructor () {\n            super(NodeType.List);\n        }\n\n        public addToControlFlow(context: ControlFlowContext) {\n            var len = this.members.length;\n            for (var i = 0; i < len; i++) {\n                if (context.noContinuation) {\n                    context.addUnreachable(this.members[i]);\n                    break;\n                }\n                else {\n                    this.members[i] = context.walk(this.members[i], this);\n                }\n            }\n            context.walker.options.goChildren = false;\n        }\n\n        public append(ast: AST) {\n            this.members[this.members.length] = ast;\n            return this;\n        }\n\n        public appendAll(ast: AST) {\n            if (ast.nodeType == NodeType.List) {\n                var list = <ASTList>ast;\n                for (var i = 0, len = list.members.length; i < len; i++) {\n                    this.append(list.members[i]);\n                }\n            }\n            else {\n                this.append(ast);\n            }\n            return this;\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.recordSourceMappingStart(this);\n            emitter.emitJavascriptList(this, null, TokenID.Semicolon, startLine, false, false);\n            emitter.recordSourceMappingEnd(this);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            var len = this.members.length;\n            typeFlow.nestingLevel++;\n            for (var i = 0; i < len; i++) {\n                if (this.members[i]) {\n                    this.members[i] = this.members[i].typeCheck(typeFlow);\n                }\n            }\n            typeFlow.nestingLevel--;\n            return this;\n        }\n    }\n\n    export class Identifier extends AST {\n        public sym: Symbol = null;\n        public cloId = -1;\n        public text: string;\n\n        // 'actualText' is the text that the user has entered for the identifier. the text might \n        // include any Unicode escape sequences (e.g.: \\u0041 for 'A'). 'text', however, contains \n        // the resolved value of any escape sequences in the actual text; so in the previous \n        // example, actualText = '\\u0041', text = 'A'.\n        //\n        // For purposes of finding a symbol, use text, as this will allow you to match all \n        // variations of the variable text. For full-fidelity translation of the user input, such\n        // as emitting, use the actualText field.\n        // \n        // Note: \n        //    To change text, and to avoid running into a situation where 'actualText' does not \n        //    match 'text', always use setText.\n        constructor (public actualText: string, public hasEscapeSequence?: bool) {\n            super(NodeType.Name);\n            this.setText(actualText, hasEscapeSequence);\n        }\n\n        public setText(actualText: string, hasEscapeSequence?: bool) {\n            this.actualText = actualText;\n            if (hasEscapeSequence) {\n                this.text = AST.getResolvedIdentifierName(actualText);\n            }\n            else {\n                this.text = actualText;\n            }\n        }\n\n        public isMissing() { return false; }\n        public isLeaf() { return true; }\n\n        public treeViewLabel() {\n            return \"id: \" + this.actualText;\n        }\n\n        public printLabel() {\n            if (this.actualText) {\n                return \"id: \" + this.actualText;\n            }\n            else {\n                return \"name node\";\n            }\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckName(this);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitJavascriptName(this, true);\n        }\n\n        public static fromToken(token: Token): Identifier {\n            return new Identifier(token.getText(), (<IdentifierToken>token).hasEscapeSequence);\n        }\n    }\n\n    export class MissingIdentifier extends Identifier {\n        constructor () {\n            super(\"__missing\");\n        }\n\n        public isMissing() {\n            return true;\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            // Emit nothing for a missing ID\n        }\n    }\n\n    export class Label extends AST {\n        constructor (public id: Identifier) {\n            super(NodeType.Label);\n        }\n\n        public printLabel() { return this.id.actualText + \":\"; }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.type = typeFlow.voidType;\n            return this;\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.recordSourceMappingStart(this.id);\n            emitter.writeToOutput(this.id.actualText);\n            emitter.recordSourceMappingEnd(this.id);\n            emitter.writeLineToOutput(\":\");\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n\n    export class Expression extends AST {\n        constructor (nodeType: NodeType) {\n            super(nodeType);\n        }\n\n        public isExpression() { return true; }\n\n        public isStatementOrExpression() { return true; }\n    }\n\n    export class UnaryExpression extends Expression {\n        public targetType: Type = null; // Target type for an object literal (null if no target type)\n        public castTerm: AST = null;\n\n        constructor (nodeType: NodeType, public operand: AST) {\n            super(nodeType);\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            super.addToControlFlow(context);\n            // TODO: add successor as catch block/finally block if present\n            if (this.nodeType == NodeType.Throw) {\n                context.returnStmt();\n            }\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            switch (this.nodeType) {\n                case NodeType.Not:\n                    return typeFlow.typeCheckBitNot(this);\n\n                case NodeType.LogNot:\n                    return typeFlow.typeCheckLogNot(this);\n\n                case NodeType.Pos:\n                case NodeType.Neg:\n                    return typeFlow.typeCheckUnaryNumberOperator(this);\n\n                case NodeType.IncPost:\n                case NodeType.IncPre:\n                case NodeType.DecPost:\n                case NodeType.DecPre:\n                    return typeFlow.typeCheckIncOrDec(this);\n\n                case NodeType.ArrayLit:\n                    typeFlow.typeCheckArrayLit(this);\n                    return this;\n\n                case NodeType.ObjectLit:\n                    typeFlow.typeCheckObjectLit(this);\n                    return this;\n\n                case NodeType.Throw:\n                    this.operand = typeFlow.typeCheck(this.operand);\n                    this.type = typeFlow.voidType;\n                    return this;\n\n                case NodeType.Typeof:\n                    this.operand = typeFlow.typeCheck(this.operand);\n                    this.type = typeFlow.stringType;\n                    return this;\n\n                case NodeType.Delete:\n                    this.operand = typeFlow.typeCheck(this.operand);\n                    this.type = typeFlow.booleanType;\n                    break;\n\n                case NodeType.TypeAssertion:\n                    this.castTerm = typeFlow.typeCheck(this.castTerm);\n                    var applyTargetType = !this.operand.isParenthesized;\n\n                    var targetType = applyTargetType ? this.castTerm.type : null;\n\n                    typeFlow.checker.typeCheckWithContextualType(targetType, typeFlow.checker.inProvisionalTypecheckMode(), true, this.operand);\n                    typeFlow.castWithCoercion(this.operand, this.castTerm.type, false, true);\n                    this.type = this.castTerm.type;\n                    return this;\n\n                case NodeType.Void:\n                    // REVIEW - Although this is good to do for completeness's sake,\n                    // this shouldn't be strictly necessary from the void operator's\n                    // point of view\n                    this.operand = typeFlow.typeCheck(this.operand);\n                    this.type = typeFlow.checker.undefinedType;\n                    break;\n\n                default:\n                    throw new Error(\"please implement in derived class\");\n            }\n            return this;\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            switch (this.nodeType) {\n                case NodeType.IncPost:\n                    emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);\n                    emitter.writeToOutput(\"++\");\n                    break;\n                case NodeType.LogNot:\n                    emitter.writeToOutput(\"!\");\n                    emitter.emitJavascript(this.operand, TokenID.Exclamation, false);\n                    break;\n                case NodeType.DecPost:\n                    emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);\n                    emitter.writeToOutput(\"--\");\n                    break;\n                case NodeType.ObjectLit:\n                    emitter.emitObjectLiteral(<ASTList>this.operand);\n                    break;\n                case NodeType.ArrayLit:\n                    emitter.emitArrayLiteral(<ASTList>this.operand);\n                    break;\n                case NodeType.Not:\n                    emitter.writeToOutput(\"~\");\n                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n                    break;\n                case NodeType.Neg:\n                    emitter.writeToOutput(\"-\");\n                    if (this.operand.nodeType == NodeType.Neg) {\n                        this.operand.isParenthesized = true;\n                    }\n                    emitter.emitJavascript(this.operand, TokenID.Minus, false);\n                    break;\n                case NodeType.Pos:\n                    emitter.writeToOutput(\"+\");\n                    if (this.operand.nodeType == NodeType.Pos) {\n                        this.operand.isParenthesized = true;\n                    }\n                    emitter.emitJavascript(this.operand, TokenID.Plus, false);\n                    break;\n                case NodeType.IncPre:\n                    emitter.writeToOutput(\"++\");\n                    emitter.emitJavascript(this.operand, TokenID.PlusPlus, false);\n                    break;\n                case NodeType.DecPre:\n                    emitter.writeToOutput(\"--\");\n                    emitter.emitJavascript(this.operand, TokenID.MinusMinus, false);\n                    break;\n                case NodeType.Throw:\n                    emitter.writeToOutput(\"throw \");\n                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n                    emitter.writeToOutput(\";\");\n                    break;\n                case NodeType.Typeof:\n                    emitter.writeToOutput(\"typeof \");\n                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n                    break;\n                case NodeType.Delete:\n                    emitter.writeToOutput(\"delete \");\n                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n                    break;\n                case NodeType.Void:\n                    emitter.writeToOutput(\"void \");\n                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n                    break;\n                case NodeType.TypeAssertion:\n                    emitter.emitJavascript(this.operand, TokenID.Tilde, false);\n                    break;\n                default:\n                    throw new Error(\"please implement in derived class\");\n            }\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n\n    export class CallExpression extends Expression {\n        constructor (nodeType: NodeType,\n                     public target: AST,\n                     public arguments: ASTList) {\n            super(nodeType);\n            this.minChar = this.target.minChar;\n        }\n\n        public signature: Signature = null;\n\n        public typeCheck(typeFlow: TypeFlow) {\n            if (this.nodeType == NodeType.New) {\n                return typeFlow.typeCheckNew(this);\n            }\n            else {\n                return typeFlow.typeCheckCall(this);\n            }\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n\n            if (this.nodeType == NodeType.New) {\n                emitter.emitNew(this.target, this.arguments);\n            }\n            else {\n                emitter.emitCall(this, this.target, this.arguments);\n            }\n\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n\n    export class BinaryExpression extends Expression {\n        constructor (nodeType: NodeType, public operand1: AST, public operand2: AST) {\n            super(nodeType);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            switch (this.nodeType) {\n                case NodeType.Dot:\n                    return typeFlow.typeCheckDotOperator(this);\n                case NodeType.Asg:\n                    return typeFlow.typeCheckAsgOperator(this);\n                case NodeType.Add:\n                case NodeType.Sub:\n                case NodeType.Mul:\n                case NodeType.Div:\n                case NodeType.Mod:\n                case NodeType.Or:\n                case NodeType.And:\n                    return typeFlow.typeCheckArithmeticOperator(this, false);\n                case NodeType.Xor:\n                    return typeFlow.typeCheckBitwiseOperator(this, false);\n                case NodeType.Ne:\n                case NodeType.Eq:\n                    var text: string;\n                    if (typeFlow.checker.styleSettings.eqeqeq) {\n                        text = nodeTypeTable[this.nodeType];\n                        typeFlow.checker.errorReporter.styleError(this, \"use of \" + text);\n                    }\n                    else if (typeFlow.checker.styleSettings.eqnull) {\n                        text = nodeTypeTable[this.nodeType];\n                        if ((this.operand2 !== null) && (this.operand2.nodeType == NodeType.Null)) {\n                            typeFlow.checker.errorReporter.styleError(this, \"use of \" + text + \" to compare with null\");\n                        }\n                    }\n                case NodeType.Eqv:\n                case NodeType.NEqv:\n                case NodeType.Lt:\n                case NodeType.Le:\n                case NodeType.Ge:\n                case NodeType.Gt:\n                    return typeFlow.typeCheckBooleanOperator(this);\n                case NodeType.Index:\n                    return typeFlow.typeCheckIndex(this);\n                case NodeType.Member:\n                    this.type = typeFlow.voidType;\n                    return this;\n                case NodeType.LogOr:\n                    return typeFlow.typeCheckLogOr(this);\n                case NodeType.LogAnd:\n                    return typeFlow.typeCheckLogAnd(this);\n                case NodeType.AsgAdd:\n                case NodeType.AsgSub:\n                case NodeType.AsgMul:\n                case NodeType.AsgDiv:\n                case NodeType.AsgMod:\n                case NodeType.AsgOr:\n                case NodeType.AsgAnd:\n                    return typeFlow.typeCheckArithmeticOperator(this, true);\n                case NodeType.AsgXor:\n                    return typeFlow.typeCheckBitwiseOperator(this, true);\n                case NodeType.Lsh:\n                case NodeType.Rsh:\n                case NodeType.Rs2:\n                    return typeFlow.typeCheckShift(this, false);\n                case NodeType.AsgLsh:\n                case NodeType.AsgRsh:\n                case NodeType.AsgRs2:\n                    return typeFlow.typeCheckShift(this, true);\n                case NodeType.Comma:\n                    return typeFlow.typeCheckCommaOperator(this);\n                case NodeType.InstOf:\n                    return typeFlow.typeCheckInstOf(this);\n                case NodeType.In:\n                    return typeFlow.typeCheckInOperator(this);\n                case NodeType.From:\n                    typeFlow.checker.errorReporter.simpleError(this, \"Illegal use of 'from' keyword in binary expression\");\n                    break;\n                default:\n                    throw new Error(\"please implement in derived class\");\n            }\n            return this;\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            var binTokenId = nodeTypeToTokTable[this.nodeType];\n\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            if (binTokenId != undefined) {\n\n                emitter.emitJavascript(this.operand1, binTokenId, false);\n\n                if (tokenTable[binTokenId].text == \"instanceof\") {\n                    emitter.writeToOutput(\" instanceof \");\n                }\n                else if (tokenTable[binTokenId].text == \"in\") {\n                    emitter.writeToOutput(\" in \");\n                }\n                else {\n                    emitter.writeToOutputTrimmable(\" \" + tokenTable[binTokenId].text + \" \");\n                }\n\n                emitter.emitJavascript(this.operand2, binTokenId, false);\n            }\n            else {\n                switch (this.nodeType) {\n                    case NodeType.Dot:\n                        if (!emitter.tryEmitConstant(this)) {\n                            emitter.emitJavascript(this.operand1, TokenID.Dot, false);\n                            emitter.writeToOutput(\".\");\n                            emitter.emitJavascriptName(<Identifier>this.operand2, false);\n                        }\n                        break;\n                    case NodeType.Index:\n                        emitter.emitIndex(this.operand1, this.operand2);\n                        break;\n\n                    case NodeType.Member:\n                        if (this.operand2.nodeType == NodeType.FuncDecl && (<FuncDecl>this.operand2).isAccessor()) {\n                            var funcDecl = <FuncDecl>this.operand2;\n                            if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n                                emitter.writeToOutput(\"get \");\n                            }\n                            else {\n                                emitter.writeToOutput(\"set \");\n                            }\n                            emitter.emitJavascript(this.operand1, TokenID.Colon, false);\n                        }\n                        else {\n                            emitter.emitJavascript(this.operand1, TokenID.Colon, false);\n                            emitter.writeToOutputTrimmable(\": \");\n                        }\n                        emitter.emitJavascript(this.operand2, TokenID.Comma, false);\n                        break;\n                    case NodeType.Comma:\n                        emitter.emitJavascript(this.operand1, TokenID.Comma, false);\n                        if (emitter.emitState.inObjectLiteral) {\n                            emitter.writeLineToOutput(\", \");\n                        }\n                        else {\n                            emitter.writeToOutput(\",\");\n                        }\n                        emitter.emitJavascript(this.operand2, TokenID.Comma, false);\n                        break;\n                    case NodeType.Is:\n                        throw new Error(\"should be de-sugared during type check\");\n                    default:\n                        throw new Error(\"please implement in derived class\");\n                }\n            }\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n\n    export class ConditionalExpression extends Expression {\n        constructor (public operand1: AST,\n                     public operand2: AST,\n                     public operand3: AST) {\n            super(NodeType.ConditionalExpression);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckQMark(this);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.emitJavascript(this.operand1, TokenID.Question, false);\n            emitter.writeToOutput(\" ? \");\n            emitter.emitJavascript(this.operand2, TokenID.Question, false);\n            emitter.writeToOutput(\" : \");\n            emitter.emitJavascript(this.operand3, TokenID.Question, false);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n\n    export class NumberLiteral extends Expression {\n        constructor (public value: number, public hasEmptyFraction?: bool) {\n            super(NodeType.NumberLit);\n        }\n\n        public isNegativeZero = false;\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.type = typeFlow.doubleType;\n            return this;\n        }\n\n        public treeViewLabel() {\n            return \"num: \" + this.printLabel();\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            if (this.isNegativeZero) {\n                emitter.writeToOutput(\"-\");\n            }\n\n            emitter.writeToOutput(this.value.toString());\n\n            if (this.hasEmptyFraction)\n                emitter.writeToOutput(\".0\");\n\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public printLabel() {\n            if (Math.floor(this.value) != this.value) {\n                return this.value.toFixed(2).toString();\n            }\n            else if (this.hasEmptyFraction) {\n                return this.value.toString() + \".0\";\n            }\n            else {\n                return this.value.toString();\n            }\n        }\n    }\n\n    export class RegexLiteral extends Expression {\n        constructor (public regex) {\n            super(NodeType.Regex);\n        }\n        \n        public typeCheck(typeFlow: TypeFlow) {\n            this.type = typeFlow.regexType;\n            return this;\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.writeToOutput(this.regex.toString());\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n\n    export class StringLiteral extends Expression {\n        constructor (public text: string) {\n            super(NodeType.QString);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.emitStringLiteral(this.text);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.type = typeFlow.stringType;\n            return this;\n        }\n\n        public treeViewLabel() {\n            return \"st: \" + this.text;\n        }\n\n        public printLabel() {\n            return this.text;\n        }\n    }\n\n    export class ModuleElement extends AST {\n        constructor (nodeType: NodeType) {\n            super(nodeType);\n        }\n    }\n\n    export class ImportDeclaration extends ModuleElement {\n        public isStatementOrExpression() { return true; }\n        public varFlags = VarFlags.None;\n        public isDynamicImport = false;\n        public isDeclaration() { return true; }\n\n        constructor (public id: Identifier, public alias: AST) {\n            super(NodeType.ImportDeclaration);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            var mod = <ModuleType>this.alias.type;\n            // REVIEW: Only modules may be aliased for now, though there's no real\n            // restriction on what the type symbol may be\n            if (!this.isDynamicImport || (this.id.sym && !(<TypeSymbol>this.id.sym).onlyReferencedAsTypeRef)) {\n                var prevModAliasId = emitter.modAliasId;\n                var prevFirstModAlias = emitter.firstModAlias;\n\n                emitter.recordSourceMappingStart(this);\n                emitter.emitParensAndCommentsInPlace(this, true);\n                emitter.writeToOutput(\"var \" + this.id.actualText + \" = \");\n                emitter.modAliasId = this.id.actualText;\n                emitter.firstModAlias = this.firstAliasedModToString();\n                emitter.emitJavascript(this.alias, TokenID.Tilde, false);\n                // the dynamic import case will insert the semi-colon automatically\n                if (!this.isDynamicImport) {\n                    emitter.writeToOutput(\";\");\n                }\n                emitter.emitParensAndCommentsInPlace(this, false);\n                emitter.recordSourceMappingEnd(this);\n\n                emitter.modAliasId = prevModAliasId;\n                emitter.firstModAlias = prevFirstModAlias;\n            }\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckImportDecl(this);\n        }\n\n        public getAliasName(aliasAST?: AST = this.alias) : string {\n            if (aliasAST.nodeType == NodeType.Name) {\n                return (<Identifier>aliasAST).actualText;\n            } else {\n                var dotExpr = <BinaryExpression>aliasAST;\n                return this.getAliasName(dotExpr.operand1) + \".\" + this.getAliasName(dotExpr.operand2);\n            }\n        }\n\n        public firstAliasedModToString() {\n            if (this.alias.nodeType == NodeType.Name) {\n                return (<Identifier>this.alias).actualText;\n            }\n            else {\n                var dotExpr = <BinaryExpression>this.alias;\n                var firstMod = <Identifier>dotExpr.operand1;\n                return firstMod.actualText;\n            }\n        }\n    }\n\n    export class BoundDecl extends AST {\n        public init: AST = null;\n        public typeExpr: AST = null;\n        public varFlags = VarFlags.None;\n        public sym: Symbol = null;\n        public isDeclaration() { return true; }\n\n        constructor (public id: Identifier, nodeType: NodeType, public nestingLevel: number) {\n            super(nodeType);\n        }\n\n        public isStatementOrExpression() { return true; }\n\n        public isPrivate() { return hasFlag(this.varFlags, VarFlags.Private); }\n        public isPublic() { return hasFlag(this.varFlags, VarFlags.Public); }\n        public isProperty() { return hasFlag(this.varFlags, VarFlags.Property); }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckBoundDecl(this);\n        }\n\n        public printLabel() {\n            return this.treeViewLabel();\n        }\n    }\n\n    export class VarDecl extends BoundDecl {\n        constructor (id: Identifier, nest: number) {\n            super(id, NodeType.VarDecl, nest);\n        }\n\n        public isAmbient() { return hasFlag(this.varFlags, VarFlags.Ambient); }\n        public isExported() { return hasFlag(this.varFlags, VarFlags.Exported); }\n        public isStatic() { return hasFlag(this.varFlags, VarFlags.Static); }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitJavascriptVarDecl(this, tokenId);\n        }\n\n        public treeViewLabel() {\n            return \"var \" + this.id.actualText;\n        }\n    }\n\n    export class ArgDecl extends BoundDecl {\n        constructor (id: Identifier) {\n            super(id, NodeType.ArgDecl, 0);\n        }\n\n        public isOptional = false;\n\n        public isOptionalArg() { return this.isOptional || this.init; }\n\n        public treeViewLabel() {\n            return \"arg: \" + this.id.actualText;\n        }\n\n        public parameterPropertySym: FieldSymbol = null;\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.writeToOutput(this.id.actualText);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n\n    var internalId = 0;\n\n    export class FuncDecl extends AST {\n        public hint: string = null;\n        public fncFlags = FncFlags.None;\n        public returnTypeAnnotation: AST = null;\n        public symbols: IHashTable;\n        public variableArgList = false;\n        public signature: Signature;\n        public envids: Identifier[];\n        public jumpRefs: Identifier[] = null;\n        public internalNameCache: string = null;\n        public tmp1Declared = false;\n        public enclosingFnc: FuncDecl = null;\n        public freeVariables: Symbol[] = [];\n        public unitIndex = -1;\n        public classDecl: NamedDeclaration = null;\n        public boundToProperty: VarDecl = null;\n        public isOverload = false;\n        public innerStaticFuncs: FuncDecl[] = [];\n        public isTargetTypedAsMethod = false;\n        public isInlineCallLiteral = false;\n        public accessorSymbol: Symbol = null;\n        public leftCurlyCount = 0;\n        public rightCurlyCount = 0;\n        public returnStatementsWithExpressions: ReturnStatement[] = [];\n        public scopeType: Type = null; // Type of the FuncDecl, before target typing\n        public endingToken: ASTSpan = null;\n        public isDeclaration() { return true; }\n\n        constructor (public name: Identifier, public bod: ASTList, public isConstructor: bool,\n                     public arguments: ASTList, public vars: ASTList, public scopes: ASTList, public statics: ASTList,\n                     nodeType: number) {\n\n            super(nodeType);\n        }\n\n        public internalName(): string {\n            if (this.internalNameCache == null) {\n                var extName = this.getNameText();\n                if (extName) {\n                    this.internalNameCache = \"_internal_\" + extName;\n                }\n                else {\n                    this.internalNameCache = \"_internal_\" + internalId++;\n                }\n            }\n            return this.internalNameCache;\n        }\n\n        public hasSelfReference() { return hasFlag(this.fncFlags, FncFlags.HasSelfReference); }\n        public setHasSelfReference() { this.fncFlags |= FncFlags.HasSelfReference; }\n\n        public hasSuperReferenceInFatArrowFunction() { return hasFlag(this.fncFlags, FncFlags.HasSuperReferenceInFatArrowFunction); }\n        public setHasSuperReferenceInFatArrowFunction() { this.fncFlags |= FncFlags.HasSuperReferenceInFatArrowFunction; }\n\n        public addCloRef(id: Identifier, sym: Symbol): number {\n            if (this.envids == null) {\n                this.envids = new Identifier[];\n            }\n            this.envids[this.envids.length] = id;\n            var outerFnc = this.enclosingFnc;\n            if (sym) {\n                while (outerFnc && (outerFnc.type.symbol != sym.container)) {\n                    outerFnc.addJumpRef(sym);\n                    outerFnc = outerFnc.enclosingFnc;\n                }\n            }\n            return this.envids.length - 1;\n        }\n\n        public addJumpRef(sym: Symbol): void {\n            if (this.jumpRefs == null) {\n                this.jumpRefs = new Identifier[];\n            }\n            var id = new Identifier(sym.name);\n            this.jumpRefs[this.jumpRefs.length] = id;\n            id.sym = sym;\n            id.cloId = this.addCloRef(id, null);\n        }\n\n        public buildControlFlow(): ControlFlowContext {\n            var entry = new BasicBlock();\n            var exit = new BasicBlock();\n\n            var context = new ControlFlowContext(entry, exit);\n\n            var controlFlowPrefix = (ast: AST, parent: AST, walker: IAstWalker) => {\n                ast.addToControlFlow(walker.state);\n                return ast;\n            }\n\n            var walker = getAstWalkerFactory().getWalker(controlFlowPrefix, null, null, context);\n            context.walker = walker;\n            walker.walk(this.bod, this);\n\n            return context;\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckFunction(this);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitJavascriptFunction(this);\n        }\n\n        public getNameText() {\n            if (this.name) {\n                return this.name.actualText;\n            }\n            else {\n                return this.hint;\n            }\n        }\n\n        public isMethod() {\n            return (this.fncFlags & FncFlags.Method) != FncFlags.None;\n        }\n\n        public isCallMember() { return hasFlag(this.fncFlags, FncFlags.CallMember); }\n        public isConstructMember() { return hasFlag(this.fncFlags, FncFlags.ConstructMember); }\n        public isIndexerMember() { return hasFlag(this.fncFlags, FncFlags.IndexerMember); }\n        public isSpecialFn() { return this.isCallMember() || this.isIndexerMember() || this.isConstructMember(); }\n        public isAnonymousFn() { return this.name === null; }\n        public isAccessor() { return hasFlag(this.fncFlags, FncFlags.GetAccessor) || hasFlag(this.fncFlags, FncFlags.SetAccessor); }\n        public isGetAccessor() { return hasFlag(this.fncFlags, FncFlags.GetAccessor); }\n        public isSetAccessor() { return hasFlag(this.fncFlags, FncFlags.SetAccessor); }\n        public isAmbient() { return hasFlag(this.fncFlags, FncFlags.Ambient); }\n        public isExported() { return hasFlag(this.fncFlags, FncFlags.Exported); }\n        public isPrivate() { return hasFlag(this.fncFlags, FncFlags.Private); }\n        public isPublic() { return hasFlag(this.fncFlags, FncFlags.Public); }\n        public isStatic() { return hasFlag(this.fncFlags, FncFlags.Static); }\n\n        public treeViewLabel() {\n            if (this.name == null) {\n                return \"funcExpr\";\n            }\n            else {\n                return \"func: \" + this.name.actualText\n            }\n        }\n\n        public ClearFlags(): void {\n            this.fncFlags = FncFlags.None;\n        }\n\n        public isSignature() { return (this.fncFlags & FncFlags.Signature) != FncFlags.None; }\n    }\n\n    export class LocationInfo {\n        constructor (public filename: string, public lineMap: number[], public unitIndex) { }\n    }\n\n    export var unknownLocationInfo = new LocationInfo(\"unknown\", null, -1);\n\n    export class Script extends FuncDecl {\n        public locationInfo: LocationInfo = null;\n        public referencedFiles: IFileReference[] = [];\n        public requiresGlobal = false;\n        public requiresExtendsBlock = false;\n        public isResident = false;\n        public isDeclareFile = false;\n        public hasBeenTypeChecked = false;\n        public topLevelMod: ModuleDeclaration = null;\n        public leftCurlyCount = 0;\n        public rightCurlyCount = 0;\n        public vars: ASTList;\n        public scopes: ASTList;\n        // Remember if the script contains Unicode chars, that is needed when generating code for this script object to decide the output file correct encoding.\n        public containsUnicodeChar = false;\n        public containsUnicodeCharInComment = false;\n        public cachedEmitRequired: bool;\n\n        private setCachedEmitRequired(value: bool) {\n            this.cachedEmitRequired = value;\n            return this.cachedEmitRequired;\n        }\n\n        constructor (vars: ASTList, scopes: ASTList) {\n            super(new Identifier(\"script\"), null, false, null, vars, scopes, null, NodeType.Script);\n            this.vars = vars;\n            this.scopes = scopes;\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckScript(this);\n        }\n\n        public treeViewLabel() {\n            return \"Script\";\n        }\n\n        public emitRequired(emitOptions: EmitOptions) {\n            if (this.cachedEmitRequired != undefined) {\n                return this.cachedEmitRequired;\n            }\n\n            if (!this.isDeclareFile && !this.isResident && this.bod) {\n                if (this.bod.members.length == 0) {\n                    // allow empty files that are not declare files \n                    return this.setCachedEmitRequired(true);\n                }\n\n                for (var i = 0, len = this.bod.members.length; i < len; i++) {\n                    var stmt = this.bod.members[i];\n                    if (stmt.nodeType == NodeType.ModuleDeclaration) {\n                        if (!hasFlag((<ModuleDeclaration>stmt).modFlags, ModuleFlags.ShouldEmitModuleDecl | ModuleFlags.Ambient)) {\n                            return this.setCachedEmitRequired(true);\n                        }\n                    }\n                    else if (stmt.nodeType == NodeType.ClassDeclaration) {\n                        if (!hasFlag((<ClassDeclaration>stmt).varFlags, VarFlags.Ambient)) {\n                            return this.setCachedEmitRequired(true);\n                        }\n                    }\n                    else if (stmt.nodeType == NodeType.VarDecl) {\n                        if (!hasFlag((<VarDecl>stmt).varFlags, VarFlags.Ambient)) {\n                            return this.setCachedEmitRequired(true);\n                        }\n                    }\n                    else if (stmt.nodeType == NodeType.FuncDecl) {\n                        if (!(<FuncDecl>stmt).isSignature()) {\n                            return this.setCachedEmitRequired(true);\n                        }\n                    }\n                    else if (stmt.nodeType != NodeType.InterfaceDeclaration && stmt.nodeType != NodeType.Empty) {\n                        return this.setCachedEmitRequired(true);\n                    }\n                }\n\n                if ( emitOptions.emitComments &&\n                    ((this.bod.preComments && this.bod.preComments.length > 0) || (this.bod.postComments && this.bod.postComments.length > 0))) {\n                    return this.setCachedEmitRequired(true);\n                }\n            }\n            return this.setCachedEmitRequired(false);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            if (this.emitRequired(emitter.emitOptions)) {\n                emitter.emitParensAndCommentsInPlace(this.bod, true);\n                emitter.emitJavascriptList(this.bod, null, TokenID.Semicolon, true, false, false, true, this.requiresExtendsBlock);\n                emitter.emitParensAndCommentsInPlace(this.bod, false);\n            }\n        }\n\n        private externallyVisibleImportedSymbols: Symbol[] = [];\n\n        public AddExternallyVisibleImportedSymbol(symbol: Symbol, checker: TypeChecker) {\n            if (this.isExternallyVisibleSymbol(symbol)) {\n                return;\n            }\n\n            // Before adding check if the external symbol is also marked for visibility\n            if (!symbol.getType().symbol.isExternallyVisible(checker)) {\n                // Report error\n                var quotes = \"\";\n                var moduleName = symbol.getType().symbol.prettyName;\n                if (!isQuoted(moduleName)) {\n                    quotes = \"'\";\n                }\n                checker.errorReporter.simpleError(symbol.declAST, \"Externally visible import statement uses non exported module \" + quotes + moduleName + quotes);\n            }\n            this.externallyVisibleImportedSymbols.push(symbol);\n        }\n\n        public isExternallyVisibleSymbol(symbol: Symbol) {\n            for (var i = 0 ; i < this.externallyVisibleImportedSymbols.length; i++) {\n                if (this.externallyVisibleImportedSymbols[i] == symbol) {\n                    return true;\n                }\n            }\n            return false;\n        }\n    }\n\n    export class NamedDeclaration extends ModuleElement {\n        public leftCurlyCount = 0;\n        public rightCurlyCount = 0;\n        public isDeclaration() { return true; }\n\n        constructor (nodeType: NodeType,\n                     public name: Identifier,\n                     public members: ASTList) {\n            super(nodeType);\n        }\n    }\n\n    export class ModuleDeclaration extends NamedDeclaration {\n        public modFlags = ModuleFlags.ShouldEmitModuleDecl;\n        public mod: ModuleType;\n        public prettyName: string;\n        public amdDependencies: string[] = [];\n        public vars: ASTList;\n        public scopes: ASTList;\n        // Remember if the module contains Unicode chars, that is needed for dynamic module as we will generate a file for each.\n        public containsUnicodeChar = false;\n        public containsUnicodeCharInComment = false;\n\n        constructor (name: Identifier, members: ASTList, vars: ASTList, scopes: ASTList, public endingToken: ASTSpan) {\n            super(NodeType.ModuleDeclaration, name, members);\n\n            this.vars = vars;\n            this.scopes = scopes;\n            this.prettyName = this.name.actualText;\n        }\n\n        public isExported() { return hasFlag(this.modFlags, ModuleFlags.Exported); }\n        public isAmbient() { return hasFlag(this.modFlags, ModuleFlags.Ambient); }\n        public isEnum() { return hasFlag(this.modFlags, ModuleFlags.IsEnum); }\n\n        public recordNonInterface() {\n            this.modFlags &= ~ModuleFlags.ShouldEmitModuleDecl;\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckModule(this);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            if (!hasFlag(this.modFlags, ModuleFlags.ShouldEmitModuleDecl)) {\n                emitter.emitParensAndCommentsInPlace(this, true);\n                emitter.emitJavascriptModule(this);\n                emitter.emitParensAndCommentsInPlace(this, false);\n            }\n        }\n    }\n\n    export class TypeDeclaration extends NamedDeclaration {\n        public varFlags = VarFlags.None;\n\n        constructor (nodeType: NodeType,\n                     name: Identifier,\n                     public extendsList: ASTList,\n                     public implementsList: ASTList,\n                     members: ASTList) {\n            super(nodeType, name, members);\n        }\n\n        public isExported() { \n            return hasFlag(this.varFlags, VarFlags.Exported);\n        }\n\n        public isAmbient() {\n            return hasFlag(this.varFlags, VarFlags.Ambient);\n        }\n    }\n\n    export class ClassDeclaration extends TypeDeclaration {\n        public knownMemberNames: any = {};\n        public constructorDecl: FuncDecl = null;\n        public constructorNestingLevel = 0;\n        public endingToken: ASTSpan = null;\n\n        constructor (name: Identifier,\n                     members: ASTList,\n                     extendsList: ASTList,\n                     implementsList: ASTList) {\n            super(NodeType.ClassDeclaration, name, extendsList, implementsList, members);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckClass(this);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitJavascriptClass(this);\n        }\n    }\n\n    export class InterfaceDeclaration extends TypeDeclaration {\n        constructor (name: Identifier,\n                     members: ASTList,\n                     extendsList: ASTList,\n                     implementsList: ASTList) {\n            super(NodeType.InterfaceDeclaration, name, extendsList, implementsList, members);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckInterface(this);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n        }\n    }\n\n    export class Statement extends ModuleElement {\n        constructor (nodeType: NodeType) {\n            super(nodeType);\n            this.flags |= ASTFlags.IsStatement;\n        }\n\n        public isLoop() { return false; }\n\n        public isStatementOrExpression() { return true; }\n\n        public isCompoundStatement() { return this.isLoop(); }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.type = typeFlow.voidType;\n            return this;\n        }\n    }\n\n    export class LabeledStatement extends Statement {\n        constructor (public labels: ASTList, public stmt: AST) {\n            super(NodeType.LabeledStatement);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            if (this.labels) {\n                var labelsLen = this.labels.members.length;\n                for (var i = 0; i < labelsLen; i++) {\n                    this.labels.members[i].emit(emitter, tokenId, startLine);\n                }\n            }\n            this.stmt.emit(emitter, tokenId, true);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            typeFlow.typeCheck(this.labels);\n            this.stmt = this.stmt.typeCheck(typeFlow);\n            return this;\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            var beforeBB = context.current;\n            var bb = new BasicBlock();\n            context.current = bb;\n            beforeBB.addSuccessor(bb);\n        }\n    }\n\n    export class Block extends Statement {\n        constructor (public statements: ASTList,\n                     public isStatementBlock: bool) {\n            super(NodeType.Block);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            if (this.isStatementBlock) {\n                emitter.writeLineToOutput(\" {\");\n                emitter.indenter.increaseIndent();\n            } else {\n                emitter.setInVarBlock(this.statements.members.length);\n            }\n            var temp = emitter.setInObjectLiteral(false);\n            if (this.statements) {\n                emitter.emitJavascriptList(this.statements, null, TokenID.Semicolon, true, false, false);\n            }\n            if (this.isStatementBlock) {\n                emitter.indenter.decreaseIndent();\n                emitter.emitIndent();\n                emitter.writeToOutput(\"}\");\n            }\n            emitter.setInObjectLiteral(temp);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public addToControlFlow(context: ControlFlowContext) {\n            var afterIfNeeded = new BasicBlock();\n            context.pushStatement(this, context.current, afterIfNeeded);\n            if (this.statements) {\n                context.walk(this.statements, this);\n            }\n            context.walker.options.goChildren = false;\n            context.popStatement();\n            if (afterIfNeeded.predecessors.length > 0) {\n                context.current.addSuccessor(afterIfNeeded);\n                context.current = afterIfNeeded;\n            }\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            if (!typeFlow.checker.styleSettings.emptyBlocks) {\n                if ((this.statements === null) || (this.statements.members.length == 0)) {\n                    typeFlow.checker.errorReporter.styleError(this, \"empty block\");\n                }\n            }\n\n            typeFlow.typeCheck(this.statements);\n            return this;\n        }\n    }\n\n    export class Jump extends Statement {\n        public target: string = null;\n        public hasExplicitTarget() { return (this.target); }\n        public resolvedTarget: Statement = null;\n\n        constructor (nodeType: NodeType) {\n            super(nodeType);\n        }\n\n        public setResolvedTarget(parser: Parser, stmt: Statement): bool {\n            if (stmt.isLoop()) {\n                this.resolvedTarget = stmt;\n                return true;\n            }\n            if (this.nodeType === NodeType.Continue) {\n                parser.reportParseError(\"continue statement applies only to loops\");\n                return false;\n            }\n            else {\n                if ((stmt.nodeType == NodeType.Switch) || this.hasExplicitTarget()) {\n                    this.resolvedTarget = stmt;\n                    return true;\n                }\n                else {\n                    parser.reportParseError(\"break statement with no label can apply only to a loop or switch statement\");\n                    return false;\n                }\n            }\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            super.addToControlFlow(context);\n            context.unconditionalBranch(this.resolvedTarget, (this.nodeType == NodeType.Continue));\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            if (this.nodeType == NodeType.Break) {\n                emitter.writeToOutput(\"break\");\n            }\n            else {\n                emitter.writeToOutput(\"continue\");\n            }\n            if (this.hasExplicitTarget()) {\n                emitter.writeToOutput(\" \" + this.target);\n            }\n            emitter.recordSourceMappingEnd(this);\n            emitter.writeToOutput(\";\");\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n\n    export class WhileStatement extends Statement {\n        public body: AST = null;\n\n        constructor (public cond: AST) {\n            super(NodeType.While);\n        }\n\n        public isLoop() { return true; }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            var temp = emitter.setInObjectLiteral(false);\n            emitter.writeToOutput(\"while(\");\n            emitter.emitJavascript(this.cond, TokenID.While, false);\n            emitter.writeToOutput(\")\");\n            emitter.emitJavascriptStatements(this.body, false);\n            emitter.setInObjectLiteral(temp);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckWhile(this);\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            var loopHeader = context.current;\n            var loopStart = new BasicBlock();\n            var afterLoop = new BasicBlock();\n\n            loopHeader.addSuccessor(loopStart);\n            context.current = loopStart;\n            context.addContent(this.cond);\n            var condBlock = context.current;\n            var targetInfo: ITargetInfo = null;\n            if (this.body) {\n                context.current = new BasicBlock();\n                condBlock.addSuccessor(context.current);\n                context.pushStatement(this, loopStart, afterLoop);\n                context.walk(this.body, this);\n                targetInfo = context.popStatement();\n            }\n            if (!(context.noContinuation)) {\n                var loopEnd = context.current;\n                loopEnd.addSuccessor(loopStart);\n            }\n            context.current = afterLoop;\n            condBlock.addSuccessor(afterLoop);\n            // TODO: check for while (true) and then only continue if afterLoop has predecessors\n            context.noContinuation = false;\n            context.walker.options.goChildren = false;\n        }\n    }\n\n    export class DoWhileStatement extends Statement {\n        public body: AST = null;\n        public whileAST: AST = null;\n        public cond: AST = null;\n        public isLoop() { return true; }\n\n        constructor () {\n            super(NodeType.DoWhile);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            var temp = emitter.setInObjectLiteral(false);\n            emitter.writeToOutput(\"do\");\n            emitter.emitJavascriptStatements(this.body, true);\n            emitter.recordSourceMappingStart(this.whileAST);\n            emitter.writeToOutput(\"while\");\n            emitter.recordSourceMappingEnd(this.whileAST);\n            emitter.writeToOutput('(');\n            emitter.emitJavascript(this.cond, TokenID.CloseParen, false);\n            emitter.writeToOutput(\")\");\n            emitter.setInObjectLiteral(temp);\n            emitter.recordSourceMappingEnd(this);\n            emitter.writeToOutput(\";\");\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckDoWhile(this);\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            var loopHeader = context.current;\n            var loopStart = new BasicBlock();\n            var afterLoop = new BasicBlock();\n            loopHeader.addSuccessor(loopStart);\n            context.current = loopStart;\n            var targetInfo: ITargetInfo = null;\n            if (this.body) {\n                context.pushStatement(this, loopStart, afterLoop);\n                context.walk(this.body, this);\n                targetInfo = context.popStatement();\n            }\n            if (!(context.noContinuation)) {\n                var loopEnd = context.current;\n                loopEnd.addSuccessor(loopStart);\n                context.addContent(this.cond);\n                // TODO: check for while (true) \n                context.current = afterLoop;\n                loopEnd.addSuccessor(afterLoop);\n            }\n            else {\n                context.addUnreachable(this.cond);\n            }\n            context.walker.options.goChildren = false;\n        }\n    }\n\n    export class IfStatement extends Statement {\n        public thenBod: AST;\n        public elseBod: AST = null;\n        public statement: ASTSpan = new ASTSpan();\n\n        constructor (public cond: AST) {\n            super(NodeType.If);\n        }\n\n        public isCompoundStatement() { return true; }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            var temp = emitter.setInObjectLiteral(false);\n            emitter.recordSourceMappingStart(this.statement);\n            emitter.writeToOutput(\"if(\");\n            emitter.emitJavascript(this.cond, TokenID.If, false);\n            emitter.writeToOutput(\")\");\n            emitter.recordSourceMappingEnd(this.statement);\n            emitter.emitJavascriptStatements(this.thenBod, true);\n            if (this.elseBod) {\n                if (this.elseBod.nodeType === NodeType.If) {\n                    emitter.writeToOutput(\" else \");\n                    this.elseBod.emit(emitter, tokenId, /*startLine:*/ false);\n                }\n                else {\n                    emitter.writeToOutput(\" else\");\n                    emitter.emitJavascriptStatements(this.elseBod, true);\n                }\n            }\n            emitter.setInObjectLiteral(temp);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckIf(this);\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            this.cond.addToControlFlow(context);\n            var afterIf = new BasicBlock();\n            var beforeIf = context.current;\n            context.pushStatement(this, beforeIf, afterIf);\n            var hasContinuation = false;\n            context.current = new BasicBlock();\n            beforeIf.addSuccessor(context.current);\n            context.walk(this.thenBod, this);\n            if (!context.noContinuation) {\n                hasContinuation = true;\n                context.current.addSuccessor(afterIf);\n            }\n            if (this.elseBod) {\n                // current block will be thenBod\n                context.current = new BasicBlock();\n                context.noContinuation = false;\n                beforeIf.addSuccessor(context.current);\n                context.walk(this.elseBod, this);\n                if (!context.noContinuation) {\n                    hasContinuation = true;\n                    context.current.addSuccessor(afterIf);\n                }\n                else {\n                    // thenBod created continuation for if statement\n                    if (hasContinuation) {\n                        context.noContinuation = false;\n                    }\n                }\n            }\n            else {\n                beforeIf.addSuccessor(afterIf);\n                context.noContinuation = false;\n                hasContinuation = true;\n            }\n            var targetInfo = context.popStatement();\n            if (afterIf.predecessors.length > 0) {\n                context.noContinuation = false;\n                hasContinuation = true;\n            }\n            if (hasContinuation) {\n                context.current = afterIf;\n            }\n            context.walker.options.goChildren = false;\n        }\n    }\n\n    export class ReturnStatement extends Statement {\n        public returnExpression: AST = null;\n\n        constructor () {\n            super(NodeType.Return);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            var temp = emitter.setInObjectLiteral(false);\n            if (this.returnExpression) {\n                emitter.writeToOutput(\"return \");\n                emitter.emitJavascript(this.returnExpression, TokenID.Semicolon, false);\n\n                if (this.returnExpression.nodeType === NodeType.FuncDecl) {\n                    emitter.writeToOutput(\";\");\n                }\n            }\n            else {\n                emitter.writeToOutput(\"return;\");\n            }\n            emitter.setInObjectLiteral(temp);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            super.addToControlFlow(context);\n            context.returnStmt();\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckReturn(this);\n        }\n    }\n\n    export class EndCode extends AST {\n        constructor () {\n            super(NodeType.EndCode);\n        }\n    }\n\n    export class ForInStatement extends Statement {\n        constructor (public lval: AST, public obj: AST) {\n            super(NodeType.ForIn);\n            if (this.lval && (this.lval.nodeType == NodeType.VarDecl)) {\n                (<BoundDecl>this.lval).varFlags |= VarFlags.AutoInit;\n            }\n        }\n        public statement: ASTSpan = new ASTSpan();\n        public body: AST;\n\n        public isLoop() { return true; }\n\n        public isFiltered() {\n            if (this.body) {\n                var singleItem: AST = null;\n                if (this.body.nodeType == NodeType.List) {\n                    var stmts = <ASTList>this.body;\n                    if (stmts.members.length == 1) {\n                        singleItem = stmts.members[0];\n                    }\n                }\n                else {\n                    singleItem = this.body;\n                }\n                // match template for filtering 'own' properties from obj\n                if (singleItem !== null) {\n                    if (singleItem.nodeType == NodeType.Block) {\n                        var block = <Block>singleItem;\n                        if ((block.statements !== null) && (block.statements.members.length == 1)) {\n                            singleItem = block.statements.members[0];\n                        }\n                    }\n                    if (singleItem.nodeType == NodeType.If) {\n                        var cond = (<IfStatement>singleItem).cond;\n                        if (cond.nodeType == NodeType.Call) {\n                            var target = (<CallExpression>cond).target;\n                            if (target.nodeType == NodeType.Dot) {\n                                var binex = <BinaryExpression>target;\n                                if ((binex.operand1.nodeType == NodeType.Name) &&\n                                    (this.obj.nodeType == NodeType.Name) &&\n                                    ((<Identifier>binex.operand1).actualText == (<Identifier>this.obj).actualText)) {\n                                    var prop = <Identifier>binex.operand2;\n                                    if (prop.actualText == \"hasOwnProperty\") {\n                                        var args = (<CallExpression>cond).arguments;\n                                        if ((args !== null) && (args.members.length == 1)) {\n                                            var arg = args.members[0];\n                                            if ((arg.nodeType == NodeType.Name) &&\n                                                 (this.lval.nodeType == NodeType.Name)) {\n                                                if (((<Identifier>this.lval).actualText) == (<Identifier>arg).actualText) {\n                                                    return true;\n                                                }\n                                            }\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n            return false;\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            var temp = emitter.setInObjectLiteral(false);\n            emitter.recordSourceMappingStart(this.statement);\n            emitter.writeToOutput(\"for(\");\n            emitter.emitJavascript(this.lval, TokenID.For, false);\n            emitter.writeToOutput(\" in \");\n            emitter.emitJavascript(this.obj, TokenID.For, false);\n            emitter.writeToOutput(\")\");\n            emitter.recordSourceMappingEnd(this.statement);\n            emitter.emitJavascriptStatements(this.body, true);\n            emitter.setInObjectLiteral(temp);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            if (typeFlow.checker.styleSettings.forin) {\n                if (!this.isFiltered()) {\n                    typeFlow.checker.errorReporter.styleError(this, \"no hasOwnProperty filter\");\n                }\n            }\n            return typeFlow.typeCheckForIn(this);\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            if (this.lval) {\n                context.addContent(this.lval);\n            }\n            if (this.obj) {\n                context.addContent(this.obj);\n            }\n\n            var loopHeader = context.current;\n            var loopStart = new BasicBlock();\n            var afterLoop = new BasicBlock();\n\n            loopHeader.addSuccessor(loopStart);\n            context.current = loopStart;\n            if (this.body) {\n                context.pushStatement(this, loopStart, afterLoop);\n                context.walk(this.body, this);\n                context.popStatement();\n            }\n            if (!(context.noContinuation)) {\n                var loopEnd = context.current;\n                loopEnd.addSuccessor(loopStart);\n            }\n            context.current = afterLoop;\n            context.noContinuation = false;\n            loopHeader.addSuccessor(afterLoop);\n            context.walker.options.goChildren = false;\n        }\n    }\n\n    export class ForStatement extends Statement {\n        public cond: AST;\n        public body: AST;\n        public incr: AST;\n\n        constructor (public init: AST) {\n            super(NodeType.For);\n        }\n\n        public isLoop() { return true; }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            var temp = emitter.setInObjectLiteral(false);\n            emitter.writeToOutput(\"for(\");\n            if (this.init) {\n                if (this.init.nodeType != NodeType.List) {\n                    emitter.emitJavascript(this.init, TokenID.For, false);\n                }\n                else {\n                    emitter.setInVarBlock((<ASTList>this.init).members.length); \n                    emitter.emitJavascriptList(this.init, null, TokenID.For, false, false, false);\n                }\n            }\n            emitter.writeToOutput(\"; \");\n            emitter.emitJavascript(this.cond, TokenID.For, false);\n            emitter.writeToOutput(\"; \");\n            emitter.emitJavascript(this.incr, TokenID.For, false);\n            emitter.writeToOutput(\")\");\n            emitter.emitJavascriptStatements(this.body, true);\n            emitter.setInObjectLiteral(temp);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckFor(this);\n        }\n\n        public addToControlFlow(context: ControlFlowContext): void {\n            if (this.init) {\n                context.addContent(this.init);\n            }\n            var loopHeader = context.current;\n            var loopStart = new BasicBlock();\n            var afterLoop = new BasicBlock();\n\n            loopHeader.addSuccessor(loopStart);\n            context.current = loopStart;\n            var condBlock: BasicBlock = null;\n            var continueTarget = loopStart;\n            var incrBB: BasicBlock = null;\n            if (this.incr) {\n                incrBB = new BasicBlock();\n                continueTarget = incrBB;\n            }\n            if (this.cond) {\n                condBlock = context.current;\n                context.addContent(this.cond);\n                context.current = new BasicBlock();\n                condBlock.addSuccessor(context.current);\n            }\n            var targetInfo: ITargetInfo = null;\n            if (this.body) {\n                context.pushStatement(this, continueTarget, afterLoop);\n                context.walk(this.body, this);\n                targetInfo = context.popStatement();\n            }\n            if (this.incr) {\n                if (context.noContinuation) {\n                    if (incrBB.predecessors.length == 0) {\n                        context.addUnreachable(this.incr);\n                    }\n                }\n                else {\n                    context.current.addSuccessor(incrBB);\n                    context.current = incrBB;\n                    context.addContent(this.incr);\n                }\n            }\n            var loopEnd = context.current;\n            if (!(context.noContinuation)) {\n                loopEnd.addSuccessor(loopStart);\n\n            }\n            if (condBlock) {\n                condBlock.addSuccessor(afterLoop);\n                context.noContinuation = false;\n            }\n            if (afterLoop.predecessors.length > 0) {\n                context.noContinuation = false;\n                context.current = afterLoop;\n            }\n            context.walker.options.goChildren = false;\n        }\n    }\n\n    export class WithStatement extends Statement {\n        public body: AST;\n\n        public isCompoundStatement() { return true; }\n\n        public withSym: WithSymbol = null;\n\n        constructor (public expr: AST) {\n            super(NodeType.With);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.writeToOutput(\"with (\");\n            if (this.expr) {\n                emitter.emitJavascript(this.expr, TokenID.With, false);\n            }\n\n            emitter.writeToOutput(\")\");\n            emitter.emitJavascriptStatements(this.body, true);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            return typeFlow.typeCheckWith(this);\n        }\n    }\n\n    export class SwitchStatement extends Statement {\n        public caseList: ASTList;\n        public defaultCase: CaseStatement = null;\n        public statement: ASTSpan = new ASTSpan();\n\n        constructor (public val: AST) {\n            super(NodeType.Switch);\n        }\n\n        public isCompoundStatement() { return true; }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            var temp = emitter.setInObjectLiteral(false);\n            emitter.recordSourceMappingStart(this.statement);\n            emitter.writeToOutput(\"switch(\");\n            emitter.emitJavascript(this.val, TokenID.Identifier, false);\n            emitter.writeToOutput(\")\"); \n            emitter.recordSourceMappingEnd(this.statement);\n            emitter.writeLineToOutput(\" {\");\n            emitter.indenter.increaseIndent();\n            var casesLen = this.caseList.members.length;\n            for (var i = 0; i < casesLen; i++) {\n                var caseExpr = this.caseList.members[i];\n                emitter.emitJavascript(caseExpr, TokenID.Case, true);\n            }\n            emitter.indenter.decreaseIndent();\n            emitter.emitIndent();\n            emitter.writeToOutput(\"}\");\n            emitter.setInObjectLiteral(temp);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            var len = this.caseList.members.length;\n            this.val = typeFlow.typeCheck(this.val);\n            for (var i = 0; i < len; i++) {\n                this.caseList.members[i] = typeFlow.typeCheck(this.caseList.members[i]);\n            }\n            this.defaultCase = <CaseStatement>typeFlow.typeCheck(this.defaultCase);\n            this.type = typeFlow.voidType;\n            return this;\n        }\n\n        // if there are break statements that match this switch, then just link cond block with block after switch\n        public addToControlFlow(context: ControlFlowContext) {\n            var condBlock = context.current;\n            context.addContent(this.val);\n            var execBlock = new BasicBlock();\n            var afterSwitch = new BasicBlock();\n\n            condBlock.addSuccessor(execBlock);\n            context.pushSwitch(execBlock);\n            context.current = execBlock;\n            context.pushStatement(this, execBlock, afterSwitch);\n            context.walk(this.caseList, this);\n            context.popSwitch();\n            var targetInfo = context.popStatement();\n            var hasCondContinuation = (this.defaultCase == null);\n            if (this.defaultCase == null) {\n                condBlock.addSuccessor(afterSwitch);\n            }\n            if (afterSwitch.predecessors.length > 0) {\n                context.noContinuation = false;\n                context.current = afterSwitch;\n            }\n            else {\n                context.noContinuation = true;\n            }\n            context.walker.options.goChildren = false;\n        }\n    }\n\n    export class CaseStatement extends Statement {\n        public expr: AST = null;\n        public body: ASTList;\n\n        constructor () {\n            super(NodeType.Case);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            if (this.expr) {\n                emitter.writeToOutput(\"case \");\n                emitter.emitJavascript(this.expr, TokenID.Identifier, false);\n            }\n            else {\n                emitter.writeToOutput(\"default\");\n            }\n            emitter.writeToOutput(\":\");\n            if (this.body.members.length == 1 && this.body.members[0].nodeType == NodeType.Block) {\n                // The case statement was written with curly braces, so emit it with the appropriate formatting\n                emitter.emitJavascriptStatements(this.body, false);\n            }\n            else {\n                // No curly braces. Format in the expected way\n                emitter.writeLineToOutput(\"\");\n                emitter.indenter.increaseIndent();\n                emitter.emitBareJavascriptStatements(this.body);\n                emitter.indenter.decreaseIndent();\n            }\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.expr = typeFlow.typeCheck(this.expr);\n            typeFlow.typeCheck(this.body);\n            this.type = typeFlow.voidType;\n            return this;\n        }\n\n        // TODO: more reasoning about unreachable cases (such as duplicate literals as case expressions)\n        // for now, assume all cases are reachable, regardless of whether some cases fall through\n        public addToControlFlow(context: ControlFlowContext) {\n            var execBlock = new BasicBlock();\n            var sw = context.currentSwitch[context.currentSwitch.length - 1];\n            // TODO: fall-through from previous (+ to end of switch)\n            if (this.expr) {\n                var exprBlock = new BasicBlock();\n                context.current = exprBlock;\n                sw.addSuccessor(exprBlock);\n                context.addContent(this.expr);\n                exprBlock.addSuccessor(execBlock);\n            }\n            else {\n                sw.addSuccessor(execBlock);\n            }\n            context.current = execBlock;\n            if (this.body) {\n                context.walk(this.body, this);\n            }\n            context.noContinuation = false;\n            context.walker.options.goChildren = false;\n        }\n    }\n\n    export class TypeReference extends AST {\n        constructor (public term: AST, public arrayCount: number) {\n            super(NodeType.TypeRef);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            throw new Error(\"should not emit a type ref\");\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            var prevInTCTR = typeFlow.inTypeRefTypeCheck;\n            typeFlow.inTypeRefTypeCheck = true;\n            var typeLink = getTypeLink(this, typeFlow.checker, true);\n            typeFlow.checker.resolveTypeLink(typeFlow.scope, typeLink, false);\n\n            if (this.term) {\n                typeFlow.typeCheck(this.term);\n            }\n\n            typeFlow.checkForVoidConstructor(typeLink.type, this);\n\n            this.type = typeLink.type;\n\n            // in error recovery cases, there may not be a term\n            if (this.term) {\n                this.term.type = this.type;\n            }\n\n            typeFlow.inTypeRefTypeCheck = prevInTCTR;\n            return this;\n        }\n    }\n\n    export class TryFinally extends Statement {\n        constructor (public tryNode: AST, public finallyNode: Finally) {\n            super(NodeType.TryFinally);\n        }\n\n        public isCompoundStatement() { return true; }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.recordSourceMappingStart(this);\n            emitter.emitJavascript(this.tryNode, TokenID.Try, false);\n            emitter.emitJavascript(this.finallyNode, TokenID.Finally, false);\n            emitter.recordSourceMappingEnd(this);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.tryNode = typeFlow.typeCheck(this.tryNode);\n            this.finallyNode = <Finally>typeFlow.typeCheck(this.finallyNode);\n            this.type = typeFlow.voidType;\n            return this;\n        }\n\n        public addToControlFlow(context: ControlFlowContext) {\n            var afterFinally = new BasicBlock();\n            context.walk(this.tryNode, this);\n            var finBlock = new BasicBlock();\n            if (context.current) {\n                context.current.addSuccessor(finBlock);\n            }\n            context.current = finBlock;\n            context.pushStatement(this, null, afterFinally);\n            context.walk(this.finallyNode, this);\n            if (!context.noContinuation && context.current) {\n                context.current.addSuccessor(afterFinally);\n            }\n            if (afterFinally.predecessors.length > 0) {\n                context.current = afterFinally;\n            }\n            else {\n                context.noContinuation = true;\n            }\n            context.popStatement();\n            context.walker.options.goChildren = false;\n        }\n    }\n\n    export class TryCatch extends Statement {\n        constructor (public tryNode: Try, public catchNode: Catch) {\n            super(NodeType.TryCatch);\n        }\n\n        public isCompoundStatement() { return true; }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.emitJavascript(this.tryNode, TokenID.Try, false);\n            emitter.emitJavascript(this.catchNode, TokenID.Catch, false);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public addToControlFlow(context: ControlFlowContext) {\n            var beforeTry = context.current;\n            var tryBlock = new BasicBlock();\n            beforeTry.addSuccessor(tryBlock);\n            context.current = tryBlock;\n            var afterTryCatch = new BasicBlock();\n            context.pushStatement(this, null, afterTryCatch);\n            context.walk(this.tryNode, this);\n            if (!context.noContinuation) {\n                if (context.current) {\n                    context.current.addSuccessor(afterTryCatch);\n                }\n            }\n            context.current = new BasicBlock();\n            beforeTry.addSuccessor(context.current);\n            context.walk(this.catchNode, this);\n            context.popStatement();\n            if (!context.noContinuation) {\n                if (context.current) {\n                    context.current.addSuccessor(afterTryCatch);\n                }\n            }\n            context.current = afterTryCatch;\n            context.walker.options.goChildren = false;\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.tryNode = <Try>typeFlow.typeCheck(this.tryNode);\n            this.catchNode = <Catch>typeFlow.typeCheck(this.catchNode);\n            this.type = typeFlow.voidType;\n            return this;\n        }\n    }\n\n    export class Try extends Statement {\n        constructor (public body: AST) {\n            super(NodeType.Try);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.writeToOutput(\"try \");\n            emitter.emitJavascript(this.body, TokenID.Try, false);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.body = typeFlow.typeCheck(this.body);\n            return this;\n        }\n\n        public addToControlFlow(context: ControlFlowContext) {\n            if (this.body) {\n                context.walk(this.body, this);\n            }\n            context.walker.options.goChildren = false;\n            context.noContinuation = false;\n        }\n    }\n\n    export class Catch extends Statement {\n        constructor (public param: VarDecl, public body: AST) {\n            super(NodeType.Catch);\n            if (this.param) {\n                this.param.varFlags |= VarFlags.AutoInit;\n            }\n        }\n        public statement: ASTSpan = new ASTSpan();\n        public containedScope: SymbolScope = null;\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.writeToOutput(\" \");\n            emitter.recordSourceMappingStart(this.statement);\n            emitter.writeToOutput(\"catch (\");\n            emitter.emitJavascript(this.param, TokenID.OpenParen, false);\n            emitter.writeToOutput(\")\");\n            emitter.recordSourceMappingEnd(this.statement);\n            emitter.emitJavascript(this.body, TokenID.Catch, false);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public addToControlFlow(context: ControlFlowContext) {\n            if (this.param) {\n                context.addContent(this.param);\n                var bodBlock = new BasicBlock();\n                context.current.addSuccessor(bodBlock);\n                context.current = bodBlock;\n            }\n            if (this.body) {\n                context.walk(this.body, this);\n            }\n            context.noContinuation = false;\n            context.walker.options.goChildren = false;\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            var prevScope = typeFlow.scope;\n            typeFlow.scope = this.containedScope;\n            this.param = <VarDecl>typeFlow.typeCheck(this.param);\n            var exceptVar = new ValueLocation();\n            var varSym = new VariableSymbol((<VarDecl>this.param).id.text,\n                                          this.param.minChar,\n                                          typeFlow.checker.locationInfo.unitIndex,\n                                          exceptVar);\n            exceptVar.symbol = varSym;\n            exceptVar.typeLink = new TypeLink();\n            // var type for now (add syntax for type annotation)\n            exceptVar.typeLink.type = typeFlow.anyType;\n            var thisFnc = typeFlow.thisFnc;\n            if (thisFnc && thisFnc.type) {\n                exceptVar.symbol.container = thisFnc.type.symbol;\n            }\n            else {\n                exceptVar.symbol.container = null;\n            }\n            this.param.sym = exceptVar.symbol;\n            typeFlow.scope.enter(exceptVar.symbol.container, this.param, exceptVar.symbol,\n                                 typeFlow.checker.errorReporter, false, false, false);\n            this.body = typeFlow.typeCheck(this.body);\n\n            // if we're in provisional typecheck mode, clean up the symbol entry\n            // REVIEW: This is obviously bad form, since we're counting on the internal\n            // layout of the symbol table, but this is also the only place where we insert\n            // symbols during typecheck\n            if (typeFlow.checker.inProvisionalTypecheckMode()) {\n                var table = typeFlow.scope.getTable();\n                (<any>table).secondaryTable.table[exceptVar.symbol.name] = undefined;\n            }\n            this.type = typeFlow.voidType;\n            typeFlow.scope = prevScope;\n            return this;\n        }\n    }\n\n    export class Finally extends Statement {\n        constructor (public body: AST) {\n            super(NodeType.Finally);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.writeToOutput(\"finally\");\n            emitter.emitJavascript(this.body, TokenID.Finally, false);\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n\n        public addToControlFlow(context: ControlFlowContext) {\n            if (this.body) {\n                context.walk(this.body, this);\n            }\n            context.walker.options.goChildren = false;\n            context.noContinuation = false;\n        }\n\n        public typeCheck(typeFlow: TypeFlow) {\n            this.body = typeFlow.typeCheck(this.body);\n            return this;\n        }\n    }\n\n    export class Comment extends AST {\n\n        public text: string[] = null;\n        public minLine: number;\n        public limLine: number;\n        private docCommentText: string = null;\n\n        constructor (public content: string, public isBlockComment: bool, public endsLine) {\n            super(NodeType.Comment);\n        }\n\n        public getText(): string[] {\n            if (this.text == null) {\n                if (this.isBlockComment) {\n                    this.text = this.content.split(\"\\n\");\n                    for (var i = 0; i < this.text.length; i++) {\n                        this.text[i] = this.text[i].replace(/^\\s+|\\s+$/g, '');\n                    }\n                }\n                else {\n                    this.text = [(this.content.replace(/^\\s+|\\s+$/g, ''))];\n                }\n            }\n\n            return this.text;\n        }\n\n        public isDocComment() {\n            if (this.isBlockComment) {\n                return this.content.charAt(2) == \"*\";\n            }\n\n            return false;\n        }\n\n        public getDocCommentText() {\n            if (this.docCommentText == null) {\n                this.docCommentText = Comment.cleanJSDocComment(this.content);\n            }\n\n            return this.docCommentText;\n        }\n\n        static consumeLeadingSpace(line: string, startIndex: number, maxSpacesToRemove?: number) {\n            var endIndex = line.length;\n            if (maxSpacesToRemove != undefined) {\n                endIndex = min(startIndex + maxSpacesToRemove, endIndex);\n            }\n\n            for (; startIndex < endIndex; startIndex++) {\n                var charCode = line.charCodeAt(startIndex);\n                if (charCode != LexCodeSpace && charCode != LexCodeTAB) {\n                    return startIndex;\n                }\n            }\n            \n            if (endIndex != line.length) {\n                return endIndex;\n            }\n\n            return -1;\n        }\n\n        static isSpaceChar(line: string, index: number) {\n            var length = line.length;\n            if (index < length) {\n                var charCode = line.charCodeAt(index);\n                // If the character is space\n                return charCode == LexCodeSpace || charCode == LexCodeTAB;\n            }\n\n            // If the index is end of the line it is space\n            return index == length;\n        }\n\n        static cleanDocCommentLine(line: string, jsDocStyleComment: bool, jsDocLineSpaceToRemove?: number) {\n            var nonSpaceIndex = Comment.consumeLeadingSpace(line, 0);\n            if (nonSpaceIndex != -1) {\n                var jsDocSpacesRemoved = nonSpaceIndex;\n                if (jsDocStyleComment && line.charAt(nonSpaceIndex) == '*') { // remove leading * in case of jsDocComment\n                    var startIndex = nonSpaceIndex + 1;\n                    nonSpaceIndex = Comment.consumeLeadingSpace(line, startIndex, jsDocLineSpaceToRemove);\n\n                    if (nonSpaceIndex != -1) {\n                        jsDocSpacesRemoved = nonSpaceIndex - startIndex;\n                    } else {\n                        return null;\n                    }\n                }\n\n                return {\n                    minChar: nonSpaceIndex,\n                    limChar: line.charAt(line.length - 1) == \"\\r\" ? line.length - 1 : line.length,\n                    jsDocSpacesRemoved: jsDocSpacesRemoved\n                };\n            }\n\n            return null;\n        }\n\n        static cleanJSDocComment(content: string, spacesToRemove?: number) {\n            var docCommentLines: string[] = [];\n            content = content.replace(\"/**\", \"\"); // remove /**\n            if (content.length >= 2 && content.charAt(content.length - 1) == \"/\" && content.charAt(content.length - 2) == \"*\") {\n                content = content.substring(0, content.length - 2); // remove last */\n            }\n            var lines = content.split(\"\\n\");\n            var inParamTag = false;\n            for (var l = 0; l < lines.length; l++) {\n                var line = lines[l];\n                var cleanLinePos = Comment.cleanDocCommentLine(line, true, spacesToRemove);\n                if (!cleanLinePos) {\n                    // Whole line empty, read next line\n                    continue;\n                }\n\n                var docCommentText = \"\";\n                var prevPos = cleanLinePos.minChar;\n                for (var i = line.indexOf(\"@\", cleanLinePos.minChar); 0 <= i && i < cleanLinePos.limChar; i = line.indexOf(\"@\", i + 1)) {\n                    // We have encoutered @. \n                    // If we were omitting param comment, we dont have to do anything\n                    // other wise the content of the text till @ tag goes as doc comment\n                    var wasInParamtag = inParamTag;\n\n                    // Parse contents next to @\n                    if (line.indexOf(\"param\", i + 1) == i + 1 && Comment.isSpaceChar(line, i + 6)) {\n                        // It is param tag. \n\n                        // If we were not in param tag earlier, push the contents from prev pos of the tag this tag start as docComment\n                        if (!wasInParamtag) {\n                            docCommentText += line.substring(prevPos, i);\n                        }\n\n                        // New start of contents \n                        prevPos = i;\n                        inParamTag = true;\n                    } else if (wasInParamtag) {\n                        // Non param tag start\n                        prevPos = i;\n                        inParamTag = false;\n                    }\n                }\n\n                if (!inParamTag) {\n                    docCommentText += line.substring(prevPos, cleanLinePos.limChar);\n                }\n\n                // Add line to comment text if it is not only white space line\n                var newCleanPos = Comment.cleanDocCommentLine(docCommentText, false);\n                if (newCleanPos) {\n                    if (spacesToRemove == undefined) {\n                        spacesToRemove = cleanLinePos.jsDocSpacesRemoved;\n                    }\n                    docCommentLines.push(docCommentText);\n                }\n            }\n            \n            return docCommentLines.join(\"\\n\");\n        }\n\n        static getDocCommentText(comments: Comment[]) {\n            var docCommentText: string[] = [];\n            for (var c = 0 ; c < comments.length; c++) {\n                var commentText = comments[c].getDocCommentText();\n                if (commentText != \"\") {\n                    docCommentText.push(commentText);\n                }\n            }\n            return docCommentText.join(\"\\n\");\n        }\n\n        static getParameterDocCommentText(param: string, fncDocComments: Comment[]) {\n            if (fncDocComments.length == 0 || !fncDocComments[0].isBlockComment) {\n                // there were no fnc doc comments and the comment is not block comment then it cannot have \n                // @param comment that can be parsed\n                return \"\";\n            }\n            \n            for (var i = 0; i < fncDocComments.length; i++) {\n                var commentContents = fncDocComments[i].content;\n                for (var j = commentContents.indexOf(\"@param\", 0); 0 <= j; j = commentContents.indexOf(\"@param\", j)) {\n                    j += 6;\n                    if (!Comment.isSpaceChar(commentContents, j)) {\n                        // This is not param tag but a tag line @paramxxxxx\n                        continue;\n                    }\n\n                    // This is param tag. Check if it is what we are looking for\n                    j = Comment.consumeLeadingSpace(commentContents, j);\n                    if (j == -1) {\n                        break;\n                    }\n                    \n                    // Ignore the type expression\n                    if (commentContents.charCodeAt(j) == LexCodeLC) {\n                        j++;\n                        // Consume the type\n                        var charCode = 0;\n                        for (var curlies = 1; j < commentContents.length; j++) {\n                            charCode = commentContents.charCodeAt(j);\n                            // { character means we need to find another } to match the found one\n                            if (charCode == LexCodeLC) {\n                                curlies++;\n                                continue;\n                            }\n\n                            // } char\n                            if (charCode == LexCodeRC) {\n                                curlies--;\n                                if (curlies == 0) {\n                                    // We do not have any more } to match the type expression is ignored completely\n                                    break;\n                                } else {\n                                    // there are more { to be matched with }\n                                    continue;\n                                }\n                            }\n\n                            // Found start of another tag\n                            if (charCode == LexCodeAtSign) {\n                                break;\n                            }\n                        }\n\n                        // End of the comment\n                        if (j == commentContents.length) {\n                            break;\n                        }\n\n                        // End of the tag, go onto looking for next tag\n                        if (charCode == LexCodeAtSign) {\n                            continue;\n                        }\n\n                        j = Comment.consumeLeadingSpace(commentContents, j + 1);\n                        if (j == -1) {\n                            break;\n                        }\n                    }\n\n                    // Parameter name\n                    if (param != commentContents.substr(j, param.length) || !Comment.isSpaceChar(commentContents, j + param.length)) {\n                        // this is not the parameter we are looking for\n                        continue;\n                    }\n\n                    // Found the parameter we were looking for\n                    j = Comment.consumeLeadingSpace(commentContents, j + param.length);\n                    if (j == -1) {\n                        return \"\";\n                    }\n                    \n                    var endOfParam = commentContents.indexOf(\"@\", j);\n                    var paramHelpString = commentContents.substring(j, endOfParam < 0 ? commentContents.length : endOfParam);\n\n                    // Find alignement spaces to remove\n                    var paramSpacesToRemove: number = undefined;\n                    var paramLineIndex = commentContents.substring(0, j).lastIndexOf(\"\\n\") + 1;\n                    if (paramLineIndex != 0) {\n                        if (paramLineIndex < j && commentContents.charAt(paramLineIndex + 1) == \"\\r\") {\n                            paramLineIndex++;\n                        }\n                    }\n                    var startSpaceRemovalIndex = Comment.consumeLeadingSpace(commentContents, paramLineIndex);\n                    if (startSpaceRemovalIndex != j && commentContents.charAt(startSpaceRemovalIndex) == \"*\") {\n                        paramSpacesToRemove = j - startSpaceRemovalIndex - 1;\n                    }\n\n                    // Clean jsDocComment and return\n                    return Comment.cleanJSDocComment(paramHelpString, paramSpacesToRemove);\n                }\n            }\n\n            return \"\";\n        }\n\n        static getDocCommentTextOfSignatures(signatures: Signature[]) {\n            var comments: string[] = [];\n            for (var i = 0; i < signatures.length; i++) {\n                var signatureDocComment = TypeScript.Comment.getDocCommentText(signatures[i].declAST.getDocComments());\n                if (signatureDocComment != \"\") {\n                    comments.push(signatureDocComment);\n                }\n            }\n\n            return comments.join(\"\\n\");\n        }\n    }\n\n    export class DebuggerStatement extends Statement {\n        constructor () {\n            super(NodeType.Debugger);\n        }\n\n        public emit(emitter: Emitter, tokenId: TokenID, startLine: bool) {\n            emitter.emitParensAndCommentsInPlace(this, true);\n            emitter.recordSourceMappingStart(this);\n            emitter.writeLineToOutput(\"debugger;\");\n            emitter.recordSourceMappingEnd(this);\n            emitter.emitParensAndCommentsInPlace(this, false);\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript.AstWalkerWithDetailCallback {\n    export interface AstWalkerDetailCallback {\n        EmptyCallback? (pre, ast: AST): bool;\n        EmptyExprCallback? (pre, ast: AST): bool;\n        TrueCallback? (pre, ast: AST): bool;\n        FalseCallback? (pre, ast: AST): bool;\n        ThisCallback? (pre, ast: AST): bool;\n        SuperCallback? (pre, ast: AST): bool;\n        QStringCallback? (pre, ast: AST): bool;\n        RegexCallback? (pre, ast: AST): bool;\n        NullCallback? (pre, ast: AST): bool;\n        ArrayLitCallback? (pre, ast: AST): bool;\n        ObjectLitCallback? (pre, ast: AST): bool;\n        VoidCallback? (pre, ast: AST): bool;\n        CommaCallback? (pre, ast: AST): bool;\n        PosCallback? (pre, ast: AST): bool;\n        NegCallback? (pre, ast: AST): bool;\n        DeleteCallback? (pre, ast: AST): bool;\n        AwaitCallback? (pre, ast: AST): bool;\n        InCallback? (pre, ast: AST): bool;\n        DotCallback? (pre, ast: AST): bool;\n        FromCallback? (pre, ast: AST): bool;\n        IsCallback? (pre, ast: AST): bool;\n        InstOfCallback? (pre, ast: AST): bool;\n        TypeofCallback? (pre, ast: AST): bool;\n        NumberLitCallback? (pre, ast: AST): bool;\n        NameCallback? (pre, identifierAst: Identifier): bool;\n        TypeRefCallback? (pre, ast: AST): bool;\n        IndexCallback? (pre, ast: AST): bool;\n        CallCallback? (pre, ast: AST): bool;\n        NewCallback? (pre, ast: AST): bool;\n        AsgCallback? (pre, ast: AST): bool;\n        AsgAddCallback? (pre, ast: AST): bool;\n        AsgSubCallback? (pre, ast: AST): bool;\n        AsgDivCallback? (pre, ast: AST): bool;\n        AsgMulCallback? (pre, ast: AST): bool;\n        AsgModCallback? (pre, ast: AST): bool;\n        AsgAndCallback? (pre, ast: AST): bool;\n        AsgXorCallback? (pre, ast: AST): bool;\n        AsgOrCallback? (pre, ast: AST): bool;\n        AsgLshCallback? (pre, ast: AST): bool;\n        AsgRshCallback? (pre, ast: AST): bool;\n        AsgRs2Callback? (pre, ast: AST): bool;\n        QMarkCallback? (pre, ast: AST): bool;\n        LogOrCallback? (pre, ast: AST): bool;\n        LogAndCallback? (pre, ast: AST): bool;\n        OrCallback? (pre, ast: AST): bool;\n        XorCallback? (pre, ast: AST): bool;\n        AndCallback? (pre, ast: AST): bool;\n        EqCallback? (pre, ast: AST): bool;\n        NeCallback? (pre, ast: AST): bool;\n        EqvCallback? (pre, ast: AST): bool;\n        NEqvCallback? (pre, ast: AST): bool;\n        LtCallback? (pre, ast: AST): bool;\n        LeCallback? (pre, ast: AST): bool;\n        GtCallback? (pre, ast: AST): bool;\n        GeCallback? (pre, ast: AST): bool;\n        AddCallback? (pre, ast: AST): bool;\n        SubCallback? (pre, ast: AST): bool;\n        MulCallback? (pre, ast: AST): bool;\n        DivCallback? (pre, ast: AST): bool;\n        ModCallback? (pre, ast: AST): bool;\n        LshCallback? (pre, ast: AST): bool;\n        RshCallback? (pre, ast: AST): bool;\n        Rs2Callback? (pre, ast: AST): bool;\n        NotCallback? (pre, ast: AST): bool;\n        LogNotCallback? (pre, ast: AST): bool;\n        IncPreCallback? (pre, ast: AST): bool;\n        DecPreCallback? (pre, ast: AST): bool;\n        IncPostCallback? (pre, ast: AST): bool;\n        DecPostCallback? (pre, ast: AST): bool;\n        TypeAssertionCallback? (pre, ast: AST): bool;\n        FuncDeclCallback? (pre, funcDecl: FuncDecl): bool;\n        MemberCallback? (pre, ast: AST): bool;\n        VarDeclCallback? (pre, varDecl: VarDecl): bool;\n        ArgDeclCallback? (pre, ast: AST): bool;\n        ReturnCallback? (pre, ast: AST): bool;\n        BreakCallback? (pre, ast: AST): bool;\n        ContinueCallback? (pre, ast: AST): bool;\n        ThrowCallback? (pre, ast: AST): bool;\n        ForCallback? (pre, ast: AST): bool;\n        ForInCallback? (pre, ast: AST): bool;\n        IfCallback? (pre, ast: AST): bool;\n        WhileCallback? (pre, ast: AST): bool;\n        DoWhileCallback? (pre, ast: AST): bool;\n        BlockCallback? (pre, block: Block): bool;\n        CaseCallback? (pre, ast: AST): bool;\n        SwitchCallback? (pre, ast: AST): bool;\n        TryCallback? (pre, ast: AST): bool;\n        TryCatchCallback? (pre, ast: AST): bool;\n        TryFinallyCallback? (pre, ast: AST): bool;\n        FinallyCallback? (pre, ast: AST): bool;\n        CatchCallback? (pre, ast: AST): bool;\n        ListCallback? (pre, astList: ASTList): bool;\n        ScriptCallback? (pre, script: Script): bool;\n        ClassDeclarationCallback? (pre, ast: AST): bool;\n        InterfaceDeclarationCallback? (pre, interfaceDecl: InterfaceDeclaration): bool;\n        ModuleDeclarationCallback? (pre, moduleDecl: ModuleDeclaration): bool;\n        ImportDeclarationCallback? (pre, ast: AST): bool;\n        WithCallback? (pre, ast: AST): bool;\n        LabelCallback? (pre, labelAST: AST): bool;\n        LabeledStatementCallback? (pre, ast: AST): bool;\n        EBStartCallback? (pre, ast: AST): bool;\n        GotoEBCallback? (pre, ast: AST): bool;\n        EndCodeCallback? (pre, ast: AST): bool;\n        ErrorCallback? (pre, ast: AST): bool;\n        CommentCallback? (pre, ast: AST): bool;\n        DebuggerCallback? (pre, ast: AST): bool;\n        DefaultCallback? (pre, ast: AST): bool;\n    }\n\n    export function walk(script: Script, callback: AstWalkerDetailCallback): void {\n        var pre = (cur: AST, parent: AST) => {\n            walker.options.goChildren = AstWalkerCallback(true, cur, callback);\n            return cur;\n        }\n\n        var post = (cur: AST, parent: AST) => {\n            AstWalkerCallback(false, cur, callback);\n            return cur;\n        }\n\n        var walker = TypeScript.getAstWalkerFactory().getWalker(pre, post);\n        walker.walk(script, null);\n    }\n\n    function AstWalkerCallback(pre: bool, ast: AST, callback: AstWalkerDetailCallback): bool {\n        // See if the Callback needs to be handled using specific one or default one\n        var nodeType = ast.nodeType;\n        var callbackString = (<any>NodeType)._map[nodeType] + \"Callback\";\n        if (callback[callbackString]) {\n            return callback[callbackString](pre, ast);\n        }\n\n        if (callback.DefaultCallback) {\n            return callback.DefaultCallback(pre, ast);\n        }\n\n        return true;\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export interface IAstWalker {\n        walk(ast: AST, parent: AST): AST;\n        options: AstWalkOptions;\n        state: any; // user state object\n    }\n\n    export class AstWalkOptions {\n        public goChildren = true;\n        public goNextSibling = true;\n        public reverseSiblings = false; // visit siblings in reverse execution order\n\n        public stopWalk(stop:bool = true) {\n            this.goChildren = !stop;\n            this.goNextSibling = !stop;\n        }\n    }\n\n    export interface IAstWalkCallback {\n        (ast: AST, parent: AST, walker: IAstWalker): AST;\n    }\n\n    export interface IAstWalkChildren {\n        (preAst: AST, parent: AST, walker: IAstWalker): void;\n    }\n\n    class AstWalker implements IAstWalker {\n        constructor (\n            private childrenWalkers: IAstWalkChildren[],\n            private pre: IAstWalkCallback,\n            private post: IAstWalkCallback,\n            public options: AstWalkOptions,\n            public state: any) {\n        }\n\n        public walk(ast: AST, parent: AST): AST {\n            var preAst = this.pre(ast, parent, this);\n            if (preAst === undefined) {\n                preAst = ast;\n            }\n            if (this.options.goChildren) {\n                var svGoSib = this.options.goNextSibling;\n                this.options.goNextSibling = true;\n                // Call the \"walkChildren\" function corresponding to \"nodeType\".\n                this.childrenWalkers[ast.nodeType](ast, parent, this);\n                this.options.goNextSibling = svGoSib;\n            }\n            else {\n                // no go only applies to children of node issuing it\n                this.options.goChildren = true;\n            }\n            if (this.post) {\n                var postAst = this.post(preAst, parent, this);\n                if (postAst === undefined) {\n                    postAst = preAst;\n                }\n                return postAst;\n            }\n            else {\n                return preAst;\n            }\n        }\n    }\n\n    export class AstWalkerFactory {\n        private childrenWalkers: IAstWalkChildren[] = [];\n\n        constructor () {\n            this.initChildrenWalkers();\n        }\n\n        public walk(ast: AST, pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): AST {\n            return this.getWalker(pre, post, options, state).walk(ast, null)\n        }\n\n        public getWalker(pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): IAstWalker {\n            return this.getSlowWalker(pre, post, options, state);\n        }\n\n        private getSlowWalker(pre: IAstWalkCallback, post?: IAstWalkCallback, options?: AstWalkOptions, state?: any): IAstWalker {\n            if (!options) {\n                options = new AstWalkOptions();\n            }\n\n            return new AstWalker(this.childrenWalkers, pre, post, options, state);\n        }\n\n        private initChildrenWalkers(): void {\n            this.childrenWalkers[NodeType.None] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Empty] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.EmptyExpr] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.True] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.False] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.This] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Super] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.QString] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Regex] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Null] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.ArrayLit] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.ObjectLit] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.Void] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.Comma] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Pos] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.Neg] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.Delete] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.Await] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.In] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Dot] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.From] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Is] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.InstOf] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Typeof] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.NumberLit] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Name] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.TypeRef] = ChildrenWalkers.walkTypeReferenceChildren;\n            this.childrenWalkers[NodeType.Index] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Call] = ChildrenWalkers.walkCallExpressionChildren;\n            this.childrenWalkers[NodeType.New] = ChildrenWalkers.walkCallExpressionChildren;\n            this.childrenWalkers[NodeType.Asg] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgAdd] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgSub] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgDiv] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgMul] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgMod] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgAnd] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgXor] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgOr] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgLsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgRsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.AsgRs2] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.ConditionalExpression] = ChildrenWalkers.walkTrinaryExpressionChildren;\n            this.childrenWalkers[NodeType.LogOr] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.LogAnd] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Or] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Xor] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.And] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Eq] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Ne] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Eqv] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.NEqv] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Lt] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Le] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Gt] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Ge] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Add] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Sub] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Mul] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Div] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Mod] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Lsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Rsh] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Rs2] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.Not] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.LogNot] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.IncPre] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.DecPre] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.IncPost] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.DecPost] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.TypeAssertion] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.FuncDecl] = ChildrenWalkers.walkFuncDeclChildren;\n            this.childrenWalkers[NodeType.Member] = ChildrenWalkers.walkBinaryExpressionChildren;\n            this.childrenWalkers[NodeType.VarDecl] = ChildrenWalkers.walkBoundDeclChildren;\n            this.childrenWalkers[NodeType.ArgDecl] = ChildrenWalkers.walkBoundDeclChildren;\n            this.childrenWalkers[NodeType.Return] = ChildrenWalkers.walkReturnStatementChildren;\n            this.childrenWalkers[NodeType.Break] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Continue] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Throw] = ChildrenWalkers.walkUnaryExpressionChildren;\n            this.childrenWalkers[NodeType.For] = ChildrenWalkers.walkForStatementChildren;\n            this.childrenWalkers[NodeType.ForIn] = ChildrenWalkers.walkForInStatementChildren;\n            this.childrenWalkers[NodeType.If] = ChildrenWalkers.walkIfStatementChildren;\n            this.childrenWalkers[NodeType.While] = ChildrenWalkers.walkWhileStatementChildren;\n            this.childrenWalkers[NodeType.DoWhile] = ChildrenWalkers.walkDoWhileStatementChildren;\n            this.childrenWalkers[NodeType.Block] = ChildrenWalkers.walkBlockChildren;\n            this.childrenWalkers[NodeType.Case] = ChildrenWalkers.walkCaseStatementChildren;\n            this.childrenWalkers[NodeType.Switch] = ChildrenWalkers.walkSwitchStatementChildren;\n            this.childrenWalkers[NodeType.Try] = ChildrenWalkers.walkTryChildren;\n            this.childrenWalkers[NodeType.TryCatch] = ChildrenWalkers.walkTryCatchChildren;\n            this.childrenWalkers[NodeType.TryFinally] = ChildrenWalkers.walkTryFinallyChildren;\n            this.childrenWalkers[NodeType.Finally] = ChildrenWalkers.walkFinallyChildren;\n            this.childrenWalkers[NodeType.Catch] = ChildrenWalkers.walkCatchChildren;\n            this.childrenWalkers[NodeType.List] = ChildrenWalkers.walkListChildren;\n            this.childrenWalkers[NodeType.Script] = ChildrenWalkers.walkScriptChildren;\n            this.childrenWalkers[NodeType.ClassDeclaration] = ChildrenWalkers.walkClassDeclChildren;\n            this.childrenWalkers[NodeType.InterfaceDeclaration] = ChildrenWalkers.walkTypeDeclChildren;\n            this.childrenWalkers[NodeType.ModuleDeclaration] = ChildrenWalkers.walkModuleDeclChildren;\n            this.childrenWalkers[NodeType.ImportDeclaration] = ChildrenWalkers.walkImportDeclChildren;\n            this.childrenWalkers[NodeType.With] = ChildrenWalkers.walkWithStatementChildren;\n            this.childrenWalkers[NodeType.Label] = ChildrenWalkers.walkLabelChildren;\n            this.childrenWalkers[NodeType.LabeledStatement] = ChildrenWalkers.walkLabeledStatementChildren;\n            this.childrenWalkers[NodeType.EBStart] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.GotoEB] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.EndCode] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Error] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Comment] = ChildrenWalkers.walkNone;\n            this.childrenWalkers[NodeType.Debugger] = ChildrenWalkers.walkNone;\n\n            // Verify the code is up to date with the enum\n            for (var e in (<any>NodeType)._map) {\n                if ((<any>this.childrenWalkers)[e] === undefined) {\n                    throw new Error(\"initWalkers function is not up to date with enum content!\");\n                }\n            }\n        }\n    }\n\n    var globalAstWalkerFactory: AstWalkerFactory;\n\n    export function getAstWalkerFactory(): AstWalkerFactory {\n        if (!globalAstWalkerFactory) {\n            globalAstWalkerFactory = new AstWalkerFactory();\n        }\n        return globalAstWalkerFactory;\n    }\n\n    module ChildrenWalkers {\n        export function walkNone(preAst: ASTList, parent: AST, walker: IAstWalker): void {\n            // Nothing to do\n        }\n\n        export function walkListChildren(preAst: ASTList, parent: AST, walker: IAstWalker): void {\n            var len = preAst.members.length;\n            if (walker.options.reverseSiblings) {\n                for (var i = len - 1; i >= 0; i--) {\n                    if (walker.options.goNextSibling) {\n                        preAst.members[i] = walker.walk(preAst.members[i], preAst);\n                    }\n                }\n            }\n            else {\n                for (var i = 0; i < len; i++) {\n                    if (walker.options.goNextSibling) {\n                        preAst.members[i] = walker.walk(preAst.members[i], preAst);\n                    }\n                }\n            }\n        }\n\n        export function walkUnaryExpressionChildren(preAst: UnaryExpression, parent: AST, walker: IAstWalker): void {\n            if (preAst.castTerm) {\n                preAst.castTerm = walker.walk(preAst.castTerm, preAst);\n            }\n            if (preAst.operand) {\n                preAst.operand = walker.walk(preAst.operand, preAst);\n            }\n        }\n\n        export function walkBinaryExpressionChildren(preAst: BinaryExpression, parent: AST, walker: IAstWalker): void {\n            if (walker.options.reverseSiblings) {\n                if (preAst.operand2) {\n                    preAst.operand2 = walker.walk(preAst.operand2, preAst);\n                }\n                if ((preAst.operand1) && (walker.options.goNextSibling)) {\n                    preAst.operand1 = walker.walk(preAst.operand1, preAst);\n                }\n            } else {\n                if (preAst.operand1) {\n                    preAst.operand1 = walker.walk(preAst.operand1, preAst);\n                }\n                if ((preAst.operand2) && (walker.options.goNextSibling)) {\n                    preAst.operand2 = walker.walk(preAst.operand2, preAst);\n                }\n            }\n        }\n\n        export function walkTypeReferenceChildren(preAst: TypeReference, parent: AST, walker: IAstWalker): void {\n            if (preAst.term) {\n                preAst.term = walker.walk(preAst.term, preAst);\n            }\n        }\n\n        export function walkCallExpressionChildren(preAst: CallExpression, parent: AST, walker: IAstWalker): void {\n            if (!walker.options.reverseSiblings) {\n                preAst.target = walker.walk(preAst.target, preAst);\n            }\n            if (preAst.arguments && (walker.options.goNextSibling)) {\n                preAst.arguments = <ASTList> walker.walk(preAst.arguments, preAst);\n            }\n            if ((walker.options.reverseSiblings) && (walker.options.goNextSibling)) {\n                preAst.target = walker.walk(preAst.target, preAst);\n            }\n        }\n\n        export function walkTrinaryExpressionChildren(preAst: ConditionalExpression, parent: AST, walker: IAstWalker): void {\n            if (preAst.operand1) {\n                preAst.operand1 = walker.walk(preAst.operand1, preAst);\n            }\n            if (preAst.operand2 && (walker.options.goNextSibling)) {\n                preAst.operand2 = walker.walk(preAst.operand2, preAst);\n            }\n            if (preAst.operand3 && (walker.options.goNextSibling)) {\n                preAst.operand3 = walker.walk(preAst.operand3, preAst);\n            }\n        }\n\n        export function walkFuncDeclChildren(preAst: FuncDecl, parent: AST, walker: IAstWalker): void {\n            if (preAst.name) {\n                preAst.name = <Identifier>walker.walk(preAst.name, preAst);\n            }\n            if (preAst.arguments && (preAst.arguments.members.length > 0) && (walker.options.goNextSibling)) {\n                preAst.arguments = <ASTList>walker.walk(preAst.arguments, preAst);\n            }\n            if (preAst.returnTypeAnnotation && (walker.options.goNextSibling)) {\n                preAst.returnTypeAnnotation = walker.walk(preAst.returnTypeAnnotation, preAst);\n            }\n            if (preAst.bod && (preAst.bod.members.length > 0) && (walker.options.goNextSibling)) {\n                preAst.bod = <ASTList>walker.walk(preAst.bod, preAst);\n            }\n        }\n\n        export function walkBoundDeclChildren(preAst: BoundDecl, parent: AST, walker: IAstWalker): void {\n            if (preAst.id) {\n                preAst.id = <Identifier>walker.walk(preAst.id, preAst);\n            }\n            if (preAst.init) {\n                preAst.init = walker.walk(preAst.init, preAst);\n            }\n            if ((preAst.typeExpr) && (walker.options.goNextSibling)) {\n                preAst.typeExpr = walker.walk(preAst.typeExpr, preAst);\n            }\n        }\n\n        export function walkReturnStatementChildren(preAst: ReturnStatement, parent: AST, walker: IAstWalker): void {\n            if (preAst.returnExpression) {\n                preAst.returnExpression = walker.walk(preAst.returnExpression, preAst);\n            }\n        }\n\n        export function walkForStatementChildren(preAst: ForStatement, parent: AST, walker: IAstWalker): void {\n            if (preAst.init) {\n                preAst.init = walker.walk(preAst.init, preAst);\n            }\n\n            if (preAst.cond && walker.options.goNextSibling) {\n                preAst.cond = walker.walk(preAst.cond, preAst);\n            }\n\n            if (preAst.incr && walker.options.goNextSibling) {\n                preAst.incr = walker.walk(preAst.incr, preAst);\n            }\n\n            if (preAst.body && walker.options.goNextSibling) {\n                preAst.body = walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkForInStatementChildren(preAst: ForInStatement, parent: AST, walker: IAstWalker): void {\n            preAst.lval = walker.walk(preAst.lval, preAst);\n            if (walker.options.goNextSibling) {\n                preAst.obj = walker.walk(preAst.obj, preAst);\n            }\n            if (preAst.body && (walker.options.goNextSibling)) {\n                preAst.body = walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkIfStatementChildren(preAst: IfStatement, parent: AST, walker: IAstWalker): void {\n            preAst.cond = walker.walk(preAst.cond, preAst);\n            if (preAst.thenBod && (walker.options.goNextSibling)) {\n                preAst.thenBod = walker.walk(preAst.thenBod, preAst);\n            }\n            if (preAst.elseBod && (walker.options.goNextSibling)) {\n                preAst.elseBod = walker.walk(preAst.elseBod, preAst);\n            }\n        }\n\n        export function walkWhileStatementChildren(preAst: WhileStatement, parent: AST, walker: IAstWalker): void {\n            preAst.cond = walker.walk(preAst.cond, preAst);\n            if (preAst.body && (walker.options.goNextSibling)) {\n                preAst.body = walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkDoWhileStatementChildren(preAst: DoWhileStatement, parent: AST, walker: IAstWalker): void {\n            preAst.cond = walker.walk(preAst.cond, preAst);\n            if (preAst.body && (walker.options.goNextSibling)) {\n                preAst.body = walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkBlockChildren(preAst: Block, parent: AST, walker: IAstWalker): void {\n            if (preAst.statements) {\n                preAst.statements = <ASTList>walker.walk(preAst.statements, preAst);\n            }\n        }\n\n        export function walkCaseStatementChildren(preAst: CaseStatement, parent: AST, walker: IAstWalker): void {\n            if (preAst.expr) {\n                preAst.expr = walker.walk(preAst.expr, preAst);\n            }\n\n            if (preAst.body && walker.options.goNextSibling) {\n                preAst.body = <ASTList>walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkSwitchStatementChildren(preAst: SwitchStatement, parent: AST, walker: IAstWalker): void {\n            if (preAst.val) {\n                preAst.val = walker.walk(preAst.val, preAst);\n            }\n\n            if ((preAst.caseList) && walker.options.goNextSibling) {\n                preAst.caseList = <ASTList>walker.walk(preAst.caseList, preAst);\n            }\n        }\n\n        export function walkTryChildren(preAst: Try, parent: AST, walker: IAstWalker): void {\n            if (preAst.body) {\n                preAst.body = walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkTryCatchChildren(preAst: TryCatch, parent: AST, walker: IAstWalker): void {\n            if (preAst.tryNode) {\n                preAst.tryNode = <Try>walker.walk(preAst.tryNode, preAst);\n            }\n\n            if ((preAst.catchNode) && walker.options.goNextSibling) {\n                preAst.catchNode = <Catch>walker.walk(preAst.catchNode, preAst);\n            }\n        }\n\n        export function walkTryFinallyChildren(preAst: TryFinally, parent: AST, walker: IAstWalker): void {\n            if (preAst.tryNode) {\n                preAst.tryNode = walker.walk(preAst.tryNode, preAst);\n            }\n\n            if (preAst.finallyNode && walker.options.goNextSibling) {\n                preAst.finallyNode = <Finally>walker.walk(preAst.finallyNode, preAst);\n            }\n        }\n\n        export function walkFinallyChildren(preAst: Finally, parent: AST, walker: IAstWalker): void {\n            if (preAst.body) {\n                preAst.body = walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkCatchChildren(preAst: Catch, parent: AST, walker: IAstWalker): void {\n            if (preAst.param) {\n                preAst.param = <VarDecl>walker.walk(preAst.param, preAst);\n            }\n\n            if ((preAst.body) && walker.options.goNextSibling) {\n                preAst.body = walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkRecordChildren(preAst: NamedDeclaration, parent: AST, walker: IAstWalker): void {\n            preAst.name = <Identifier>walker.walk(preAst.name, preAst);\n            if (walker.options.goNextSibling && preAst.members) {\n                preAst.members = <ASTList>walker.walk(preAst.members, preAst);\n            }\n\n        }\n\n        export function walkNamedTypeChildren(preAst: TypeDeclaration, parent: AST, walker: IAstWalker): void {\n            walkRecordChildren(preAst, parent, walker);\n        }\n\n        export function walkClassDeclChildren(preAst: ClassDeclaration, parent: AST, walker: IAstWalker): void {\n            walkNamedTypeChildren(preAst, parent, walker);\n\n            if (walker.options.goNextSibling && preAst.extendsList) {\n                preAst.extendsList = <ASTList>walker.walk(preAst.extendsList, preAst);\n            }\n\n            if (walker.options.goNextSibling && preAst.implementsList) {\n                preAst.implementsList = <ASTList>walker.walk(preAst.implementsList, preAst);\n            }\n        }\n\n        export function walkScriptChildren(preAst: Script, parent: AST, walker: IAstWalker): void {\n            if (preAst.bod) {\n                preAst.bod = <ASTList>walker.walk(preAst.bod, preAst);\n            }\n        }\n\n        export function walkTypeDeclChildren(preAst: InterfaceDeclaration, parent: AST, walker: IAstWalker): void {\n            walkNamedTypeChildren(preAst, parent, walker);\n\n            // walked arguments as part of members\n            if (walker.options.goNextSibling && preAst.extendsList) {\n                preAst.extendsList = <ASTList>walker.walk(preAst.extendsList, preAst);\n            }\n\n            if (walker.options.goNextSibling && preAst.implementsList) {\n                preAst.implementsList = <ASTList>walker.walk(preAst.implementsList, preAst);\n            }\n        }\n\n        export function walkModuleDeclChildren(preAst: ModuleDeclaration, parent: AST, walker: IAstWalker): void {\n            walkRecordChildren(preAst, parent, walker);\n        }\n\n        export function walkImportDeclChildren(preAst: ImportDeclaration, parent: AST, walker: IAstWalker): void {\n            if (preAst.id) {\n                preAst.id = <Identifier>walker.walk(preAst.id, preAst);\n            }\n            if (preAst.alias) {\n                preAst.alias = walker.walk(preAst.alias, preAst);\n            }\n        }\n\n        export function walkWithStatementChildren(preAst: WithStatement, parent: AST, walker: IAstWalker): void {\n            if (preAst.expr) {\n                preAst.expr = walker.walk(preAst.expr, preAst);\n            }\n\n            if (preAst.body && walker.options.goNextSibling) {\n                preAst.body = walker.walk(preAst.body, preAst);\n            }\n        }\n\n        export function walkLabelChildren(preAst: Label, parent: AST, walker: IAstWalker): void {\n            //TODO: Walk \"id\"?\n        }\n\n        export function walkLabeledStatementChildren(preAst: LabeledStatement, parent: AST, walker: IAstWalker): void {\n            preAst.labels = <ASTList>walker.walk(preAst.labels, preAst);\n            if (walker.options.goNextSibling) {\n                preAst.stmt = walker.walk(preAst.stmt, preAst);\n            }\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\nmodule TypeScript {\n    class Base64Format {\n        static encodedValues = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n        static encode(inValue: number) {\n            if (inValue < 64) {\n                return encodedValues.charAt(inValue);\n            }\n            throw TypeError(inValue + \": not a 64 based value\");\n        }\n\n        static decodeChar(inChar: string) {\n            if (inChar.length === 1) {\n                return encodedValues.indexOf(inChar);\n            } else {\n                throw TypeError('\"' + inChar + '\" must have length 1');\n            }\n        }\n    }\n\n    export class Base64VLQFormat {\n        static encode(inValue: number) {\n            // Add a new least significant bit that has the sign of the value.\n            // if negative number the least significant bit that gets added to the number has value 1\n            // else least significant bit value that gets added is 0\n            // eg. -1 changes to binary : 01 [1] => 3\n            //     +1 changes to binary : 01 [0] => 2\n            if (inValue < 0) {\n                inValue = ((-inValue) << 1) + 1;\n            }\n            else {\n                inValue = inValue << 1;\n            }\n\n            // Encode 5 bits at a time starting from least significant bits\n            var encodedStr = \"\";\n            do {\n                var currentDigit = inValue & 31; // 11111\n                inValue = inValue >> 5;\n                if (inValue > 0) {\n                    // There are still more digits to decode, set the msb (6th bit)\n                    currentDigit = currentDigit | 32; \n                }\n                encodedStr = encodedStr + Base64Format.encode(currentDigit);\n            } while (inValue > 0);\n\n            return encodedStr;\n        }\n\n        static decode(inString: string) {\n            var result = 0;\n            var negative = false;\n\n            var shift = 0;\n            for (var i = 0; i < inString.length; i++) {\n                var byte = Base64Format.decodeChar(inString[i]);\n                if (i === 0) {\n                    // Sign bit appears in the LSBit of the first value\n                    if ((byte & 1) === 1) {\n                        negative = true;\n                    }\n                    result = (byte >> 1) & 15; // 1111x\n                } else {\n                    result = result | ((byte & 31) << shift); // 11111\n                }\n\n                shift += (i == 0) ? 4 : 5;\n\n                if ((byte & 32) === 32) {\n                    // Continue\n                } else {\n                    return { value: negative ? -(result) : result, rest: inString.substr(i + 1) };\n                }\n            }\n\n            throw new Error('Base64 value \"' + inString + '\" finished with a continuation bit');\n        }\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export class Binder {\n        constructor(public checker: TypeChecker) { }\n        \n        public resolveBaseTypeLinks(typeLinks: TypeLink[], scope: SymbolScope) {\n            var extendsList: Type[] = null;\n            if (typeLinks) {\n                extendsList = new Type[];\n                for (var i = 0, len = typeLinks.length; i < len; i++) {\n                    extendsList[i] = this.checker.resolveBaseTypeLink(typeLinks[i], scope);\n                }\n            }\n            return extendsList;\n        }\n\n        public resolveBases(scope: SymbolScope, type: Type) {\n            type.extendsList = this.resolveBaseTypeLinks(type.extendsTypeLinks, scope);\n\n            var i = 0, len = type.extendsList.length;\n            var derivedIsClass = type.isClassInstance();\n            for (; i < len; i++) {\n                var baseIsClass = type.extendsList[i].isClassInstance();\n                if (type.extendsList[i] != this.checker.anyType) {\n                    var baseRef = type.extendsTypeLinks[i].ast;\n                    if (derivedIsClass) {\n                        if (!baseIsClass) {\n                            this.checker.errorReporter.simpleError(baseRef,\n                                                                     \"A class may only extend other classes, \" + type.extendsList[i].symbol.fullName() + \" is not a class.\");\n                        }\n                    }\n                    else {\n                        if (baseIsClass) {\n                            this.checker.errorReporter.simpleError(baseRef,\n                                                                     \"An interface may only extend other interfaces, \" + type.extendsList[i].symbol.fullName() + \" is a class.\");\n                        }\n                    }\n                }\n            }\n\n            type.implementsList = this.resolveBaseTypeLinks(type.implementsTypeLinks, scope);\n\n            if (type.implementsList) {\n                for (i = 0, len = type.implementsList.length; i < len; i++) {\n                    var iface = type.implementsList[i];\n                    var baseRef = type.implementsTypeLinks[i].ast;\n                    if (iface.isClassInstance()) {\n                        if (derivedIsClass) {\n                            this.checker.errorReporter.simpleError(baseRef,\n                                                                     \"A class may only implement an interface; \" + iface.symbol.fullName() + \" is a class.\");\n                        }\n                    }\n                }\n            }\n        }\n\n        public resolveSignatureGroup(signatureGroup: SignatureGroup, scope: SymbolScope, instanceType: Type) {\n            var supplyVar = !(signatureGroup.hasImplementation);\n            for (var i = 0, len = signatureGroup.signatures.length; i < len; i++) {\n                var signature = signatureGroup.signatures[i];\n                if (instanceType) {\n                    signature.returnType.type = instanceType;\n                }\n                else {\n                    this.checker.resolveTypeLink(scope, signature.returnType, supplyVar);\n                }\n                var paramLen = signature.parameters.length;\n                for (var j = 0; j < paramLen; j++) {\n                    this.bindSymbol(scope, signature.parameters[j]);\n                }\n                if (signature.hasVariableArgList) {\n                    // check that last parameter has an array type\n                    var lastParam = <ParameterSymbol>signature.parameters[paramLen - 1];\n                    lastParam.argsOffset = paramLen - 1;\n                    if (!lastParam.getType().isArray()) {\n                        this.checker.errorReporter.simpleErrorFromSym(lastParam,\n                                                                 \"... parameter must have array type\");\n                        lastParam.parameter.typeLink.type = this.checker.makeArrayType(lastParam.parameter.typeLink.type);\n                    }\n                }\n            }\n        }\n\n        public bindType(scope: SymbolScope, type: Type, instanceType: Type): void {\n            if (instanceType) {\n                this.bindType(scope, instanceType, null);\n            }\n            if (type.hasMembers()) {\n                var members = type.members;\n                var ambientMembers = type.ambientMembers;\n                var typeMembers = type.getAllEnclosedTypes(); // REVIEW: Should only be getting exported types?\n                var ambientTypeMembers = type.getAllAmbientEnclosedTypes(); // REVIEW: Should only be getting exported types?\n                var memberScope = new SymbolTableScope(members, ambientMembers, typeMembers, ambientTypeMembers, type.symbol);\n                var agg = new SymbolAggregateScope(type.symbol);\n                var prevCurrentModDecl = this.checker.currentModDecl;\n                var prevBindStatus = this.checker.inBind;\n                agg.addParentScope(memberScope);\n                agg.addParentScope(scope);\n                if (type.isModuleType()) {\n                    this.checker.currentModDecl = <ModuleDeclaration>type.symbol.declAST;\n                    this.checker.inBind = true;\n                }\n                if (members) {\n                    this.bind(agg, type.members.allMembers); // REVIEW: Should only be getting exported types?\n                }\n                if (typeMembers) {\n                    this.bind(agg, typeMembers.allMembers);\n                }\n                if (ambientMembers) {\n                    this.bind(agg, ambientMembers.allMembers);\n                }\n                if (ambientTypeMembers) {\n                    this.bind(agg, ambientTypeMembers.allMembers);\n                }\n                this.checker.currentModDecl = prevCurrentModDecl;\n                this.checker.inBind = prevBindStatus;\n            }\n            if (type.extendsTypeLinks) {\n                this.resolveBases(scope, type);\n            }\n            if (type.construct) {\n                this.resolveSignatureGroup(type.construct, scope, instanceType);\n            }\n            if (type.call) {\n                this.resolveSignatureGroup(type.call, scope, null);\n            }\n            if (type.index) {\n                this.resolveSignatureGroup(type.index, scope, null);\n            }\n            if (type.elementType) {\n                this.bindType(scope, type.elementType, null);\n            }\n        }\n\n        public bindSymbol(scope: SymbolScope, symbol: Symbol) {\n            if (!symbol.bound) {\n                var prevLocationInfo = this.checker.locationInfo;\n                if ((this.checker.units) && (symbol.unitIndex >= 0) && (symbol.unitIndex < this.checker.units.length)) {\n                    this.checker.locationInfo = this.checker.units[symbol.unitIndex];\n                }\n                switch (symbol.kind()) {\n                    case SymbolKind.Type:\n\n                        if (symbol.flags & SymbolFlags.Bound) {\n                            break;\n                        }\n\n                        var typeSymbol = <TypeSymbol>symbol;\n                        typeSymbol.flags |= SymbolFlags.Bound;\n\n                        // Since type collection happens out of order, a dynamic module referenced by an import statement\n                        // may not yet be in scope when the import symbol is created.  In that case, we need to search\n                        // out the module symbol now\n                        // Note that we'll also want to do this in resolveTypeMembers, in case the symbol is set outside the\n                        // context of a given module  (E.g., an outer import statement)\n                        if (typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == NodeType.Name) {\n                            var modPath = (<Identifier>typeSymbol.aliasLink.alias).text;\n                            var modSym = this.checker.findSymbolForDynamicModule(modPath, this.checker.locationInfo.filename, (id) => scope.find(id, false, true));\n                            if (modSym) {\n                                typeSymbol.type = modSym.getType();\n                            }\n                        }\n\n                        if (typeSymbol.type && typeSymbol.type != this.checker.gloModType) {\n                            this.bindType(scope, typeSymbol.type, typeSymbol.instanceType);\n\n                            // bind expansions on the parent type symbol\n                            if (typeSymbol.type.isModuleType()) {\n                                for (var i = 0; i < typeSymbol.expansions.length; i++) {\n                                    this.bindType(scope, typeSymbol.expansions[i], typeSymbol.instanceType);\n                                }\n                            }\n                        }\n                        break;\n                    case SymbolKind.Field:\n                        this.checker.resolveTypeLink(scope, (<FieldSymbol>symbol).field.typeLink,\n                                                false);\n                        break;\n                    case SymbolKind.Parameter:\n                        this.checker.resolveTypeLink(scope,\n                                                (<ParameterSymbol>symbol).parameter.typeLink,\n                                                true);\n                        break;\n                }\n                this.checker.locationInfo = prevLocationInfo;\n            }\n            symbol.bound = true;\n        }\n\n        public bind(scope: SymbolScope, table: IHashTable) {\n            table.map(\n                (key, sym, binder) => {\n                    binder.bindSymbol(scope, sym);\n                },\n                this);\n        }\n    }\n\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export class DeclFileWriter {\n        public onNewLine = true;\n        constructor(private declFile: ITextWriter) {\n        }\n\n        public Write(s: string) {\n            this.declFile.Write(s);\n            this.onNewLine = false;\n        }\n\n        public WriteLine(s: string) {\n            this.declFile.WriteLine(s);\n            this.onNewLine = true;\n        }\n\n        public Close() {\n            this.declFile.Close();\n        }\n    }\n\n    export class DeclarationEmitter implements AstWalkerWithDetailCallback.AstWalkerDetailCallback {\n        private declFile: DeclFileWriter = null;\n        private indenter = new Indenter();\n        private declarationContainerStack: AST[] = [];\n        private isDottedModuleName: bool[] = [];\n        private dottedModuleEmit: string;\n        private ignoreCallbackAst: AST = null;\n        private singleDeclFile: DeclFileWriter = null;\n        private varListCount: number = 0;\n\n        private getAstDeclarationContainer() {\n            return this.declarationContainerStack[this.declarationContainerStack.length - 1];\n        }\n\n        private emitDottedModuleName() {\n            return (this.isDottedModuleName.length == 0) ? false : this.isDottedModuleName[this.isDottedModuleName.length - 1];\n        }\n\n        constructor (public checker: TypeChecker, public emitOptions: EmitOptions, public errorReporter: ErrorReporter) {\n        }\n\n        public setDeclarationFile(file: ITextWriter) {\n            this.declFile = new DeclFileWriter(file);\n        }\n\n        public Close() {\n            try {\n                // Closing files could result in exceptions, report them if they occur\n                this.declFile.Close();\n            } catch (ex) {\n                this.errorReporter.emitterError(null, ex.message);\n            }\n        }\n\n        public emitDeclarations(script: TypeScript.Script): void {\n            AstWalkerWithDetailCallback.walk(script, this);\n        }\n\n        private getIndentString(declIndent? = false) {\n            if (this.emitOptions.minWhitespace) {\n                return \"\";\n            }\n            else {\n                return this.indenter.getIndent();\n            }\n        }\n\n        private emitIndent() {\n            this.declFile.Write(this.getIndentString());\n        }\n\n        private canEmitSignature(declFlags: DeclFlags, canEmitGlobalAmbientDecl?: bool = true, useDeclarationContainerTop?: bool = true) {\n            var container: AST;\n            if (useDeclarationContainerTop) {\n                container = this.getAstDeclarationContainer();\n            } else {\n                container = this.declarationContainerStack[this.declarationContainerStack.length - 2];\n            }\n\n            if (container.nodeType == NodeType.ModuleDeclaration && !hasFlag(declFlags, DeclFlags.Exported)) {\n                return false;\n            }\n\n            if (!canEmitGlobalAmbientDecl && container.nodeType == NodeType.Script && hasFlag(declFlags, DeclFlags.Ambient)) {\n                return false;\n            }\n\n            return true;\n        }\n\n        private canEmitPrePostAstSignature(declFlags: DeclFlags, astWithPrePostCallback: AST, preCallback: bool) {\n            if (this.ignoreCallbackAst) {\n                CompilerDiagnostics.assert(this.ignoreCallbackAst != astWithPrePostCallback, \"Ignore Callback AST mismatch\");\n                this.ignoreCallbackAst = null;\n                return false;\n            } else if (preCallback &&\n                !this.canEmitSignature(declFlags, true, preCallback)) {\n                this.ignoreCallbackAst = astWithPrePostCallback;\n                return false;\n            }\n\n            return true;\n        }\n\n        private getDeclFlagsString(declFlags: DeclFlags, typeString: string) {\n            var result = this.getIndentString();\n\n            // Accessor strings\n            var accessorString = \"\";\n            if (hasFlag(declFlags, DeclFlags.GetAccessor)) {\n                accessorString = \"get \";\n            }\n            else if (hasFlag(declFlags, DeclFlags.SetAccessor)) {\n                accessorString = \"set \";\n            }\n\n            // Emit export only for global export statements. The container for this would be dynamic module which is whole file\n            var container = this.getAstDeclarationContainer();\n            if (container.nodeType == NodeType.ModuleDeclaration &&\n                hasFlag((<ModuleDeclaration>container).modFlags, ModuleFlags.IsWholeFile) &&\n                hasFlag(declFlags, DeclFlags.Exported)) {\n                result += \"export \";\n            }\n\n            // Static/public/private/global declare\n            if (hasFlag(declFlags, DeclFlags.LocalStatic) || hasFlag(declFlags, DeclFlags.Static)) {\n                result += \"static \" + accessorString;\n            }\n            else {\n                if (hasFlag(declFlags, DeclFlags.Private)) {\n                    result += \"private \" + accessorString;\n                }\n                else if (hasFlag(declFlags, DeclFlags.Public)) {\n                    result += \"public \" + accessorString;\n                }\n                else {\n                    if (accessorString == \"\") {\n                        result += typeString + \" \";\n                    } else {\n                        result += accessorString;\n                    }\n                }\n            }\n\n            return result;\n        }\n\n        private emitDeclFlags(declFlags: DeclFlags, typeString: string) {\n            this.declFile.Write(this.getDeclFlagsString(declFlags, typeString));\n        }\n\n        private canEmitTypeAnnotationSignature(declFlag: DeclFlags = DeclFlags.None) {\n            // Private declaration, shouldnt emit type any time.\n            return !hasFlag(declFlag, DeclFlags.Private);\n        }\n\n        private pushDeclarationContainer(ast: AST) {\n            this.declarationContainerStack.push(ast);\n        }\n\n        private popDeclarationContainer(ast: AST) {\n            CompilerDiagnostics.assert(ast != this.getAstDeclarationContainer(), 'Declaration container mismatch');\n            this.declarationContainerStack.pop();\n        }\n\n        private emitTypeNamesMember(memberName: MemberName, emitIndent? : bool = false) {\n            if (memberName.prefix == \"{ \") {\n                if (emitIndent) {\n                    this.emitIndent();\n                }\n                this.declFile.WriteLine(\"{\");\n                this.indenter.increaseIndent();\n                emitIndent = true;\n            } else if (memberName.prefix != \"\") {\n                if (emitIndent) {\n                    this.emitIndent();\n                }\n                this.declFile.Write(memberName.prefix);\n                emitIndent = false;\n            }\n\n            if (memberName.isString()) {\n                if (emitIndent) {\n                    this.emitIndent();\n                }\n                this.declFile.Write((<MemberNameString>memberName).text);\n            } else {\n                var ar = <MemberNameArray>memberName;\n                for (var index = 0; index < ar.entries.length; index++) {\n                    this.emitTypeNamesMember(ar.entries[index], emitIndent);\n                    if (ar.delim == \"; \") {\n                        this.declFile.WriteLine(\";\");\n                    }\n                }\n            }\n\n            if (memberName.suffix == \"}\") {\n                this.indenter.decreaseIndent();\n                this.emitIndent();\n                this.declFile.Write(memberName.suffix);\n            } else {\n                this.declFile.Write(memberName.suffix);\n            }\n        }\n\n        private emitTypeSignature(type: Type) {\n            var containingScope: SymbolScope = null;\n            var declarationContainerAst = this.getAstDeclarationContainer();\n            switch (declarationContainerAst.nodeType) {\n                case NodeType.ModuleDeclaration:\n                case NodeType.InterfaceDeclaration:\n                case NodeType.FuncDecl:\n                    if (declarationContainerAst.type) {\n                        containingScope = declarationContainerAst.type.containedScope;\n                    }\n                    break;\n\n                case NodeType.Script:\n                    var script = <Script>declarationContainerAst;\n                    if (script.bod) {\n                        containingScope = script.bod.enclosingScope;\n                    }\n                    break;\n\n                case NodeType.ClassDeclaration:\n                    if (declarationContainerAst.type) {\n                        containingScope = declarationContainerAst.type.instanceType.containedScope;\n                    }\n                    break;\n\n                default:\n                    CompilerDiagnostics.debugPrint(\"Unknown containing scope\");\n            }\n\n            var typeNameMembers = type.getScopedTypeNameEx(containingScope);\n            this.emitTypeNamesMember(typeNameMembers);\n        }\n\n        private emitComment(comment: Comment) {\n            var text = comment.getText();\n            if (this.declFile.onNewLine) {\n                this.emitIndent();\n            } else if (!comment.isBlockComment) {\n                this.declFile.WriteLine(\"\");\n                this.emitIndent();\n            }\n            \n            this.declFile.Write(text[0]);\n\n            for (var i = 1; i < text.length; i++) {\n                this.declFile.WriteLine(\"\");\n                this.emitIndent();\n                this.declFile.Write(text[i]);\n            }\n\n            if (comment.endsLine || !comment.isBlockComment) {\n                this.declFile.WriteLine(\"\");\n            } else {\n                this.declFile.Write(\" \");\n            }\n        }\n\n        private emitDeclarationComments(ast: AST, endLine?: bool);\n        private emitDeclarationComments(symbol: Symbol, endLine?: bool);\n        private emitDeclarationComments(astOrSymbol, endLine = true) {\n            if (!this.emitOptions.emitComments) {\n                return;\n            }\n\n            var declComments = <Comment[]>astOrSymbol.getDocComments();\n            if (declComments.length > 0) {\n                for (var i = 0; i < declComments.length; i++) {\n                    this.emitComment(declComments[i]);\n                }\n\n                if (endLine) {\n                    if (!this.declFile.onNewLine) {\n                        this.declFile.WriteLine(\"\");\n                    }\n                } else {\n                    if (this.declFile.onNewLine) {\n                        this.emitIndent();\n                    }\n                }\n            }\n        }\n\n        public VarDeclCallback(pre: bool, varDecl: VarDecl): bool {\n            if (pre && this.canEmitSignature(ToDeclFlags(varDecl.varFlags), false)) {\n                var interfaceMember = (this.getAstDeclarationContainer().nodeType == NodeType.InterfaceDeclaration);\n                this.emitDeclarationComments(varDecl);\n                if (!interfaceMember) {\n                    // If it is var list of form var a, b, c = emit it only if count > 0 - which will be when emitting first var\n                    // If it is var list of form  var a = varList count will be 0\n                    if (this.varListCount >= 0) {\n                        this.emitDeclFlags(ToDeclFlags(varDecl.varFlags), \"var\");\n                        this.varListCount = -this.varListCount;\n                    }\n                    this.declFile.Write(varDecl.id.text);\n                } else {\n                    this.emitIndent();\n                    this.declFile.Write(varDecl.id.text);\n                    if (hasFlag(varDecl.id.flags, ASTFlags.OptionalName)) {\n                        this.declFile.Write(\"?\");\n                    }\n                }\n\n                var type: Type = null;\n                if (varDecl.typeExpr && varDecl.typeExpr.type) {\n                    type = varDecl.typeExpr.type;\n                }\n                else if (varDecl.sym) {\n                    type = (<FieldSymbol>varDecl.sym).getType();\n                    // Dont emit inferred any\n                    if (type == this.checker.anyType) {\n                        type = null;\n                    }\n                }\n\n                if (type && this.canEmitTypeAnnotationSignature(ToDeclFlags(varDecl.varFlags))) {\n                    this.declFile.Write(\": \");\n                    this.emitTypeSignature(type);\n                }\n               \n                // emitted one var decl\n                if (this.varListCount > 0) { this.varListCount--; } else if (this.varListCount < 0) { this.varListCount++; }\n\n                // Write ; or ,\n                if (this.varListCount < 0) {\n                    this.declFile.Write(\", \");\n                } else {\n                    this.declFile.WriteLine(\";\");\n                }\n            }\n            return false;\n        }\n\n        public BlockCallback(pre: bool, block: Block): bool {\n            if (!block.isStatementBlock) {\n                if (pre) {\n                    this.varListCount = block.statements.members.length;\n                } else {\n                    this.varListCount = 0;\n                }\n                return true;\n            }\n            return false;\n        }\n\n        private emitArgDecl(argDecl: ArgDecl, funcDecl: FuncDecl) {\n            this.emitDeclarationComments(argDecl, false);\n            this.declFile.Write(argDecl.id.text);\n            if (argDecl.isOptionalArg()) {\n                this.declFile.Write(\"?\");\n            }\n            if ((argDecl.typeExpr || argDecl.type != this.checker.anyType) &&\n                this.canEmitTypeAnnotationSignature(ToDeclFlags(funcDecl.fncFlags))) {\n                this.declFile.Write(\": \");\n                this.emitTypeSignature(argDecl.type);\n            }\n        }\n\n        public FuncDeclCallback(pre: bool, funcDecl: FuncDecl): bool {\n            if (!pre) {\n                return false;\n            }\n\n            if (funcDecl.isAccessor()) {\n                return this.emitPropertyAccessorSignature(funcDecl);\n            }\n\n            var isInterfaceMember = (this.getAstDeclarationContainer().nodeType == NodeType.InterfaceDeclaration);\n            if (funcDecl.bod) {\n                if (funcDecl.isConstructor) {\n                    if (funcDecl.type.construct && funcDecl.type.construct.signatures.length > 1) {\n                        return false;\n                    }\n                } else {\n                    if (funcDecl.type.call && funcDecl.type.call.signatures.length > 1) {\n                        // This means its implementation of overload signature. do not emit\n                        return false;\n                    }\n                }\n            } else if (!isInterfaceMember && hasFlag(funcDecl.fncFlags, FncFlags.Private) && funcDecl.type.call && funcDecl.type.call.signatures.length > 1) {\n                // Print only first overload of private function\n                var signatures = funcDecl.type.call.signatures;\n                var firstSignature = signatures[0].declAST;\n                if (firstSignature.bod) {\n                    // Its a implementation, use next one\n                    firstSignature = signatures[1].declAST;\n                }\n\n                if (firstSignature != funcDecl) {\n                    return false;\n                }\n            }\n\n            if (!this.canEmitSignature(ToDeclFlags(funcDecl.fncFlags), false)) {\n                return false;\n            }\n\n            this.emitDeclarationComments(funcDecl);\n            if (funcDecl.isConstructor) {\n                this.emitIndent();\n                this.declFile.Write(\"constructor\");\n            }\n            else {\n                var id = funcDecl.getNameText();\n                if (!isInterfaceMember) {\n                    this.emitDeclFlags(ToDeclFlags(funcDecl.fncFlags), \"function\");\n                    this.declFile.Write(id);\n                } else {\n                    this.emitIndent();\n                    if (funcDecl.isConstructMember()) {\n                        this.declFile.Write(\"new\");\n                    } else if (!funcDecl.isCallMember() && !funcDecl.isIndexerMember()) {\n                        this.declFile.Write(id);\n                        if (hasFlag(funcDecl.name.flags, ASTFlags.OptionalName)) {\n                            this.declFile.Write(\"? \");\n                        }\n                    }\n                }\n            }\n\n            if (!funcDecl.isIndexerMember()) {\n                this.declFile.Write(\"(\");\n            } else {\n                this.declFile.Write(\"[\");\n            }\n\n            this.indenter.increaseIndent();\n\n            if (funcDecl.arguments) {\n                var argsLen = funcDecl.arguments.members.length;\n                if (funcDecl.variableArgList) {\n                    argsLen--;\n                }\n                for (var i = 0; i < argsLen; i++) {\n                    var argDecl = <ArgDecl>funcDecl.arguments.members[i];\n                    this.emitArgDecl(argDecl, funcDecl);\n                    if (i < (argsLen - 1)) {\n                        this.declFile.Write(\", \");\n                    }\n                }\n            }\n\n            if (funcDecl.variableArgList) {\n                var lastArg = <ArgDecl>funcDecl.arguments.members[funcDecl.arguments.members.length - 1];\n                if (funcDecl.arguments.members.length > 1) {\n                    this.declFile.Write(\", ...\");\n                }\n                else {\n                    this.declFile.Write(\"...\");\n                }\n                this.emitArgDecl(lastArg, funcDecl);\n            }\n\n            this.indenter.decreaseIndent();\n\n            if (!funcDecl.isIndexerMember()) {\n                this.declFile.Write(\")\");\n            } else {\n                this.declFile.Write(\"]\");\n            }\n\n            if (!funcDecl.isConstructor &&\n                (funcDecl.returnTypeAnnotation || funcDecl.signature.returnType.type != this.checker.anyType) &&\n                this.canEmitTypeAnnotationSignature(ToDeclFlags(funcDecl.fncFlags))) {\n                this.declFile.Write(\": \");\n                this.emitTypeSignature(funcDecl.signature.returnType.type);\n            }\n\n            this.declFile.WriteLine(\";\");\n\n            return false;\n        }\n\n        private emitBaseList(bases: ASTList, qual: string) {\n            if (bases && (bases.members.length > 0)) {\n                this.declFile.Write(\" \" + qual + \" \");\n                var basesLen = bases.members.length;\n                for (var i = 0; i < basesLen; i++) {\n                    var baseExpr = bases.members[i];\n                    var baseSymbol = baseExpr.type.symbol;\n                    var baseType = baseExpr.type;\n                    if (i > 0) {\n                        this.declFile.Write(\", \");\n                    }\n                    this.emitTypeSignature(baseType);\n                }\n            }\n        }\n\n        private emitPropertyAccessorSignature(funcDecl: FuncDecl) {\n            var accessorSymbol = <FieldSymbol>funcDecl.accessorSymbol;\n            if (accessorSymbol.getter && accessorSymbol.getter.declAST != funcDecl) {\n                // Setter is being used to emit the type info. \n                return false;\n            }\n\n            this.emitDeclarationComments(accessorSymbol);\n            this.emitDeclFlags(ToDeclFlags(accessorSymbol.flags), \"var\");\n            this.declFile.Write(funcDecl.name.text);\n            var propertyType = accessorSymbol.getType();\n            if (this.canEmitTypeAnnotationSignature(ToDeclFlags(accessorSymbol.flags))) {\n                this.declFile.Write(\" : \");\n                this.emitTypeSignature(propertyType);\n            }\n            this.declFile.WriteLine(\";\");\n\n            return false;\n        }\n\n        private emitClassMembersFromConstructorDefinition(funcDecl: FuncDecl) {\n            if (funcDecl.arguments) {\n                var argsLen = funcDecl.arguments.members.length; if (funcDecl.variableArgList) { argsLen--; }\n\n                for (var i = 0; i < argsLen; i++) {\n                    var argDecl = <ArgDecl>funcDecl.arguments.members[i];\n                    if (hasFlag(argDecl.varFlags, VarFlags.Property)) {\n                        this.emitDeclarationComments(argDecl);\n                        this.emitDeclFlags(ToDeclFlags(argDecl.varFlags), \"var\");\n                        this.declFile.Write(argDecl.id.text);\n\n                        if (argDecl.typeExpr && this.canEmitTypeAnnotationSignature(ToDeclFlags(argDecl.varFlags))) {\n                            this.declFile.Write(\": \");\n                            this.emitTypeSignature(argDecl.type);\n                        }\n                        this.declFile.WriteLine(\";\");\n                    }\n                }\n            }\n        }\n\n        public ClassDeclarationCallback(pre: bool, classDecl: ClassDeclaration): bool {\n            if (!this.canEmitPrePostAstSignature(ToDeclFlags(classDecl.varFlags), classDecl, pre)) {\n                return false;\n            }\n\n            if (pre) {\n                var className = classDecl.name.text;\n                this.emitDeclarationComments(classDecl);\n                this.emitDeclFlags(ToDeclFlags(classDecl.varFlags), \"class\");\n                this.declFile.Write(className);\n                this.emitBaseList(classDecl.extendsList, \"extends\");\n                this.emitBaseList(classDecl.implementsList, \"implements\");\n                this.declFile.WriteLine(\" {\");\n\n                this.pushDeclarationContainer(classDecl);\n                this.indenter.increaseIndent();\n                if (classDecl.constructorDecl) {\n                    this.emitClassMembersFromConstructorDefinition(classDecl.constructorDecl);\n                }\n            } else {\n                this.indenter.decreaseIndent();\n                this.popDeclarationContainer(classDecl);\n\n                this.emitIndent();\n                this.declFile.WriteLine(\"}\");\n            }\n\n            return true;\n        }\n\n        public InterfaceDeclarationCallback(pre: bool, interfaceDecl: InterfaceDeclaration): bool {\n            if (!this.canEmitPrePostAstSignature(ToDeclFlags(interfaceDecl.varFlags), interfaceDecl, pre)) {\n                return false;\n            }\n\n            if (pre) {\n                var interfaceName = interfaceDecl.name.text;\n                this.emitDeclarationComments(interfaceDecl);\n                this.emitDeclFlags(ToDeclFlags(interfaceDecl.varFlags), \"interface\");\n                this.declFile.Write(interfaceName);\n                this.emitBaseList(interfaceDecl.extendsList, \"extends\");\n                this.declFile.WriteLine(\" {\");\n\n                this.indenter.increaseIndent();\n                this.pushDeclarationContainer(interfaceDecl);\n            } else {\n                this.indenter.decreaseIndent();\n                this.popDeclarationContainer(interfaceDecl);\n\n                this.emitIndent();\n                this.declFile.WriteLine(\"}\");\n            }\n\n            return true;\n        }\n\n        public ImportDeclarationCallback(pre: bool, importDecl: ImportDeclaration): bool {\n            if (pre) {\n                if ((<Script>this.declarationContainerStack[0]).isExternallyVisibleSymbol(importDecl.id.sym)) {\n                    this.emitDeclarationComments(importDecl);\n                    this.emitIndent();\n                    this.declFile.Write(\"import \");\n\n                    this.declFile.Write(importDecl.id.text + \" = \");\n                    if (importDecl.isDynamicImport) {\n                        this.declFile.WriteLine(\"module (\" + importDecl.getAliasName() + \");\");\n                    } else {\n                        this.declFile.WriteLine(importDecl.getAliasName() + \";\");\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        private emitEnumSignature(moduleDecl: ModuleDeclaration) {\n            if (!this.canEmitSignature(ToDeclFlags(moduleDecl.modFlags))) {\n                return false;\n            }\n\n            this.emitDeclarationComments(moduleDecl);\n            this.emitDeclFlags(ToDeclFlags(moduleDecl.modFlags), \"enum\");\n            this.declFile.WriteLine(moduleDecl.name.text + \" {\");\n\n            this.indenter.increaseIndent();\n            var membersLen = moduleDecl.members.members.length;\n            for (var j = 1; j < membersLen; j++) {\n                var memberDecl: AST = moduleDecl.members.members[j];\n                if (memberDecl.nodeType == NodeType.VarDecl) {\n                    this.emitDeclarationComments(memberDecl);\n                    this.emitIndent();\n                    this.declFile.WriteLine((<VarDecl>memberDecl).id.text + \",\");\n                } else {\n                    CompilerDiagnostics.assert(memberDecl.nodeType != NodeType.Asg, \"We want to catch this\");\n                }\n            }\n            this.indenter.decreaseIndent();\n\n            this.emitIndent();\n            this.declFile.WriteLine(\"}\");\n\n            return false;\n        }\n\n        public ModuleDeclarationCallback(pre: bool, moduleDecl: ModuleDeclaration): bool {\n            if (hasFlag(moduleDecl.modFlags, ModuleFlags.IsWholeFile)) {\n                // This is dynamic modules and we are going to outputing single file, \n                // we need to change the declFile because dynamic modules are always emitted to their corresponding .d.ts\n                if (hasFlag(moduleDecl.modFlags, ModuleFlags.IsDynamic)) {\n                    if (pre) {\n                        if (!this.emitOptions.outputMany) {\n                            this.singleDeclFile = this.declFile;\n                            CompilerDiagnostics.assert(this.indenter.indentAmt == 0, \"Indent has to be 0 when outputing new file\");\n                            // Create new file\n                            var declareFileName = this.emitOptions.mapOutputFileName(stripQuotes(moduleDecl.name.sym.name), TypeScriptCompiler.mapToDTSFileName);\n                            var useUTF8InOutputfile = moduleDecl.containsUnicodeChar || (this.emitOptions.emitComments && moduleDecl.containsUnicodeCharInComment);\n                            try {\n                                // Creating files can cause exceptions, report them.   \n                                this.declFile = new DeclFileWriter(this.emitOptions.ioHost.createFile(declareFileName, useUTF8InOutputfile));\n                            } catch (ex) {\n                                this.errorReporter.emitterError(null, ex.message);\n                            }\n                        }\n                        this.pushDeclarationContainer(moduleDecl);\n                    } else {\n                        if (!this.emitOptions.outputMany) {\n                            CompilerDiagnostics.assert(this.singleDeclFile != this.declFile, \"singleDeclFile cannot be null as we are going to revert back to it\");\n                            CompilerDiagnostics.assert(this.indenter.indentAmt == 0, \"Indent has to be 0 when outputing new file\");\n                            try {\n                                // Closing files could result in exceptions, report them if they occur\n                                this.declFile.Close();\n                            } catch (ex) {\n                                this.errorReporter.emitterError(null, ex.message);\n                            }\n                            this.declFile = this.singleDeclFile;\n                        }\n                        this.popDeclarationContainer(moduleDecl);\n                    }\n                }\n\n                return true;\n            }\n\n            if (moduleDecl.isEnum()) {\n                if (pre) {\n                    this.emitEnumSignature(moduleDecl);\n                }\n                return false;\n            }\n\n            if (!this.canEmitPrePostAstSignature(ToDeclFlags(moduleDecl.modFlags), moduleDecl, pre)) {\n                return false;\n            }\n\n            if (pre) {\n                if (this.emitDottedModuleName()) {\n                    this.dottedModuleEmit += \".\";\n                } else {\n                    this.dottedModuleEmit = this.getDeclFlagsString(ToDeclFlags(moduleDecl.modFlags), \"module\");\n                }\n                this.dottedModuleEmit += moduleDecl.name.text;\n\n                var isCurrentModuleDotted = (moduleDecl.members.members.length == 1 &&\n                    moduleDecl.members.members[0].nodeType == NodeType.ModuleDeclaration &&\n                    !(<ModuleDeclaration>moduleDecl.members.members[0]).isEnum() &&\n                    hasFlag((<ModuleDeclaration>moduleDecl.members.members[0]).modFlags, ModuleFlags.Exported));\n\n                // Module is dotted only if it does not have doc comments for it\n                var moduleDeclComments = moduleDecl.getDocComments();\n                isCurrentModuleDotted = isCurrentModuleDotted && (moduleDeclComments == null || moduleDeclComments.length == 0);\n\n                this.isDottedModuleName.push(isCurrentModuleDotted);\n                this.pushDeclarationContainer(moduleDecl);\n\n                if (!isCurrentModuleDotted) {\n                    this.emitDeclarationComments(moduleDecl);\n                    this.declFile.Write(this.dottedModuleEmit);\n                    this.declFile.WriteLine(\" {\");\n                    this.indenter.increaseIndent();\n                }\n            } else {\n                if (!this.emitDottedModuleName()) {\n                    this.indenter.decreaseIndent();\n                    this.emitIndent();\n                    this.declFile.WriteLine(\"}\");\n                }\n                this.popDeclarationContainer(moduleDecl);\n                this.isDottedModuleName.pop();\n            }\n\n            return true;\n        }\n\n        public ScriptCallback(pre: bool, script: Script): bool {\n            if (pre) {\n                if (this.emitOptions.outputMany) {\n                    for (var i = 0; i < script.referencedFiles.length; i++) {\n                        var referencePath = script.referencedFiles[i].path;\n                        var declareFileName: string;\n                        if (isRooted(referencePath)) {\n                            declareFileName = this.emitOptions.mapOutputFileName(referencePath, TypeScriptCompiler.mapToDTSFileName)\n                        } else {\n                            declareFileName = getDeclareFilePath(script.referencedFiles[i].path);\n                        }\n                        this.declFile.WriteLine('/// <reference path=\"' + declareFileName + '\" />');\n                    }\n                }\n                this.pushDeclarationContainer(script);\n            }\n            else {\n                this.popDeclarationContainer(script);\n            }\n            return true;\n        }\n\n        public DefaultCallback(pre: bool, ast: AST): bool {\n            return !hasFlag(ast.flags, ASTFlags.IsStatement);\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export module CompilerDiagnostics {\n        export var debug = false;\n        export interface IDiagnosticWriter {\n            Alert(output: string): void;\n        }\n\n        export var diagnosticWriter: IDiagnosticWriter = null;\n\n        export var analysisPass: number = 0;\n\n        export function Alert(output: string) {\n            if (diagnosticWriter) {\n                diagnosticWriter.Alert(output);\n            }\n        }\n\n        export function debugPrint(s: string) {\n            if (debug) {\n                Alert(s);\n            }\n        }\n\n        export function assert(condition: bool, s: string) {\n            if (debug) {\n                if (!condition) {\n                    Alert(s);\n                }\n            }\n        }\n\n    }\n\n    export interface ILogger {\n        information(): bool;\n        debug(): bool;\n        warning(): bool;\n        error(): bool;\n        fatal(): bool;\n        log(s: string): void;\n    }\n\n    export class NullLogger implements ILogger {\n        public information(): bool { return false; }\n        public debug(): bool { return false; }\n        public warning(): bool { return false; }\n        public error(): bool { return false; }\n        public fatal(): bool { return false; }\n        public log(s: string): void {\n        }\n    }\n\n    export class LoggerAdapter implements ILogger {\n        private _information: bool;\n        private _debug: bool;\n        private _warning: bool;\n        private _error: bool;\n        private _fatal: bool;\n\n        constructor (public logger: ILogger) { \n            this._information = this.logger.information();\n            this._debug = this.logger.debug();\n            this._warning = this.logger.warning();\n            this._error = this.logger.error();\n            this._fatal = this.logger.fatal();\n        }\n\n\n        public information(): bool { return this._information; }\n        public debug(): bool { return this._debug; }\n        public warning(): bool { return this._warning; }\n        public error(): bool { return this._error; }\n        public fatal(): bool { return this._fatal; }\n        public log(s: string): void {\n            this.logger.log(s);\n        }\n    }\n\n    export class BufferedLogger implements ILogger {\n        public logContents = [];\n\n        public information(): bool { return false; }\n        public debug(): bool { return false; }\n        public warning(): bool { return false; }\n        public error(): bool { return false; }\n        public fatal(): bool { return false; }\n        public log(s: string): void {\n            this.logContents.push(s);\n        }\n    }\n\n    export function timeFunction(logger: ILogger, funcDescription: string, func: () =>any): any {\n        var start = +new Date();\n        var result = func();\n        var end = +new Date();\n        logger.log(funcDescription + \" completed in \" + (end - start) + \" msec\");\n        return result;\n    }\n\n    export function stringToLiteral(value: string, length: number): string {\n        var result = \"\";\n\n        var addChar = (index: number) => {\n            var ch = value.charCodeAt(index);\n            switch (ch) {\n                case 0x09: // tab\n                    result += \"\\\\t\";\n                    break;\n                case 0x0a: // line feed\n                    result += \"\\\\n\";\n                    break;\n                case 0x0b: // vertical tab\n                    result += \"\\\\v\";\n                    break;\n                case 0x0c: // form feed\n                    result += \"\\\\f\";\n                    break;\n                case 0x0d: // carriage return\n                    result += \"\\\\r\";\n                    break;\n                case 0x22:  // double quote\n                    result += \"\\\\\\\"\";\n                    break;\n                case 0x27: // single quote\n                    result += \"\\\\\\'\";\n                    break;\n                case 0x5c: // Backslash\n                    result += \"\\\\\";\n                    break;\n                default:\n                    result += value.charAt(index);\n            }\n        }\n\n        var tooLong = (value.length > length);\n        if (tooLong) {\n            var mid = length >> 1;\n            for (var i = 0; i < mid; i++) addChar(i);\n            result += \"(...)\";\n            for (var i = value.length - mid; i < value.length; i++) addChar(i);\n        }\n        else {\n            length = value.length;\n            for (var i = 0; i < length; i++) addChar(i);\n        }\n        return result;\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export enum EmitContainer {\n        Prog,\n        Module,\n        DynamicModule,\n        Class,\n        Constructor,\n        Function,\n        Args,\n        Interface,\n    }\n\n    export class EmitState {\n        public column: number;\n        public line: number;\n        public pretty: bool;\n        public inObjectLiteral: bool;\n        public container: EmitContainer;\n\n        constructor () {\n            this.column = 0;\n            this.line = 0;\n            this.pretty = false;\n            this.inObjectLiteral = false;\n            this.container = EmitContainer.Prog;\n        }\n    }\n\n    export class EmitOptions {\n        public minWhitespace: bool;\n        public propagateConstants: bool;\n        public emitComments: bool;\n        public outputOption: string;\n        public ioHost: EmitterIOHost = null;\n        public outputMany: bool = true;\n        public commonDirectoryPath = \"\";\n\n        constructor(settings: CompilationSettings) {\n            this.minWhitespace = settings.minWhitespace;\n            this.propagateConstants = settings.propagateConstants;\n            this.emitComments = settings.emitComments;\n            this.outputOption = settings.outputOption;\n        }\n\n        public mapOutputFileName(fileName: string, extensionChanger: (fname: string, wholeFileNameReplaced: bool) => string) {\n            if (this.outputMany) {\n                var updatedFileName = fileName;\n                if (this.outputOption != \"\") {\n                    // Replace the common directory path with the option specified\n                    updatedFileName = fileName.replace(this.commonDirectoryPath, \"\");\n                    updatedFileName = this.outputOption + updatedFileName;\n                }\n                return extensionChanger(updatedFileName, false);\n            } else {\n                return extensionChanger(this.outputOption, true);\n            }\n        }\n    }\n\n    export class Indenter {\n        static indentStep : number = 4;\n        static indentStepString : string = \"    \";\n        static indentStrings: string[] = [];\n        public indentAmt: number = 0;\n\n        public increaseIndent() {\n            this.indentAmt += Indenter.indentStep;\n        }\n\n        public decreaseIndent() {\n            this.indentAmt -= Indenter.indentStep;\n        }\n\n        public getIndent() {\n            var indentString = Indenter.indentStrings[this.indentAmt];\n            if (indentString === undefined) {\n                indentString = \"\";\n                for (var i = 0; i < this.indentAmt; i = i + Indenter.indentStep) {\n                    indentString += Indenter.indentStepString;\n                }\n                Indenter.indentStrings[this.indentAmt] = indentString;\n            }\n            return indentString;\n        }\n    }\n\n    export class Emitter {\n        public prologueEmitted = false;\n        public thisClassNode: TypeDeclaration = null;\n        public thisFnc: FuncDecl = null;\n        public moduleDeclList: ModuleDeclaration[] = [];\n        public moduleName = \"\";\n        public emitState = new EmitState();\n        public indenter = new Indenter();\n        public ambientModule = false;\n        public modAliasId: string = null;\n        public firstModAlias: string = null;\n        public allSourceMappers: SourceMapper[] = [];\n        public sourceMapper: SourceMapper = null;\n        public captureThisStmtString = \"var _this = this;\";\n        private varListCountStack: number[] = [0]; \n\n        constructor(public checker: TypeChecker, public emittingFileName: string, public outfile: ITextWriter, public emitOptions: EmitOptions, public errorReporter: ErrorReporter) {\n        }\n\n        public setSourceMappings(mapper: SourceMapper) {\n            this.allSourceMappers.push(mapper);\n            this.sourceMapper = mapper;\n        }\n\n        public writeToOutput(s: string) {\n            this.outfile.Write(s);\n            // TODO: check s for newline\n            this.emitState.column += s.length;\n        }\n\n        public writeToOutputTrimmable(s: string) {\n            if (this.emitOptions.minWhitespace) {\n                s = s.replace(/[\\s]*/g, '');\n            }\n            this.writeToOutput(s);\n        }\n\n        public writeLineToOutput(s: string) {\n            if (this.emitOptions.minWhitespace) {\n                this.writeToOutput(s);\n                var c = s.charCodeAt(s.length - 1);\n                if (!((c == LexCodeSpace) || (c == LexCodeSMC) || (c == LexCodeLBR))) {\n                    this.writeToOutput(' ');\n                }\n            }\n            else {\n                this.outfile.WriteLine(s);\n                this.emitState.column = 0\n                this.emitState.line++;\n            }\n        }\n\n        public writeCaptureThisStatement(ast: AST) {\n            this.emitIndent();\n            this.recordSourceMappingStart(ast);\n            this.writeToOutput(this.captureThisStmtString);\n            this.recordSourceMappingEnd(ast);\n            this.writeLineToOutput(\"\");\n        }\n\n        public setInVarBlock(count: number) {\n            this.varListCountStack[this.varListCountStack.length - 1] = count;\n        }\n\n        public setInObjectLiteral(val: bool): bool {\n            var temp = this.emitState.inObjectLiteral;\n            this.emitState.inObjectLiteral = val;\n            return temp;\n        }\n\n        public setContainer(c: number): number {\n            var temp = this.emitState.container;\n            this.emitState.container = c;\n            return temp;\n        }\n\n        private getIndentString() {\n            if (this.emitOptions.minWhitespace) {\n                return \"\";\n            }\n            else {\n                return this.indenter.getIndent();\n            }\n        }\n\n        public emitIndent() {\n            this.writeToOutput(this.getIndentString());\n        }\n\n        public emitCommentInPlace(comment: Comment) {\n            var text = comment.getText();\n            var hadNewLine = false;\n\n            if (comment.isBlockComment) {\n                if (this.emitState.column == 0) {\n                    this.emitIndent();\n                }\n                this.recordSourceMappingStart(comment);\n                this.writeToOutput(text[0]);\n\n                if (text.length > 1 || comment.endsLine) {\n                    for (var i = 1; i < text.length; i++) {\n                        this.writeLineToOutput(\"\");\n                        this.emitIndent();\n                        this.writeToOutput(text[i]);\n                    }\n                    this.recordSourceMappingEnd(comment);\n                    this.writeLineToOutput(\"\");\n                    hadNewLine = true;\n                } else {\n                    this.recordSourceMappingEnd(comment);\n                }\n            }\n            else {\n                if (this.emitState.column == 0) {\n                    this.emitIndent();\n                }\n                this.recordSourceMappingStart(comment);\n                this.writeToOutput(text[0]);\n                this.recordSourceMappingEnd(comment);\n                this.writeLineToOutput(\"\");\n                hadNewLine = true;\n            }\n\n            if (hadNewLine) {\n                this.emitIndent();\n            }\n            else {\n                this.writeToOutput(\" \");\n            }\n        }\n\n        public emitParensAndCommentsInPlace(ast: AST, pre: bool) {\n            var comments = pre ? ast.preComments : ast.postComments;\n\n            // comments should be printed before the LParen, but after the RParen\n            if (ast.isParenthesized && !pre) {\n                this.writeToOutput(\")\");\n            }\n            if (this.emitOptions.emitComments && comments && comments.length != 0) {\n                for (var i = 0; i < comments.length; i++) {\n                    this.emitCommentInPlace(comments[i]);\n                }\n            }\n            if (ast.isParenthesized && pre) {\n                this.writeToOutput(\"(\");\n            }\n        }\n\n        // TODO: emit accessor pattern\n        public emitObjectLiteral(content: ASTList) {\n            this.writeLineToOutput(\"{\");\n            this.indenter.increaseIndent();\n            var inObjectLiteral = this.setInObjectLiteral(true);\n            this.emitJavascriptList(content, \",\", TokenID.Comma, true, false, false);\n            this.setInObjectLiteral(inObjectLiteral);\n            this.indenter.decreaseIndent();\n            this.emitIndent();\n            this.writeToOutput(\"}\");\n        }\n\n        public emitArrayLiteral(content: ASTList) {\n            this.writeToOutput(\"[\");\n            if (content) {\n                this.writeLineToOutput(\"\");\n                this.indenter.increaseIndent();\n                this.emitJavascriptList(content, \", \", TokenID.Comma, true, false, false);\n                this.indenter.decreaseIndent();\n                this.emitIndent();\n            }\n            this.writeToOutput(\"]\");\n        }\n\n        public emitNew(target: AST, args: ASTList) {\n            this.writeToOutput(\"new \");\n            if (target.nodeType == NodeType.TypeRef) {\n                var typeRef = <TypeReference>target;\n                if (typeRef.arrayCount) {\n                    this.writeToOutput(\"Array()\");\n                }\n                else {\n                    this.emitJavascript(typeRef.term, TokenID.Tilde, false);\n                    this.writeToOutput(\"()\");\n                }\n            }\n            else {\n                this.emitJavascript(target, TokenID.Tilde, false);\n                this.recordSourceMappingStart(args);\n                this.writeToOutput(\"(\");\n                this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n                this.writeToOutput(\")\");\n                this.recordSourceMappingEnd(args);\n            }\n        }\n\n        public tryEmitConstant(dotExpr: BinaryExpression) {\n            if (!this.emitOptions.propagateConstants) {\n                return false;\n            }\n            var propertyName = <Identifier>dotExpr.operand2;\n            if (propertyName && propertyName.sym && propertyName.sym.isVariable()) {\n                if (hasFlag(propertyName.sym.flags, SymbolFlags.Constant)) {\n                    if (propertyName.sym.declAST) {\n                        var boundDecl = <BoundDecl>propertyName.sym.declAST;\n                        if (boundDecl.init && (boundDecl.init.nodeType == NodeType.NumberLit)) {\n                            var numLit = <NumberLiteral>boundDecl.init;\n                            this.writeToOutput(numLit.value.toString());\n                            var comment = \" /* \";\n                            comment += propertyName.actualText;\n                            comment += \" */ \";\n                            this.writeToOutput(comment);\n                            return true;\n                        }\n                    }\n                }\n            }\n            return false;\n        }\n\n        public emitCall(callNode: CallExpression, target: AST, args: ASTList) {\n            if (!this.emitSuperCall(callNode)) {\n                if (!hasFlag(callNode.flags, ASTFlags.ClassBaseConstructorCall)) {\n                    if (target.nodeType == NodeType.FuncDecl && !target.isParenthesized) {\n                        this.writeToOutput(\"(\");\n                    }\n                    if (callNode.target.nodeType == NodeType.Super && this.emitState.container == EmitContainer.Constructor) {\n                        this.writeToOutput(\"_super.call\");\n                    }\n                    else {\n                        this.emitJavascript(target, TokenID.OpenParen, false);\n                    }\n                    if (target.nodeType == NodeType.FuncDecl && !target.isParenthesized) {\n                        this.writeToOutput(\")\");\n                    }\n                    this.recordSourceMappingStart(args);\n                    this.writeToOutput(\"(\");\n                    if (callNode.target.nodeType == NodeType.Super && this.emitState.container == EmitContainer.Constructor) {\n                        this.writeToOutput(\"this\");\n                        if (args && args.members.length) {\n                            this.writeToOutput(\", \");\n                        }\n                    }\n                    this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n                    this.writeToOutput(\")\");\n                    this.recordSourceMappingEnd(args);\n                }\n                else {\n                    this.indenter.decreaseIndent();\n                    this.indenter.decreaseIndent();\n                    var constructorCall = new ASTList();\n                    constructorCall.members[0] = callNode;\n                    this.emitConstructorCalls(constructorCall, this.thisClassNode);\n                    this.indenter.increaseIndent();\n                    this.indenter.increaseIndent();\n                }\n            }\n        }\n\n        public emitConstructorCalls(bases: ASTList, classDecl: TypeDeclaration) {\n            if (bases == null) {\n                return;\n            }\n            var basesLen = bases.members.length;\n            this.recordSourceMappingStart(classDecl);\n            for (var i = 0; i < basesLen; i++) {\n                var baseExpr = bases.members[i];\n                var baseSymbol: Symbol = null;\n                if (baseExpr.nodeType == NodeType.Call) {\n                    baseSymbol = (<CallExpression>baseExpr).target.type.symbol;\n                }\n                else {\n                    baseSymbol = baseExpr.type.symbol;\n                }\n                var baseName = baseSymbol.name;\n                if (baseSymbol.declModule != classDecl.type.symbol.declModule) {\n                    baseName = baseSymbol.fullName();\n                }\n                if (baseExpr.nodeType == NodeType.Call) {\n                    this.emitIndent();\n                    this.writeToOutput(\"_super.call(this\");\n                    var args = (<CallExpression>baseExpr).arguments;\n                    if (args && (args.members.length > 0)) {\n                        this.writeToOutput(\", \");\n                        this.emitJavascriptList(args, \", \", TokenID.Comma, false, false, false);\n                    }\n                    this.writeToOutput(\")\");\n                }\n                else {\n                    if (baseExpr.type && (baseExpr.type.isClassInstance())) {\n                        // parameterless constructor call;\n                        this.emitIndent();\n                        this.writeToOutput(classDecl.name.actualText + \"._super.constructor\");\n                        //emitJavascript(baseExpr,TokenID.LParen,false);\n                        this.writeToOutput(\".call(this)\");\n                    }\n                }\n            }\n            this.recordSourceMappingEnd(classDecl);\n        }\n\n        public emitInnerFunction(funcDecl: FuncDecl, printName: bool, isMember: bool,\n            bases: ASTList, hasSelfRef: bool, classDecl: TypeDeclaration) {\n            /// REVIEW: The code below causes functions to get pushed to a newline in cases where they shouldn't\n            /// such as: \n            ///     Foo.prototype.bar = \n            ///         function() {\n            ///         };\n            /// Once we start emitting comments, we should pull this code out to place on the outer context where the function\n            /// is used.\n            //if (funcDecl.preComments!=null && funcDecl.preComments.length>0) {\n            //    this.writeLineToOutput(\"\");\n            //    this.increaseIndent();\n            //    emitIndent();\n            //}\n\n            var isClassConstructor = funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod);\n            var hasNonObjectBaseType = isClassConstructor && hasFlag(this.thisClassNode.type.instanceType.typeFlags, TypeFlags.HasBaseType) && !hasFlag(this.thisClassNode.type.instanceType.typeFlags, TypeFlags.HasBaseTypeOfObject);\n            var classPropertiesMustComeAfterSuperCall = hasNonObjectBaseType && hasFlag((<ClassDeclaration>this.thisClassNode).varFlags, VarFlags.ClassSuperMustBeFirstCallInConstructor);\n\n            // We have no way of knowing if the current function is used as an expression or a statement, so as to enusre that the emitted\n            // JavaScript is always valid, add an extra parentheses for unparenthesized function expressions\n            var shouldParenthesize = hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression) && !funcDecl.isParenthesized && !funcDecl.isAccessor() && (hasFlag(funcDecl.flags, ASTFlags.ExplicitSemicolon) || hasFlag(funcDecl.flags, ASTFlags.AutomaticSemicolon));\n\n            this.emitParensAndCommentsInPlace(funcDecl, true);\n            if (shouldParenthesize) {\n                this.writeToOutput(\"(\");\n            }\n            this.recordSourceMappingStart(funcDecl);\n            if (!(funcDecl.isAccessor() && (<FieldSymbol>funcDecl.accessorSymbol).isObjectLitField)) {\n                this.writeToOutput(\"function \");\n            }\n            if (printName) {\n                var id = funcDecl.getNameText();\n                if (id && !funcDecl.isAccessor()) {\n                    if (funcDecl.name) {\n                        this.recordSourceMappingStart(funcDecl.name);\n                    }\n                    this.writeToOutput(id);\n                    if (funcDecl.name) {\n                        this.recordSourceMappingEnd(funcDecl.name);\n                    }\n                }\n            }\n\n            this.writeToOutput(\"(\");\n            var argsLen = 0;\n            var i = 0;\n            var arg: ArgDecl;\n            var defaultArgs: ArgDecl[] = [];\n            if (funcDecl.arguments) {\n                var tempContainer = this.setContainer(EmitContainer.Args);\n                argsLen = funcDecl.arguments.members.length;\n                var printLen = argsLen;\n                if (funcDecl.variableArgList) {\n                    printLen--;\n                }\n                for (i = 0; i < printLen; i++) {\n                    arg = <ArgDecl>funcDecl.arguments.members[i];\n                    if (arg.init) {\n                        defaultArgs.push(arg);\n                    }\n                    this.emitJavascript(arg, TokenID.OpenParen, false);\n                    if (i < (printLen - 1)) {\n                        this.writeToOutput(\", \");\n                    }\n                }\n                this.setContainer(tempContainer);\n            }\n            this.writeLineToOutput(\") {\");\n\n            if (funcDecl.isConstructor) {\n                this.recordSourceMappingNameStart(\"constructor\");\n            } else if (funcDecl.isGetAccessor()) {\n                this.recordSourceMappingNameStart(\"get_\" + funcDecl.getNameText());\n            } else if (funcDecl.isSetAccessor()) {\n                this.recordSourceMappingNameStart(\"set_\" + funcDecl.getNameText());\n            } else {\n                this.recordSourceMappingNameStart(funcDecl.getNameText());\n            }\n            this.indenter.increaseIndent();\n\n            // set default args first\n            for (i = 0; i < defaultArgs.length; i++) {\n                var arg = defaultArgs[i];\n                this.emitIndent();\n                this.recordSourceMappingStart(arg);\n                this.writeToOutput(\"if (typeof \" + arg.id.actualText + \" === \\\"undefined\\\") { \");//\n                this.recordSourceMappingStart(arg.id);\n                this.writeToOutput(arg.id.actualText);\n                this.recordSourceMappingEnd(arg.id);\n                this.writeToOutput(\" = \");\n                this.emitJavascript(arg.init, TokenID.OpenParen, false);\n                this.writeLineToOutput(\"; }\")\n                this.recordSourceMappingEnd(arg);\n            }\n\n            if (funcDecl.isConstructor && ((<ClassDeclaration>funcDecl.classDecl).varFlags & VarFlags.MustCaptureThis)) {\n                this.writeCaptureThisStatement(funcDecl);\n            }\n\n            if (funcDecl.isConstructor && !classPropertiesMustComeAfterSuperCall) {\n                if (funcDecl.arguments) {\n                    argsLen = funcDecl.arguments.members.length;\n                    for (i = 0; i < argsLen; i++) {\n                        arg = <ArgDecl>funcDecl.arguments.members[i];\n                        if ((arg.varFlags & VarFlags.Property) != VarFlags.None) {\n                            this.emitIndent();\n                            this.recordSourceMappingStart(arg);\n                            this.recordSourceMappingStart(arg.id);\n                            this.writeToOutput(\"this.\" + arg.id.actualText);\n                            this.recordSourceMappingEnd(arg.id);\n                            this.writeToOutput(\" = \");\n                            this.recordSourceMappingStart(arg.id);\n                            this.writeToOutput(arg.id.actualText);\n                            this.recordSourceMappingEnd(arg.id);\n                            this.writeLineToOutput(\";\");\n                            this.recordSourceMappingEnd(arg);\n                        }\n                    }\n                }\n\n                // For classes, the constructor needs to be explicitly called\n                if (!hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n                    this.emitConstructorCalls(bases, classDecl);\n                }\n            }\n            if (hasSelfRef) {\n                this.writeCaptureThisStatement(funcDecl);\n            }\n            if (funcDecl.variableArgList) {\n                argsLen = funcDecl.arguments.members.length;\n                var lastArg = <ArgDecl>funcDecl.arguments.members[argsLen - 1];\n                this.emitIndent();\n                this.recordSourceMappingStart(lastArg);\n                this.writeToOutput(\"var \");\n                this.recordSourceMappingStart(lastArg.id);\n                this.writeToOutput(lastArg.id.actualText);\n                this.recordSourceMappingEnd(lastArg.id);\n                this.writeLineToOutput(\" = [];\");\n                this.recordSourceMappingEnd(lastArg);\n                this.emitIndent();\n                this.writeToOutput(\"for (\")\n                this.recordSourceMappingStart(lastArg);\n                this.writeToOutput(\"var _i = 0;\");\n                this.recordSourceMappingEnd(lastArg);\n                this.writeToOutput(\" \");\n                this.recordSourceMappingStart(lastArg);\n                this.writeToOutput(\"_i < (arguments.length - \" + (argsLen - 1) + \")\");\n                this.recordSourceMappingEnd(lastArg);\n                this.writeToOutput(\"; \");\n                this.recordSourceMappingStart(lastArg);\n                this.writeToOutput(\"_i++\");\n                this.recordSourceMappingEnd(lastArg);\n                this.writeLineToOutput(\") {\");\n                this.indenter.increaseIndent();\n                this.emitIndent();\n\n                this.recordSourceMappingStart(lastArg);\n                this.writeToOutput(lastArg.id.actualText + \"[_i] = arguments[_i + \" + (argsLen - 1) + \"];\");\n                this.recordSourceMappingEnd(lastArg);\n                this.writeLineToOutput(\"\");\n                this.indenter.decreaseIndent();\n                this.emitIndent();\n                this.writeLineToOutput(\"}\");\n            }\n\n            // if it's a class, emit the uninitializedMembers, first emit the non-proto class body members\n            if (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod) && !classPropertiesMustComeAfterSuperCall) {\n\n                var nProps = (<ASTList>this.thisClassNode.members).members.length;\n\n                for (var i = 0; i < nProps; i++) {\n                    if ((<ASTList>this.thisClassNode.members).members[i].nodeType == NodeType.VarDecl) {\n                        var varDecl = <VarDecl>(<ASTList>this.thisClassNode.members).members[i];\n                        if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n                            this.emitIndent();\n                            this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n                            this.writeLineToOutput(\"\");\n                        }\n                    }\n                }\n                //this.writeLineToOutput(\"\");\n            }\n\n            this.emitBareJavascriptStatements(funcDecl.bod, classPropertiesMustComeAfterSuperCall);\n\n            this.indenter.decreaseIndent();\n            this.emitIndent();\n            this.recordSourceMappingStart(funcDecl.endingToken);\n            this.writeToOutput(\"}\");\n\n            this.recordSourceMappingNameEnd();\n            this.recordSourceMappingEnd(funcDecl.endingToken);\n            this.recordSourceMappingEnd(funcDecl);\n\n            if (shouldParenthesize) {\n                this.writeToOutput(\")\");\n            }\n\n            // The extra call is to make sure the caller's funcDecl end is recorded, since caller wont be able to record it\n            this.recordSourceMappingEnd(funcDecl);\n\n            this.emitParensAndCommentsInPlace(funcDecl, false);\n\n            if (!isMember &&\n                //funcDecl.name != null &&\n                !hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression) &&\n                (hasFlag(funcDecl.fncFlags, FncFlags.Definition) || funcDecl.isConstructor)) {\n                this.writeLineToOutput(\"\");\n            } else if (hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression)) {\n                if (hasFlag(funcDecl.flags, ASTFlags.ExplicitSemicolon) || hasFlag(funcDecl.flags, ASTFlags.AutomaticSemicolon)) {\n                    // If either of these two flags are set, then the function expression is a statement. Terminate it.\n                    this.writeLineToOutput(\";\");\n                }\n            }\n            /// TODO: See the other part of this at the beginning of function\n            //if (funcDecl.preComments!=null && funcDecl.preComments.length>0) {\n            //    this.decreaseIndent();\n            //}           \n        }\n\n        public emitJavascriptModule(moduleDecl: ModuleDeclaration) {\n            var modName = moduleDecl.name.actualText;\n            if (isTSFile(modName)) {\n                moduleDecl.name.setText(modName.substring(0, modName.length - 3));\n            }\n            else if (isSTRFile(modName)) {\n                moduleDecl.name.setText(modName.substring(0, modName.length - 4));\n            }\n\n            if (!hasFlag(moduleDecl.modFlags, ModuleFlags.Ambient)) {\n                var isDynamicMod = hasFlag(moduleDecl.modFlags, ModuleFlags.IsDynamic);\n                var prevOutFile = this.outfile;\n                var prevOutFileName = this.emittingFileName;\n                var prevAllSourceMappers = this.allSourceMappers;\n                var prevSourceMapper = this.sourceMapper;\n                var prevColumn = this.emitState.column;\n                var prevLine = this.emitState.line;\n                var temp = this.setContainer(EmitContainer.Module);\n                var svModuleName = this.moduleName;\n                var isExported = hasFlag(moduleDecl.modFlags, ModuleFlags.Exported);\n                this.moduleDeclList[this.moduleDeclList.length] = moduleDecl;\n                var isWholeFile = hasFlag(moduleDecl.modFlags, ModuleFlags.IsWholeFile);\n                this.moduleName = moduleDecl.name.actualText;\n\n                // prologue\n                if (isDynamicMod) {\n                    // create the new outfile for this module\n                    var tsModFileName = stripQuotes(moduleDecl.name.actualText);\n                    var modFilePath = trimModName(tsModFileName) + \".js\";\n                    modFilePath = this.emitOptions.mapOutputFileName(modFilePath, TypeScriptCompiler.mapToJSFileName);\n\n                    if (this.emitOptions.ioHost) {\n                        // Ensure that the slashes are normalized so that the comparison is fair\n                        // REVIEW: Note that modFilePath is normalized to forward slashes in Parser.parse, so the \n                        // first call to switchToForwardSlashes is technically a no-op, but it will prevent us from\n                        // regressing if the parser changes\n                        if (switchToForwardSlashes(modFilePath) != switchToForwardSlashes(this.emittingFileName)) {\n                            this.emittingFileName = modFilePath;\n                            var useUTF8InOutputfile = moduleDecl.containsUnicodeChar || (this.emitOptions.emitComments && moduleDecl.containsUnicodeCharInComment);\n                            this.outfile = this.createFile(this.emittingFileName, useUTF8InOutputfile);\n                            if (prevSourceMapper != null) {\n                                this.allSourceMappers = [];\n                                var sourceMappingFile = this.createFile(this.emittingFileName + SourceMapper.MapFileExtension, false);\n                                this.setSourceMappings(new TypeScript.SourceMapper(tsModFileName, this.emittingFileName, this.outfile, sourceMappingFile, this.errorReporter));\n                                this.emitState.column = 0;\n                                this.emitState.line = 0;\n                            }\n                        } else {\n                            CompilerDiagnostics.assert(this.emitOptions.outputMany, \"Cannot have dynamic modules compiling into single file\");\n                        }\n                    }\n\n                    this.setContainer(EmitContainer.DynamicModule); // discard the previous 'Module' container\n\n                    this.recordSourceMappingStart(moduleDecl);\n                    if (moduleGenTarget == ModuleGenTarget.Asynchronous) { // AMD\n                        var dependencyList = \"[\\\"require\\\", \\\"exports\\\"\";\n                        var importList = \"require, exports\";\n                        var importStatement: ImportDeclaration = null;\n\n                        // all dependencies are quoted\n                        for (var i = 0; i < (<ModuleType>moduleDecl.mod).importedModules.length; i++) {\n                            importStatement = (<ModuleType>moduleDecl.mod).importedModules[i]\n\n                            // if the imported module is only used in a type position, do not add it as a requirement\n                            if (importStatement.id.sym &&\n                                !(<TypeSymbol>importStatement.id.sym).onlyReferencedAsTypeRef) {\n                                if (i <= (<ModuleType>moduleDecl.mod).importedModules.length - 1) {\n                                    dependencyList += \", \";\n                                    importList += \", \";\n                                }\n\n                                importList += \"__\" + importStatement.id.actualText + \"__\";\n                                dependencyList += importStatement.firstAliasedModToString();\n                            }\n                        }\n\n                        // emit any potential amd dependencies\n                        for (var i = 0; i < moduleDecl.amdDependencies.length; i++) {\n                            dependencyList += \", \\\"\" + moduleDecl.amdDependencies[i] + \"\\\"\";\n                        }\n\n                        dependencyList += \"]\";\n\n                        this.writeLineToOutput(\"define(\" + dependencyList + \",\" + \" function(\" + importList + \") {\");\n                    }\n                    else { // Node\n\n                    }\n                }\n                else {\n\n                    if (!isExported) {\n                        this.recordSourceMappingStart(moduleDecl);\n                        this.writeToOutput(\"var \");\n                        this.recordSourceMappingStart(moduleDecl.name);\n                        this.writeToOutput(this.moduleName);\n                        this.recordSourceMappingEnd(moduleDecl.name);\n                        this.writeLineToOutput(\";\");\n                        this.recordSourceMappingEnd(moduleDecl);\n                        this.emitIndent();\n                    }\n\n                    this.writeToOutput(\"(\");\n                    this.recordSourceMappingStart(moduleDecl);\n                    this.writeToOutput(\"function (\");\n                    this.recordSourceMappingStart(moduleDecl.name);\n                    this.writeToOutput(this.moduleName);\n                    this.recordSourceMappingEnd(moduleDecl.name);\n                    this.writeLineToOutput(\") {\");\n                }\n\n                if (!isWholeFile) {\n                    this.recordSourceMappingNameStart(this.moduleName);\n                }\n\n                // body - don't indent for Node\n                if (!isDynamicMod || moduleGenTarget == ModuleGenTarget.Asynchronous) {\n                    this.indenter.increaseIndent();\n                }\n\n                if (moduleDecl.modFlags & ModuleFlags.MustCaptureThis) {\n                    this.writeCaptureThisStatement(moduleDecl);\n                }\n\n                this.emitJavascriptList(moduleDecl.members, null, TokenID.Semicolon, true, false, false);\n                if (!isDynamicMod || moduleGenTarget == ModuleGenTarget.Asynchronous) {\n                    this.indenter.decreaseIndent();\n                }\n                this.emitIndent();\n\n                // epilogue\n                if (isDynamicMod) {\n                    if (moduleGenTarget == ModuleGenTarget.Asynchronous) { // AMD\n                        this.writeLineToOutput(\"})\");\n                    }\n                    else { // Node\n                    }\n                    if (!isWholeFile) {\n                        this.recordSourceMappingNameEnd();\n                    }\n                    this.recordSourceMappingEnd(moduleDecl);\n\n                    // close the module outfile, and restore the old one\n                    if (this.outfile != prevOutFile) {\n                        this.Close();\n                        if (prevSourceMapper != null) {\n                            this.allSourceMappers = prevAllSourceMappers;\n                            this.sourceMapper = prevSourceMapper;\n                            this.emitState.column = prevColumn;\n                            this.emitState.line = prevLine;\n                        }\n                        this.outfile = prevOutFile;\n                        this.emittingFileName = prevOutFileName;\n                    }\n                }\n                else {\n                    var containingMod: ModuleDeclaration = null;\n                    if (moduleDecl.type && moduleDecl.type.symbol.container && moduleDecl.type.symbol.container.declAST) {\n                        containingMod = <ModuleDeclaration>moduleDecl.type.symbol.container.declAST;\n                    }\n                    var parentIsDynamic = containingMod && hasFlag(containingMod.modFlags, ModuleFlags.IsDynamic);\n\n                    this.recordSourceMappingStart(moduleDecl.endingToken);\n                    if (temp == EmitContainer.Prog && isExported) {\n                        this.writeToOutput(\"}\");\n                        if (!isWholeFile) {\n                            this.recordSourceMappingNameEnd();\n                        }\n                        this.recordSourceMappingEnd(moduleDecl.endingToken);\n                        this.writeToOutput(\")(this.\" + this.moduleName + \" || (this.\" + this.moduleName + \" = {}));\");\n                    }\n                    else if (isExported || temp == EmitContainer.Prog) {\n                        var dotMod = svModuleName != \"\" ? (parentIsDynamic ? \"exports\" : svModuleName) + \".\" : svModuleName;\n                        this.writeToOutput(\"}\");\n                        if (!isWholeFile) {\n                            this.recordSourceMappingNameEnd();\n                        }\n                        this.recordSourceMappingEnd(moduleDecl.endingToken);\n                        this.writeToOutput(\")(\" + dotMod + this.moduleName + \" || (\" + dotMod + this.moduleName + \" = {}));\");\n                    }\n                    else if (!isExported && temp != EmitContainer.Prog) {\n                        this.writeToOutput(\"}\");\n                        if (!isWholeFile) {\n                            this.recordSourceMappingNameEnd();\n                        }\n                        this.recordSourceMappingEnd(moduleDecl.endingToken);\n                        this.writeToOutput(\")(\" + this.moduleName + \" || (\" + this.moduleName + \" = {}));\");\n                    }\n                    else {\n                        this.writeToOutput(\"}\");\n                        if (!isWholeFile) {\n                            this.recordSourceMappingNameEnd();\n                        }\n                        this.recordSourceMappingEnd(moduleDecl.endingToken);\n                        this.writeToOutput(\")();\");\n                    }\n                    this.recordSourceMappingEnd(moduleDecl);\n                    this.writeLineToOutput(\"\");\n                    if (temp != EmitContainer.Prog && isExported) {\n                        this.emitIndent();\n                        this.recordSourceMappingStart(moduleDecl);\n                        if (parentIsDynamic) {\n                            this.writeLineToOutput(\"var \" + this.moduleName + \" = exports.\" + this.moduleName + \";\");\n                        } else {\n                            this.writeLineToOutput(\"var \" + this.moduleName + \" = \" + svModuleName + \".\" + this.moduleName + \";\");\n                        }\n                        this.recordSourceMappingEnd(moduleDecl);\n                    }\n                }\n\n                this.setContainer(temp);\n                this.moduleName = svModuleName;\n                this.moduleDeclList.length--;\n            }\n        }\n\n        public emitIndex(operand1: AST, operand2: AST) {\n            var temp = this.setInObjectLiteral(false);\n            this.emitJavascript(operand1, TokenID.Tilde, false);\n            this.writeToOutput(\"[\");\n            this.emitJavascriptList(operand2, \", \", TokenID.Comma, false, false, false);\n            this.writeToOutput(\"]\");\n            this.setInObjectLiteral(temp);\n        }\n\n        public emitStringLiteral(text: string) {\n            // should preserve escape etc.\n            // TODO: simplify object literal simple name\n            this.writeToOutput(text);\n        }\n\n        public emitJavascriptFunction(funcDecl: FuncDecl) {\n            if (hasFlag(funcDecl.fncFlags, FncFlags.Signature) || funcDecl.isOverload) {\n                return;\n            }\n            var temp: number;\n            var tempFnc = this.thisFnc;\n            this.thisFnc = funcDecl;\n\n            if (funcDecl.isConstructor) {\n                temp = this.setContainer(EmitContainer.Constructor);\n            }\n            else {\n                temp = this.setContainer(EmitContainer.Function);\n            }\n\n            var bases: ASTList = null;\n            var hasSelfRef = false;\n            var funcName = funcDecl.getNameText();\n\n            if ((this.emitState.inObjectLiteral || !funcDecl.isAccessor()) &&\n                ((temp != EmitContainer.Constructor) ||\n                ((funcDecl.fncFlags & FncFlags.Method) == FncFlags.None))) {\n                var tempLit = this.setInObjectLiteral(false);\n                if (this.thisClassNode) {\n                    bases = this.thisClassNode.extendsList;\n                }\n                hasSelfRef = Emitter.shouldCaptureThis(funcDecl);\n                this.recordSourceMappingStart(funcDecl);\n                if (hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported) && funcDecl.type.symbol.container == this.checker.gloMod && !funcDecl.isConstructor) {\n                    this.writeToOutput(\"this.\" + funcName + \" = \");\n                    this.emitInnerFunction(funcDecl, false, false, bases, hasSelfRef, this.thisClassNode);\n                }\n                else {\n                    this.emitInnerFunction(funcDecl, (funcDecl.name && !funcDecl.name.isMissing()), false, bases, hasSelfRef, this.thisClassNode);\n                }\n                this.setInObjectLiteral(tempLit);\n            }\n            this.setContainer(temp);\n            this.thisFnc = tempFnc;\n\n            if (hasFlag(funcDecl.fncFlags, FncFlags.Definition)) {\n                if (hasFlag(funcDecl.fncFlags, FncFlags.Static)) {\n                    if (this.thisClassNode) {\n                        if (funcDecl.isAccessor()) {\n                            this.emitPropertyAccessor(funcDecl, this.thisClassNode.name.actualText, false);\n                        }\n                        else {\n                            this.emitIndent();\n                            this.recordSourceMappingStart(funcDecl);\n                            this.writeLineToOutput(this.thisClassNode.name.actualText + \".\" + funcName +\n                                          \" = \" + funcName + \";\");\n                            this.recordSourceMappingEnd(funcDecl);\n                        }\n                    }\n                }\n                else if ((this.emitState.container == EmitContainer.Module || this.emitState.container == EmitContainer.DynamicModule) && hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported)) {\n                    this.emitIndent();\n                    var modName = this.emitState.container == EmitContainer.Module ? this.moduleName : \"exports\";\n                    this.recordSourceMappingStart(funcDecl);\n                    this.writeLineToOutput(modName + \".\" + funcName +\n                                      \" = \" + funcName + \";\");\n                    this.recordSourceMappingEnd(funcDecl);\n                }\n            }\n        }\n\n        public emitAmbientVarDecl(varDecl: VarDecl) {\n            if (varDecl.init) {\n                this.emitParensAndCommentsInPlace(varDecl, true);\n                this.recordSourceMappingStart(varDecl);\n                this.recordSourceMappingStart(varDecl.id);\n                this.writeToOutput(varDecl.id.actualText);\n                this.recordSourceMappingEnd(varDecl.id);\n                this.writeToOutput(\" = \");\n                this.emitJavascript(varDecl.init, TokenID.Comma, false);\n                this.recordSourceMappingEnd(varDecl);\n                this.writeToOutput(\";\");\n                this.emitParensAndCommentsInPlace(varDecl, false);\n            }\n        }\n\n        private varListCount(): number {\n            return this.varListCountStack[this.varListCountStack.length - 1];\n        }\n\n        // Emits \"var \" if it is allowed\n        private emitVarDeclVar() {\n            // If it is var list of form var a, b, c = emit it only if count > 0 - which will be when emitting first var\n            // If it is var list of form  var a = varList count will be 0\n            if (this.varListCount() >= 0) {\n                this.writeToOutput(\"var \");\n                this.setInVarBlock(-this.varListCount());\n            }\n            return true;\n        }\n\n        private onEmitVar() {\n            if (this.varListCount() > 0) {\n                this.setInVarBlock(this.varListCount() - 1);\n            }\n            else if (this.varListCount() < 0) {\n                this.setInVarBlock(this.varListCount() + 1);\n            }\n        }\n\n        public emitJavascriptVarDecl(varDecl: VarDecl, tokenId: TokenID) {\n            if ((varDecl.varFlags & VarFlags.Ambient) == VarFlags.Ambient) {\n                this.emitAmbientVarDecl(varDecl);\n                this.onEmitVar();\n            }\n            else {\n                var sym = varDecl.sym;\n                var hasInitializer = (varDecl.init != null);\n                this.emitParensAndCommentsInPlace(varDecl, true);\n                this.recordSourceMappingStart(varDecl);\n                if (sym && sym.isMember() && sym.container &&\n                    (sym.container.kind() == SymbolKind.Type)) {\n                    var type = (<TypeSymbol>sym.container).type;\n                    if (type.isClass() && (!hasFlag(sym.flags, SymbolFlags.ModuleMember))) {\n                        // class\n                        if (this.emitState.container != EmitContainer.Args) {\n                            if (hasFlag(sym.flags, SymbolFlags.Static)) {\n                                this.writeToOutput(sym.container.name + \".\");\n                            }\n                            else {\n                                this.writeToOutput(\"this.\");\n                            }\n                        }\n                    }\n                    else if (type.hasImplementation()) {\n                        // module\n                        if (!hasFlag(sym.flags, SymbolFlags.Exported) && (sym.container == this.checker.gloMod || !hasFlag(sym.flags, SymbolFlags.Property))) {\n                            this.emitVarDeclVar();\n                        }\n                        else if (hasFlag(varDecl.varFlags, VarFlags.LocalStatic)) {\n                            this.writeToOutput(\".\");\n                        }\n                        else {\n                            if (this.emitState.container == EmitContainer.DynamicModule) {\n                                this.writeToOutput(\"exports.\");\n                            }\n                            else {\n                                this.writeToOutput(this.moduleName + \".\");\n                            }\n                        }\n                    }\n                    else {\n                        // function, constructor, method etc.\n                        if (tokenId != TokenID.OpenParen) {\n                            if (hasFlag(sym.flags, SymbolFlags.Exported) && sym.container == this.checker.gloMod) {\n                                this.writeToOutput(\"this.\");\n                            }\n                            else {\n                                this.emitVarDeclVar();\n                            }\n                        }\n                    }\n                }\n                else {\n                    if (tokenId != TokenID.OpenParen) {\n                        this.emitVarDeclVar();\n                    }\n                }\n                this.recordSourceMappingStart(varDecl.id);\n                this.writeToOutput(varDecl.id.actualText);\n                this.recordSourceMappingEnd(varDecl.id);\n                if (hasInitializer) {\n                    this.writeToOutputTrimmable(\" = \");\n\n                    // Ensure we have a fresh var list count when recursing into the variable \n                    // initializer.  We don't want our current list of variables to affect how we\n                    // emit nested variable lists.\n                    this.varListCountStack.push(0);\n                    this.emitJavascript(varDecl.init, TokenID.Comma, false);\n                    this.varListCountStack.pop();\n                }\n                this.onEmitVar();\n                if ((tokenId != TokenID.OpenParen)) {\n                    if (this.varListCount() < 0) {\n                        this.writeToOutput(\", \");\n                    } else if (tokenId != TokenID.For) {\n                        this.writeToOutputTrimmable(\";\");\n                    }\n                }\n                this.recordSourceMappingEnd(varDecl);\n                this.emitParensAndCommentsInPlace(varDecl, false);\n            }\n        }\n\n        public declEnclosed(moduleDecl: ModuleDeclaration): bool {\n            if (moduleDecl == null) {\n                return true;\n            }\n            for (var i = 0, len = this.moduleDeclList.length; i < len; i++) {\n                if (this.moduleDeclList[i] == moduleDecl) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public emitJavascriptName(name: Identifier, addThis: bool) {\n            var sym = name.sym;\n            this.emitParensAndCommentsInPlace(name, true);\n            this.recordSourceMappingStart(name);\n            if (!name.isMissing()) {\n                if (addThis && (this.emitState.container != EmitContainer.Args) && sym) {\n                    // TODO: flag global module with marker other than string name\n                    if (sym.container && (sym.container.name != globalId)) {\n                        if (hasFlag(sym.flags, SymbolFlags.Static) && (hasFlag(sym.flags, SymbolFlags.Property))) {\n                            if (sym.declModule && hasFlag(sym.declModule.modFlags, ModuleFlags.IsDynamic)) {\n                                this.writeToOutput(\"exports.\");\n                            }\n                            else {\n                                this.writeToOutput(sym.container.name + \".\");\n                            }\n                        }\n                        else if (sym.kind() == SymbolKind.Field) {\n                            var fieldSym = <FieldSymbol>sym;\n                            if (hasFlag(fieldSym.flags, SymbolFlags.ModuleMember)) {\n                                if ((sym.container != this.checker.gloMod) && ((hasFlag(sym.flags, SymbolFlags.Property)) || hasFlag(sym.flags, SymbolFlags.Exported))) {\n                                    if (hasFlag(sym.declModule.modFlags, ModuleFlags.IsDynamic)) {\n                                        this.writeToOutput(\"exports.\");\n                                    }\n                                    else {\n                                        this.writeToOutput(sym.container.name + \".\");\n                                    }\n                                }\n                            }\n                            else {\n                                if (sym.isInstanceProperty()) {\n                                    this.emitThis();\n                                    this.writeToOutput(\".\");\n                                }\n                            }\n                        }\n                        else if (sym.kind() == SymbolKind.Type) {\n                            if (sym.isInstanceProperty()) {\n                                var typeSym = <TypeSymbol>sym;\n                                var type = typeSym.type;\n                                if (type.call && !hasFlag(sym.flags, SymbolFlags.ModuleMember)) {\n                                    this.emitThis();\n                                    this.writeToOutput(\".\");\n                                }\n                            }\n                            else if ((sym.unitIndex != this.checker.locationInfo.unitIndex) || (!this.declEnclosed(sym.declModule))) {\n                                this.writeToOutput(sym.container.name + \".\")\n                            }\n                        }\n                    }\n                    else if (sym.container == this.checker.gloMod &&\n                                hasFlag(sym.flags, SymbolFlags.Exported) &&\n                                !hasFlag(sym.flags, SymbolFlags.Ambient) &&\n                                // check that it's a not a member of an ambient module...\n                                !((sym.isType() || sym.isMember()) &&\n                                    sym.declModule &&\n                                    hasFlag(sym.declModule.modFlags, ModuleFlags.Ambient)) &&\n                                this.emitState.container == EmitContainer.Prog &&\n                                sym.declAST.nodeType != NodeType.FuncDecl) {\n                        this.writeToOutput(\"this.\");\n                    }\n                }\n\n                // If it's a dynamic module, we need to print the \"require\" invocation\n                if (sym &&\n                    sym.declAST &&\n                    sym.declAST.nodeType == NodeType.ModuleDeclaration &&\n                    (hasFlag((<ModuleDeclaration>sym.declAST).modFlags, ModuleFlags.IsDynamic))) {\n                    var moduleDecl: ModuleDeclaration = <ModuleDeclaration>sym.declAST;\n\n                    if (moduleGenTarget == ModuleGenTarget.Asynchronous) {\n                        this.writeLineToOutput(\"__\" + this.modAliasId + \"__;\");\n                    }\n                    else {\n                        var modPath = name.actualText;//(<ModuleDecl>moduleDecl.mod.symbol.declAST).name.actualText;\n                        var isAmbient = moduleDecl.mod.symbol.declAST && hasFlag((<ModuleDeclaration>moduleDecl.mod.symbol.declAST).modFlags, ModuleFlags.Ambient);\n                        modPath = isAmbient ? modPath : this.firstModAlias ? this.firstModAlias : quoteBaseName(modPath);\n                        modPath = isAmbient ? modPath : (!isRelative(stripQuotes(modPath)) ? quoteStr(\"./\" + stripQuotes(modPath)) : modPath);\n                        this.writeToOutput(\"require(\" + modPath + \")\");\n                    }\n                }\n                else {\n                    this.writeToOutput(name.actualText);\n                }\n            }\n            this.recordSourceMappingEnd(name);\n            this.emitParensAndCommentsInPlace(name, false);\n        }\n\n        public emitJavascriptStatements(stmts: AST, emitEmptyBod: bool) {\n            if (stmts) {\n                if (stmts.nodeType != NodeType.Block) {\n                    var hasContents = (stmts && (stmts.nodeType != NodeType.List || ((<ASTList>stmts).members.length > 0)));\n                    if (emitEmptyBod || hasContents) {\n                        var hasOnlyBlockStatement = ((stmts.nodeType == NodeType.Block) ||\n                            ((stmts.nodeType == NodeType.List) && ((<ASTList>stmts).members.length == 1) && ((<ASTList>stmts).members[0].nodeType == NodeType.Block)));\n\n                        this.recordSourceMappingStart(stmts);\n                        if (!hasOnlyBlockStatement) {\n                            this.writeLineToOutput(\" {\");\n                            this.indenter.increaseIndent();\n                        }\n                        this.emitJavascriptList(stmts, null, TokenID.Semicolon, true, false, false);\n                        if (!hasOnlyBlockStatement) {\n                            this.writeLineToOutput(\"\");\n                            this.indenter.decreaseIndent();\n                            this.emitIndent();\n                            this.writeToOutput(\"}\");\n                        }\n                        this.recordSourceMappingEnd(stmts);\n                    }\n                }\n                else {\n                    this.emitJavascript(stmts, TokenID.Semicolon, true);\n                }\n            }\n            else if (emitEmptyBod) {\n                this.writeToOutput(\"{ }\");\n            }\n        }\n\n        public emitBareJavascriptStatements(stmts: AST, emitClassPropertiesAfterSuperCall: bool = false) {\n            // just the statements without enclosing curly braces\n            if (stmts.nodeType != NodeType.Block) {\n                if (stmts.nodeType == NodeType.List) {\n                    var stmtList = <ASTList>stmts;\n                    if ((stmtList.members.length == 2) &&\n                        (stmtList.members[0].nodeType == NodeType.Block) &&\n                        (stmtList.members[1].nodeType == NodeType.EndCode)) {\n                        this.emitJavascript(stmtList.members[0], TokenID.Semicolon, true);\n                        this.writeLineToOutput(\"\");\n                    }\n                    else {\n                        this.emitJavascriptList(stmts, null, TokenID.Semicolon, true, false, emitClassPropertiesAfterSuperCall);\n                    }\n                }\n                else {\n                    this.emitJavascript(stmts, TokenID.Semicolon, true);\n                }\n            }\n            else {\n                this.emitJavascript(stmts, TokenID.Semicolon, true);\n            }\n        }\n\n        public recordSourceMappingNameStart(name: string) {\n            if (this.sourceMapper) {\n                var finalName = name;\n                if (!name) {\n                    finalName = \"\";\n                } else if (this.sourceMapper.currentNameIndex.length > 0) {\n                    finalName = this.sourceMapper.names[this.sourceMapper.currentNameIndex.length - 1] + \".\" + name;\n                }\n\n                // We are currently not looking for duplicate but that is possible.\n                this.sourceMapper.names.push(finalName);\n                this.sourceMapper.currentNameIndex.push(this.sourceMapper.names.length - 1);\n            }\n        }\n\n        public recordSourceMappingNameEnd() {\n            if (this.sourceMapper) {\n                this.sourceMapper.currentNameIndex.pop();\n            }\n        }\n\n        public recordSourceMappingStart(ast: ASTSpan) {\n            if (this.sourceMapper && isValidAstNode(ast)) {\n                var lineCol = { line: -1, col: -1 };\n                var sourceMapping = new SourceMapping();\n                sourceMapping.start.emittedColumn = this.emitState.column;\n                sourceMapping.start.emittedLine = this.emitState.line;\n                // REVIEW: check time consumed by this binary search (about two per leaf statement)\n                getSourceLineColFromMap(lineCol, ast.minChar, this.checker.locationInfo.lineMap);\n                sourceMapping.start.sourceColumn = lineCol.col;\n                sourceMapping.start.sourceLine = lineCol.line;\n                getSourceLineColFromMap(lineCol, ast.limChar, this.checker.locationInfo.lineMap);\n                sourceMapping.end.sourceColumn = lineCol.col;\n                sourceMapping.end.sourceLine = lineCol.line;\n                if (this.sourceMapper.currentNameIndex.length > 0) {\n                    sourceMapping.nameIndex = this.sourceMapper.currentNameIndex[this.sourceMapper.currentNameIndex.length - 1];\n                }\n                // Set parent and child relationship\n                var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];\n                siblings.push(sourceMapping);\n                this.sourceMapper.currentMappings.push(sourceMapping.childMappings);\n            }\n        }\n\n        public recordSourceMappingEnd(ast: ASTSpan) {\n            if (this.sourceMapper && isValidAstNode(ast)) {\n                // Pop source mapping childs\n                this.sourceMapper.currentMappings.pop();\n\n                // Get the last source mapping from sibling list = which is the one we are recording end for\n                var siblings = this.sourceMapper.currentMappings[this.sourceMapper.currentMappings.length - 1];\n                var sourceMapping = siblings[siblings.length - 1];\n\n                sourceMapping.end.emittedColumn = this.emitState.column;\n                sourceMapping.end.emittedLine = this.emitState.line;\n            }\n        }\n\n        public Close() {\n            if (this.sourceMapper != null) {\n                SourceMapper.EmitSourceMapping(this.allSourceMappers);\n            }\n            try {\n                // Closing files could result in exceptions, report them if they occur\n                this.outfile.Close();\n            } catch (ex) {\n                this.errorReporter.emitterError(null, ex.message);\n            }\n        }\n\n        public emitJavascriptList(ast: AST, delimiter: string, tokenId: TokenID, startLine: bool, onlyStatics: bool, emitClassPropertiesAfterSuperCall: bool = false, emitPrologue? = false, requiresExtendsBlock?: bool) {\n            if (ast == null) {\n                return;\n            }\n            else if (ast.nodeType != NodeType.List) {\n                this.emitPrologue(emitPrologue);\n                this.emitJavascript(ast, tokenId, startLine);\n            }\n            else {\n                var list = <ASTList>ast;\n                if (list.members.length == 0) {\n                    return;\n                }\n\n                this.emitParensAndCommentsInPlace(ast, true);\n                var len = list.members.length;\n                for (var i = 0; i < len; i++) {\n                    if (emitPrologue) {\n                        // If the list has Strict mode flags, emit prologue after first statement\n                        // otherwise emit before first statement\n                        if (i == 1 || !hasFlag(list.flags, ASTFlags.StrictMode)) {\n                            this.emitPrologue(requiresExtendsBlock);\n                            emitPrologue = false;\n                        }\n                    }\n\n                    // In some circumstances, class property initializers must be emitted immediately after the 'super' constructor\n                    // call which, in these cases, must be the first statement in the constructor body\n                    if (i == 1 && emitClassPropertiesAfterSuperCall) {\n\n                        // emit any parameter properties first\n                        var constructorDecl = (<ClassDeclaration>this.thisClassNode).constructorDecl;\n\n                        if (constructorDecl && constructorDecl.arguments) {\n                            var argsLen = constructorDecl.arguments.members.length;\n                            for (var iArg = 0; iArg < argsLen; iArg++) {\n                                var arg = <BoundDecl>constructorDecl.arguments.members[iArg];\n                                if ((arg.varFlags & VarFlags.Property) != VarFlags.None) {\n                                    this.emitIndent();\n                                    this.recordSourceMappingStart(arg);\n                                    this.recordSourceMappingStart(arg.id);\n                                    this.writeToOutput(\"this.\" + arg.id.actualText);\n                                    this.recordSourceMappingEnd(arg.id);\n                                    this.writeToOutput(\" = \");\n                                    this.recordSourceMappingStart(arg.id);\n                                    this.writeToOutput(arg.id.actualText);\n                                    this.recordSourceMappingEnd(arg.id);\n                                    this.writeLineToOutput(\";\");\n                                    this.recordSourceMappingEnd(arg);\n                                }\n                            }\n                        }\n\n                        var nProps = (<ASTList>this.thisClassNode.members).members.length;\n\n                        for (var iMember = 0; iMember < nProps; iMember++) {\n                            if ((<ASTList>this.thisClassNode.members).members[iMember].nodeType == NodeType.VarDecl) {\n                                var varDecl = <VarDecl>(<ASTList>this.thisClassNode.members).members[iMember];\n                                if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n                                    this.emitIndent();\n                                    this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n                                    this.writeLineToOutput(\"\");\n                                }\n                            }\n                        }\n                    }\n\n                    var emitNode = list.members[i];\n\n                    var isStaticDecl =\n                                (emitNode.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>emitNode).fncFlags, FncFlags.Static)) ||\n                                (emitNode.nodeType == NodeType.VarDecl && hasFlag((<VarDecl>emitNode).varFlags, VarFlags.Static))\n\n                    if (onlyStatics ? !isStaticDecl : isStaticDecl) {\n                        continue;\n                    }\n                    this.emitJavascript(emitNode, tokenId, startLine);\n\n                    if (delimiter && (i < (len - 1))) {\n                        if (startLine) {\n                            this.writeLineToOutput(delimiter);\n                        }\n                        else {\n                            this.writeToOutput(delimiter);\n                        }\n                    }\n                    else if (startLine &&\n                             (emitNode.nodeType != NodeType.ModuleDeclaration) &&\n                             (emitNode.nodeType != NodeType.InterfaceDeclaration) &&\n                             (!((emitNode.nodeType == NodeType.VarDecl) &&\n                                ((((<VarDecl>emitNode).varFlags) & VarFlags.Ambient) == VarFlags.Ambient) &&\n                                (((<VarDecl>emitNode).init) == null)) && this.varListCount() >= 0) &&\n                             (emitNode.nodeType != NodeType.Block || (<Block>emitNode).isStatementBlock) &&\n                             (emitNode.nodeType != NodeType.EndCode) &&\n                             (emitNode.nodeType != NodeType.FuncDecl)) {\n                        this.writeLineToOutput(\"\");\n                    }\n                }\n                this.emitParensAndCommentsInPlace(ast, false);\n            }\n        }\n\n        // tokenId is the id the preceding token\n        public emitJavascript(ast: AST, tokenId: TokenID, startLine: bool) {\n            if (ast == null) {\n                return;\n            }\n\n            // REVIEW: simplify rules for indenting\n            if (startLine && (this.indenter.indentAmt > 0) && (ast.nodeType != NodeType.List) &&\n                (ast.nodeType != NodeType.Block)) {\n                if ((ast.nodeType != NodeType.InterfaceDeclaration) &&\n                    (!((ast.nodeType == NodeType.VarDecl) &&\n                       ((((<VarDecl>ast).varFlags) & VarFlags.Ambient) == VarFlags.Ambient) &&\n                       (((<VarDecl>ast).init) == null)) && this.varListCount() >= 0) &&\n                    (ast.nodeType != NodeType.EndCode) &&\n                    ((ast.nodeType != NodeType.FuncDecl) ||\n                     (this.emitState.container != EmitContainer.Constructor))) {\n                    this.emitIndent();\n                }\n            }\n\n            ast.emit(this, tokenId, startLine);\n\n            if ((tokenId == TokenID.Semicolon) && (ast.nodeType < NodeType.GeneralNode)) {\n                this.writeToOutput(\";\");\n            }\n        }\n\n        public emitPropertyAccessor(funcDecl: FuncDecl, className: string, isProto: bool) {\n            if (!(<FieldSymbol>funcDecl.accessorSymbol).hasBeenEmitted) {\n                var accessorSymbol = <FieldSymbol>funcDecl.accessorSymbol;\n                this.emitIndent();\n                this.recordSourceMappingStart(funcDecl);\n                this.writeLineToOutput(\"Object.defineProperty(\" + className + (isProto ? \".prototype, \\\"\" : \", \\\"\") + funcDecl.name.actualText + \"\\\"\" + \", {\");\n                this.indenter.increaseIndent();\n\n                if (accessorSymbol.getter) {\n                    var getter: FuncDecl = <FuncDecl>accessorSymbol.getter.declAST;\n\n                    this.emitIndent();\n                    this.recordSourceMappingStart(getter);\n                    this.writeToOutput(\"get: \");\n                    this.emitInnerFunction(getter, false, isProto, null, Emitter.shouldCaptureThis(getter), null);\n                    this.writeLineToOutput(\",\");\n                }\n\n                if (accessorSymbol.setter) {\n                    var setter: FuncDecl = <FuncDecl>accessorSymbol.setter.declAST;\n\n                    this.emitIndent();\n                    this.recordSourceMappingStart(setter);\n                    this.writeToOutput(\"set: \");\n                    this.emitInnerFunction(setter, false, isProto, null, Emitter.shouldCaptureThis(setter), null);\n                    this.writeLineToOutput(\",\");\n                }\n\n                this.emitIndent();\n                this.writeLineToOutput(\"enumerable: true,\");\n                this.emitIndent();\n                this.writeLineToOutput(\"configurable: true\");\n                this.indenter.decreaseIndent();\n                this.emitIndent();\n                this.writeLineToOutput(\"});\");\n                this.recordSourceMappingEnd(funcDecl);\n\n                accessorSymbol.hasBeenEmitted = true;\n            }\n        }\n\n        public emitPrototypeMember(member: AST, className: string) {\n            if (member.nodeType == NodeType.FuncDecl) {\n                var funcDecl = <FuncDecl>member;\n                if (funcDecl.isAccessor()) {\n                    this.emitPropertyAccessor(funcDecl, className, true);\n                }\n                else {\n                    this.emitIndent();\n                    this.recordSourceMappingStart(funcDecl);\n                    this.writeToOutput(className + \".prototype.\" + funcDecl.getNameText() + \" = \");\n                    this.emitInnerFunction(funcDecl, false, true, null, Emitter.shouldCaptureThis(funcDecl), null);\n                    this.writeLineToOutput(\";\");\n                }\n            }\n            else if (member.nodeType == NodeType.VarDecl) {\n                var varDecl = <VarDecl>member;\n\n                if (varDecl.init) {\n                    this.emitIndent();\n                    this.recordSourceMappingStart(varDecl);\n                    this.recordSourceMappingStart(varDecl.id);\n                    this.writeToOutput(className + \".prototype.\" + varDecl.id.actualText);\n                    this.recordSourceMappingEnd(varDecl.id);\n                    this.writeToOutput(\" = \");\n                    this.emitJavascript(varDecl.init, TokenID.Equals, false);\n                    this.recordSourceMappingEnd(varDecl);\n                    this.writeLineToOutput(\";\");\n                }\n            }\n        }\n\n        public emitAddBaseMethods(className: string, base: Type, classDecl: TypeDeclaration): void {\n            if (base.members) {\n                var baseSymbol = base.symbol;\n                var baseName = baseSymbol.name;\n                if (baseSymbol.declModule != classDecl.type.symbol.declModule) {\n                    baseName = baseSymbol.fullName();\n                }\n                base.members.allMembers.map(function(key, s, c) {\n                    var sym = <Symbol>s;\n                    if ((sym.kind() == SymbolKind.Type) && (<TypeSymbol>sym).type.call) {\n                        this.recordSourceMappingStart(sym.declAST);\n                        this.writeLineToOutput(className + \".prototype.\" + sym.name + \" = \" +\n                                          baseName + \".prototype.\" + sym.name + \";\");\n                        this.recordSourceMappingEnd(sym.declAST);\n                    }\n                }, null);\n            }\n            if (base.extendsList) {\n                for (var i = 0, len = base.extendsList.length; i < len; i++) {\n                    this.emitAddBaseMethods(className, base.extendsList[i], classDecl);\n                }\n            }\n        }\n\n        public emitJavascriptClass(classDecl: ClassDeclaration) {\n            if (!hasFlag(classDecl.varFlags, VarFlags.Ambient)) {\n                var svClassNode = this.thisClassNode;\n                var i = 0;\n                this.thisClassNode = classDecl;\n                var className = classDecl.name.actualText;\n                this.emitParensAndCommentsInPlace(classDecl, true);\n                var temp = this.setContainer(EmitContainer.Class);\n\n                this.recordSourceMappingStart(classDecl);\n                if (hasFlag(classDecl.varFlags, VarFlags.Exported) && classDecl.type.symbol.container == this.checker.gloMod) {\n                    this.writeToOutput(\"this.\" + className);\n                }\n                else {\n                    this.writeToOutput(\"var \" + className);\n                }\n\n                //if (hasFlag(classDecl.varFlags, VarFlags.Exported) && (temp == EmitContainer.Module || temp == EmitContainer.DynamicModule)) {\n                //    var modName = temp == EmitContainer.Module ? this.moduleName : \"exports\";\n                //    this.writeToOutput(\" = \" + modName + \".\" + className);\n                //}\n\n                var hasBaseClass = classDecl.extendsList && classDecl.extendsList.members.length;\n                var baseNameDecl: AST = null;\n                var baseName: AST = null;\n\n                if (hasBaseClass) {\n                    this.writeLineToOutput(\" = (function (_super) {\");\n                } else {\n                    this.writeLineToOutput(\" = (function () {\");\n                }\n\n                this.recordSourceMappingNameStart(className);\n                this.indenter.increaseIndent();\n\n                if (hasBaseClass) {\n                    baseNameDecl = classDecl.extendsList.members[0];\n                    baseName = baseNameDecl.nodeType == NodeType.Call ? (<CallExpression>baseNameDecl).target : baseNameDecl;\n                    this.emitIndent();\n                    this.writeLineToOutput(\"__extends(\" + className + \", _super);\");\n                }\n\n                this.emitIndent();\n\n                var constrDecl = classDecl.constructorDecl;\n\n                // output constructor\n                if (constrDecl) {\n                    // declared constructor\n                    this.emitJavascript(classDecl.constructorDecl, TokenID.OpenParen, false);\n\n                }\n                else {\n                    var wroteProps = 0;\n\n                    this.recordSourceMappingStart(classDecl);\n                    // default constructor\n                    this.indenter.increaseIndent();\n                    this.writeToOutput(\"function \" + classDecl.name.actualText + \"() {\");\n                    this.recordSourceMappingNameStart(\"constructor\");\n                    if (hasBaseClass) {\n                        this.writeLineToOutput(\"\");\n                        this.emitIndent();\n                        this.writeLineToOutput(\"_super.apply(this, arguments);\");\n                        wroteProps++;\n                    }\n\n                    if (classDecl.varFlags & VarFlags.MustCaptureThis) {\n                        this.writeCaptureThisStatement(classDecl);\n                    }\n\n                    var members = (<ASTList>this.thisClassNode.members).members\n\n                    // output initialized properties\n                    for (var i = 0; i < members.length; i++) {\n                        if (members[i].nodeType == NodeType.VarDecl) {\n                            var varDecl = <VarDecl>members[i];\n                            if (!hasFlag(varDecl.varFlags, VarFlags.Static) && varDecl.init) {\n                                this.writeLineToOutput(\"\");\n                                this.emitIndent();\n                                this.emitJavascriptVarDecl(varDecl, TokenID.Tilde);\n                                wroteProps++;\n                            }\n                        }\n                    }\n                    if (wroteProps) {\n                        this.writeLineToOutput(\"\");\n                        this.indenter.decreaseIndent();\n                        this.emitIndent();\n                        this.writeLineToOutput(\"}\");\n                    }\n                    else {\n                        this.writeLineToOutput(\" }\");\n                        this.indenter.decreaseIndent();\n                    }\n                    this.recordSourceMappingNameEnd();\n                    this.recordSourceMappingEnd(classDecl);\n                }\n\n                var membersLen = classDecl.members.members.length;\n                for (var j = 0; j < membersLen; j++) {\n\n                    var memberDecl: AST = classDecl.members.members[j];\n\n                    if (memberDecl.nodeType == NodeType.FuncDecl) {\n                        var fn = <FuncDecl>memberDecl;\n\n                        if (hasFlag(fn.fncFlags, FncFlags.Method) && !fn.isSignature()) {\n                            if (!hasFlag(fn.fncFlags, FncFlags.Static)) {\n                                this.emitPrototypeMember(fn, className);\n                            }\n                            else { // static functions\n                                if (fn.isAccessor()) {\n                                    this.emitPropertyAccessor(fn, this.thisClassNode.name.actualText, false);\n                                }\n                                else {\n                                    this.emitIndent();\n                                    this.recordSourceMappingStart(fn)\n                                    this.writeToOutput(classDecl.name.actualText + \".\" + fn.name.actualText + \" = \");\n                                    this.emitInnerFunction(fn, (fn.name && !fn.name.isMissing()), true,\n                                            null, Emitter.shouldCaptureThis(fn), null);\n                                    this.writeLineToOutput(\";\");\n                                }\n                            }\n                        }\n                    }\n                    else if (memberDecl.nodeType == NodeType.VarDecl) {\n                        var varDecl = <VarDecl>memberDecl;\n                        if (hasFlag(varDecl.varFlags, VarFlags.Static)) {\n\n                            if (varDecl.init) {\n                                // EMITREVIEW\n                                this.emitIndent();\n                                this.recordSourceMappingStart(varDecl);\n                                this.writeToOutput(classDecl.name.actualText + \".\" + varDecl.id.actualText + \" = \");\n                                this.emitJavascript(varDecl.init, TokenID.Equals, false);\n                                // EMITREVIEW\n\n                                this.writeLineToOutput(\";\");\n                                this.recordSourceMappingEnd(varDecl);\n                            }\n                        }\n                    }\n                    else {\n                        throw Error(\"We want to catch this\");\n                    }\n                }\n\n                this.emitIndent();\n                this.recordSourceMappingStart(classDecl.endingToken);\n                this.writeLineToOutput(\"return \" + className + \";\");\n                this.recordSourceMappingEnd(classDecl.endingToken);\n                this.indenter.decreaseIndent();\n                this.emitIndent();\n                this.recordSourceMappingStart(classDecl.endingToken);\n                this.writeToOutput(\"}\");\n                this.recordSourceMappingNameEnd();\n                this.recordSourceMappingEnd(classDecl.endingToken);\n                this.recordSourceMappingStart(classDecl);\n                this.writeToOutput(\")(\");\n                if (hasBaseClass)\n                    this.emitJavascript(baseName, TokenID.Tilde, false);\n                this.writeToOutput(\");\");\n                this.recordSourceMappingEnd(classDecl);\n\n                if ((temp == EmitContainer.Module || temp == EmitContainer.DynamicModule) && hasFlag(classDecl.varFlags, VarFlags.Exported)) {\n                    this.writeLineToOutput(\"\");\n                    this.emitIndent();\n                    var modName = temp == EmitContainer.Module ? this.moduleName : \"exports\";\n                    this.recordSourceMappingStart(classDecl);\n                    this.writeToOutput(modName + \".\" + className + \" = \" + className + \";\");\n                    this.recordSourceMappingEnd(classDecl);\n                }\n\n                this.emitIndent();\n                this.recordSourceMappingEnd(classDecl);\n                this.emitParensAndCommentsInPlace(classDecl, false);\n                this.setContainer(temp);\n                this.thisClassNode = svClassNode;\n            }\n        }\n\n        public emitPrologue(reqInherits: bool) {\n            if (!this.prologueEmitted) {\n                if (reqInherits) {\n                    this.prologueEmitted = true;\n                    this.writeLineToOutput(\"var __extends = this.__extends || function (d, b) {\");\n                    this.writeLineToOutput(\"    function __() { this.constructor = d; }\");\n                    this.writeLineToOutput(\"    __.prototype = b.prototype;\");\n                    this.writeLineToOutput(\"    d.prototype = new __();\");\n                    this.writeLineToOutput(\"};\");\n                }\n                if (this.checker.mustCaptureGlobalThis) {\n                    this.prologueEmitted = true;\n                    this.writeLineToOutput(this.captureThisStmtString);\n                }\n            }\n        }\n\n        public emitSuperReference() {\n            this.writeToOutput(\"_super.prototype\");\n        }\n\n        public emitSuperCall(callEx: CallExpression): bool {\n            if (callEx.target.nodeType == NodeType.Dot) {\n                var dotNode = <BinaryExpression>callEx.target;\n                if (dotNode.operand1.nodeType == NodeType.Super) {\n                    this.emitJavascript(dotNode, TokenID.OpenParen, false);\n                    this.writeToOutput(\".call(\");\n                    this.emitThis();\n                    if (callEx.arguments && callEx.arguments.members.length > 0) {\n                        this.writeToOutput(\", \");\n                        this.emitJavascriptList(callEx.arguments, \", \", TokenID.Comma, false, false, false);\n                    }\n                    this.writeToOutput(\")\");\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public emitThis() {\n            if (this.thisFnc && !this.thisFnc.isMethod() && (!this.thisFnc.isConstructor)) {\n                this.writeToOutput(\"_this\");\n            }\n            else {\n                this.writeToOutput(\"this\");\n            }\n        }\n\n        private static shouldCaptureThis(func: FuncDecl): bool {\n            // Super calls use 'this' reference. If super call is in a lambda, 'this' value needs to be captured in the parent.\n            return func.hasSelfReference() || func.hasSuperReferenceInFatArrowFunction();\n        }\n\n        private createFile(fileName: string, useUTF8: bool): ITextWriter {\n            try {\n                return this.emitOptions.ioHost.createFile(fileName, useUTF8);\n            } catch (ex) {\n                this.errorReporter.emitterError(null, ex.message);\n            }\n        }\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export interface ILineCol {\n        line: number;\n        col: number;\n    }\n\n    export class ErrorReporter {\n        public parser: Parser = null;\n        public checker: TypeChecker = null;\n        public lineCol = { line: 0, col: 0 };\n        public emitAsComments = true;\n        public hasErrors = false;\n        public pushToErrorSink = false;\n        public errorSink: string[] = [];\n\n        constructor (public outfile: ITextWriter) { }\n\n        public getCapturedErrors() { return this.errorSink; }\n        public freeCapturedErrors() { this.errorSink = []; }\n        public captureError(emsg: string) { this.errorSink[this.errorSink.length] = emsg; }\n\n        public setErrOut(outerr) {\n            this.outfile = outerr;\n            this.emitAsComments = false;\n        }\n\n        public emitPrefix() {\n            if (this.emitAsComments) {\n                this.outfile.Write(\"// \");\n            }\n            this.outfile.Write(this.checker.locationInfo.filename + \"(\" + this.lineCol.line + \",\" + this.lineCol.col + \"): \");\n        }\n\n        public writePrefix(ast: AST): void {\n            if (ast) {\n                this.setError(ast);\n            }\n            else {\n                this.lineCol.line = 0;\n                this.lineCol.col = 0;\n            }\n            this.emitPrefix();\n        }\n\n        public writePrefixFromSym(symbol: Symbol): void {\n            if (symbol && this.checker.locationInfo.lineMap) {\n                getSourceLineColFromMap(this.lineCol, symbol.location,\n                                        this.checker.locationInfo.lineMap);\n            }\n            else {\n                this.lineCol.line = -1;\n                this.lineCol.col = -1;\n            }\n            this.emitPrefix();\n        }\n\n        public setError(ast: AST) {\n            if (ast) {\n                ast.flags |= ASTFlags.Error;\n                if (this.checker.locationInfo.lineMap) {\n                    getSourceLineColFromMap(this.lineCol, ast.minChar, this.checker.locationInfo.lineMap);\n                }\n            }\n        }\n\n        public reportError(ast: AST, message: string) {\n            if (this.pushToErrorSink) {\n                this.captureError(message);\n                return;\n            }\n\n            this.hasErrors = true;\n            if (ast && this.parser.errorRecovery && this.parser.errorCallback) {\n                var len = (ast.limChar - ast.minChar);\n                this.parser.errorCallback(ast.minChar, len, message, this.checker.locationInfo.unitIndex);\n            }\n            else {\n                this.writePrefix(ast);\n                this.outfile.WriteLine(message); // Right after the semi-colon\n            }\n        }\n\n        public reportErrorFromSym(symbol: Symbol, message: string) {\n            if (this.pushToErrorSink) {\n                this.captureError(message);\n                return;\n            }\n\n            this.hasErrors = true;\n            if (this.parser.errorRecovery && this.parser.errorCallback) {\n                this.parser.errorCallback(symbol.location, symbol.length, message, this.checker.locationInfo.unitIndex);\n            }\n            else {\n                this.writePrefixFromSym(symbol);\n                this.outfile.WriteLine(message);\n            }\n        }\n\n        public emitterError(ast: AST, message: string) {\n            this.reportError(ast, message);\n            // Emitter errors are not recoverable, stop immediately\n            throw Error(\"EmitError\");\n        }\n\n        public duplicateIdentifier(ast: AST, name: string) {\n            this.reportError(ast, \"Duplicate identifier '\" + name + \"'\");\n        }\n\n        public showRef(ast: AST, text: string, symbol: Symbol) {\n            var defLineCol = { line: -1, col: -1 };\n            // TODO: multiple def locations\n            this.parser.getSourceLineCol(defLineCol, symbol.location);\n            this.reportError(ast, \"symbol \" + text + \" defined at (\" + defLineCol.line + \",\" +\n                              defLineCol.col + \")\");\n        }\n\n        public unresolvedSymbol(ast: AST, name: string) {\n            this.reportError(ast, \"The name '\" + name + \"' does not exist in the current scope\");\n        }\n\n        public symbolDoesNotReferToAValue(ast: AST, name: string): void {\n            this.reportError(ast, \"The name '\" + name + \"' does not refer to a value\");\n        }\n\n        public styleError(ast: AST, msg: string): void {\n            var bkThrow = this.pushToErrorSink;\n            this.pushToErrorSink = false;\n            this.reportError(ast, \"STYLE: \" + msg);\n            this.pushToErrorSink = bkThrow;\n        }\n\n        public simpleError(ast: AST, msg: string): void {\n            this.reportError(ast, msg);\n        }\n\n        public simpleErrorFromSym(sym: Symbol, msg: string): void {\n            this.reportErrorFromSym(sym, msg);\n        }\n\n        public invalidSuperReference(ast: AST) {\n            this.simpleError(ast, \"Keyword 'super' can only be used inside a class instance method\");\n        }\n\n        public valueCannotBeModified(ast: AST) {\n            this.simpleError(ast, \"The left-hand side of an assignment expression must be a variable, property or indexer\");\n        }\n\n        public invalidCall(ast: CallExpression, nodeType: number, scope: SymbolScope): void {\n            var targetType = ast.target.type;\n            var typeName = targetType.getScopedTypeName(scope);\n            if (targetType.construct && (nodeType == NodeType.Call)) {\n                this.reportError(ast, \"Value of type '\" + typeName + \"' is not callable.  Did you mean to include 'new'?\");\n            } else {\n                var catString = (nodeType == NodeType.Call) ? \"callable\" : \"newable\";\n\n                this.reportError(ast, \"Value of type '\" + typeName + \"' is not \" + catString);\n            }\n        }\n\n        public indexLHS(ast: BinaryExpression, scope: SymbolScope): void {\n            var targetType = ast.operand1.type.getScopedTypeName(scope);\n            var indexType = ast.operand2.type.getScopedTypeName(scope);\n            this.simpleError(ast, \"Value of type '\" + targetType + \"' is not indexable by type '\" + indexType + \"'\");\n        }\n\n        public incompatibleTypes(ast: AST, t1: Type, t2: Type, op: string, scope: SymbolScope, comparisonInfo?:TypeComparisonInfo) {\n            if (!t1) {\n                t1 = this.checker.anyType;\n            }\n            if (!t2) {\n                t2 = this.checker.anyType;\n            }\n\n            var reason = comparisonInfo ? comparisonInfo.message : \"\";\n            if (op) {\n                this.reportError(ast, \"Operator '\" + op + \"' cannot be applied to types '\" + t1.getScopedTypeName(scope) +\n                                  \"' and '\" + t2.getScopedTypeName(scope) + \"'\" + (reason ? \": \" + reason : \"\"));\n            }\n            else {\n                this.reportError(ast, \"Cannot convert '\" + t1.getScopedTypeName(scope) +\n                                  \"' to '\" + t2.getScopedTypeName(scope) + \"'\" + (reason ? \": \" + reason : \"\"));\n            }\n        }\n\n        public expectedClassOrInterface(ast: AST): void {\n            this.simpleError(ast, \"Expected var, class, interface, or module\");\n        }\n\n        public unaryOperatorTypeError(ast: AST, op: string, type: Type) {\n            this.reportError(ast, \"Operator '\" + op + \"' cannot be applied to type '\" + type.getTypeName() + \"'\");\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export function hasFlag(val: number, flag: number) {\n        return (val & flag) != 0;\n    }\n\n    export enum ErrorRecoverySet {\n        None = 0,\n        Comma = 1, // Comma\n        SColon = 1 << 1, // SColon\n        Asg = 1 << 2, // Asg\n        BinOp = 1 << 3, // Lsh, Rsh, Rs2, Le, Ge, INSTANCEOF, EQ, NE, Eqv, NEqv, LogAnd, LogOr, AsgMul, AsgDiv\n        // AsgMod, AsgAdd, AsgSub, AsgLsh, AsgRsh, AsgRs2, AsgAnd, AsgXor, AsgOr, QMark, Mult, Div, \n        // Pct, GT, LT, And, Xor, Or\n        RBrack = 1 << 4, // RBrack\n        RCurly = 1 << 5, // RCurly\n        RParen = 1 << 6, // RParen\n        Dot = 1 << 7, // Dot\n        Colon = 1 << 8, // Colon\n        PrimType = 1 << 9, // number, string, bool\n        AddOp = 1 << 10, // Add, Sub\n        LCurly = 1 << 11, // LCurly\n        PreOp = 1 << 12, // Tilde, Bang, Inc, Dec\n        RegExp = 1 << 13, // RegExp\n        LParen = 1 << 14, // LParen\n        LBrack = 1 << 15, // LBrack\n        Scope = 1 << 16, // Scope\n        In = 1 << 17, // IN\n        SCase = 1 << 18, // CASE, DEFAULT\n        Else = 1 << 19, // ELSE\n        Catch = 1 << 20, // CATCH, FINALLY\n        Var = 1 << 21, // \n        Stmt = 1 << 22, // BREAK, RETURN, THROW, DEBUGGER, FOR, SWITCH, DO, IF, TRY, WITH\n        While = 1 << 23, // WHILE\n        ID = 1 << 24, // ID\n        Prefix = 1 << 25, // VOID, DELETE, TYPEOF, AWAIT\n        Literal = 1 << 26, // IntCon, FltCon, StrCon\n        RLit = 1 << 27, // THIS, TRUE, FALSE, NULL\n        Func = 1 << 28, // FUNCTION\n        EOF = 1 << 29, // EOF\n\n        // REVIEW: Name this something clearer.\n        TypeScriptS = 1 << 30, // PROPERTY, PRIVATE, STATIC, INTERFACE, CLASS, MODULE, EXPORT, IMPORT\n        ExprStart = SColon | AddOp | LCurly | PreOp | RegExp | LParen | LBrack | ID | Prefix | RLit | Func | Literal,\n        StmtStart = ExprStart | SColon | Var | Stmt | While | TypeScriptS,\n        Postfix = Dot | LParen | LBrack,\n    }\n\n    export enum AllowedElements {\n        None = 0,\n        ModuleDeclarations = 1 << 2,\n        ClassDeclarations = 1 << 3,\n        InterfaceDeclarations = 1 << 4,\n        AmbientDeclarations = 1 << 10,\n        Properties = 1 << 11,\n\n        Global = ModuleDeclarations | ClassDeclarations | InterfaceDeclarations | AmbientDeclarations,\n        QuickParse = Global | Properties,\n    }\n\n    export enum Modifiers {\n        None = 0,\n        Private = 1,\n        Public = 1 << 1,\n        Readonly = 1 << 2,\n        Ambient = 1 << 3,\n        Exported = 1 << 4,\n        Getter = 1 << 5,\n        Setter = 1 << 6,\n        Static = 1 << 7,\n    }\n\n    export enum ASTFlags {\n        None = 0,\n        ExplicitSemicolon = 1, // statment terminated by an explicit semicolon\n        AutomaticSemicolon = 1 << 1, // statment terminated by an automatic semicolon\n        Writeable = 1 << 2,  // node is lhs that can be modified\n        Error = 1 << 3, // node has an error\n        DotLHSPartial = 1 << 4, // node is the lhs of an incomplete dot expr at cursor\n        DotLHS = 1 << 5, // node is the lhs of a dot expr\n        IsStatement = 1 << 6, // node is a statement\n        StrictMode = 1 << 7, // node is in the strict mode environment\n        PossibleOptionalParameter = 1 << 8,\n        ClassBaseConstructorCall = 1 << 9,\n        OptionalName = 1 << 10,\n        // REVIEW: This flag is to mark lambda nodes to note that the LParen of an expression has already been matched in the lambda header.\n        //         The flag is used to communicate this piece of information to the calling parseTerm, which intern will remove it.\n        //         Once we have a better way to associate information with nodes, this flag should not be used.\n        SkipNextRParen = 1 << 11, \n    }\n\n    export enum DeclFlags {\n        None = 0,\n        Exported = 1,\n        Private = 1 << 1,\n        Public = 1 << 2,\n        Ambient = 1 << 3,\n        Static = 1 << 4,\n        LocalStatic = 1 << 5,\n        GetAccessor = 1 << 6,\n        SetAccessor = 1 << 7,\n    }\n\n    export enum ModuleFlags {\n        None = 0,\n        Exported = 1,\n        Private = 1 << 1,\n        Public = 1 << 2,\n        Ambient = 1 << 3,\n        Static = 1 << 4,\n        LocalStatic = 1 << 5,\n        GetAccessor = 1 << 6,\n        SetAccessor = 1 << 7,\n        IsEnum = 1 << 8,\n        ShouldEmitModuleDecl = 1 << 9,\n        IsWholeFile = 1 << 10,\n        IsDynamic = 1 << 11,\n        MustCaptureThis = 1 << 12,\n    }\n\n    export enum SymbolFlags {\n        None = 0,\n        Exported = 1,\n        Private = 1 << 1,\n        Public = 1 << 2,\n        Ambient = 1 << 3,\n        Static = 1 << 4,\n        LocalStatic = 1 << 5,\n        GetAccessor = 1 << 6,\n        SetAccessor = 1 << 7,\n        Property = 1 << 8,\n        Readonly = 1 << 9,\n        ModuleMember = 1 << 10,\n        InterfaceMember = 1 << 11,\n        ClassMember = 1 << 12,\n        BuiltIn = 1 << 13,\n        TypeSetDuringScopeAssignment = 1 << 14,\n        Constant = 1 << 15,\n        Optional = 1 << 16,\n        RecursivelyReferenced = 1 << 17,\n        Bound = 1 << 18,\n        CompilerGenerated = 1 << 19,\n    }\n\n    export enum VarFlags {\n        None = 0,\n        Exported = 1,\n        Private = 1 << 1,\n        Public = 1 << 2,\n        Ambient = 1 << 3,\n        Static = 1 << 4,\n        LocalStatic = 1 << 5,\n        GetAccessor = 1 << 6,\n        SetAccessor = 1 << 7,\n        AutoInit = 1 << 8,\n        Property = 1 << 9,\n        Readonly = 1 << 10,\n        Class = 1 << 11,\n        ClassProperty = 1 << 12,\n        ClassBodyProperty = 1 << 13,\n        ClassConstructorProperty = 1 << 14,\n        ClassSuperMustBeFirstCallInConstructor = 1 << 15,\n        Constant = 1 << 16,\n        MustCaptureThis = 1 << 17,\n    }\n\n    export enum FncFlags {\n        None = 0,\n        Exported = 1,\n        Private = 1 << 1,\n        Public = 1 << 2,\n        Ambient = 1 << 3,\n        Static = 1 << 4,\n        LocalStatic = 1 << 5,\n        GetAccessor = 1 << 6,\n        SetAccessor = 1 << 7,\n        Definition = 1 << 8,\n        Signature = 1 << 9,\n        Method = 1 << 10,\n        HasReturnExpression = 1 << 11,\n        CallMember = 1 << 12,\n        ConstructMember = 1 << 13,\n        HasSelfReference = 1 << 14,\n        IsFatArrowFunction = 1 << 15,\n        IndexerMember = 1 << 16,\n        IsFunctionExpression = 1 << 17,\n        ClassMethod = 1 << 18,\n        ClassPropertyMethodExported = 1 << 19,\n        HasSuperReferenceInFatArrowFunction = 1 << 20,\n        IsPropertyBound = 1 << 21,\n    }\n\n    export enum SignatureFlags {\n        None = 0,\n        IsIndexer = 1,\n        IsStringIndexer = 1 << 1,\n        IsNumberIndexer = 1 << 2,\n    }\n\n    export function ToDeclFlags(fncFlags: FncFlags) : DeclFlags;\n    export function ToDeclFlags(varFlags: VarFlags) : DeclFlags;\n    export function ToDeclFlags(symFlags: SymbolFlags): DeclFlags;\n    export function ToDeclFlags(moduleFlags: ModuleFlags): DeclFlags;\n    export function ToDeclFlags(fncOrVarOrSymbolOrModuleFlags: any) {\n        return <DeclFlags>fncOrVarOrSymbolOrModuleFlags;\n    }\n\n    export enum TypeFlags {\n        None = 0,\n        HasImplementation = 1,\n        HasSelfReference = 1 << 1,\n        MergeResult = 1 << 2,\n        IsEnum = 1 << 3,\n        BuildingName = 1 << 4,\n        HasBaseType = 1 << 5,\n        HasBaseTypeOfObject = 1 << 6,\n        IsClass = 1 << 7,\n    }\n\n    export enum TypeRelationshipFlags {\n        SuccessfulComparison = 0,\n        SourceIsNullTargetIsVoidOrUndefined = 1,\n        RequiredPropertyIsMissing = 1 << 1,\n        IncompatibleSignatures = 1 << 2,\n        SourceSignatureHasTooManyParameters = 3,\n        IncompatibleReturnTypes = 1 << 4,\n        IncompatiblePropertyTypes = 1 << 5,\n        IncompatibleParameterTypes = 1 << 6,\n    }\n\n    export enum CodeGenTarget {\n        ES3 = 0,\n        ES5 = 1,\n    }\n\n    export enum ModuleGenTarget {\n        Synchronous = 0,\n        Asynchronous = 1,\n        Local = 1 << 1,\n    }\n\n    // Compiler defaults to generating ES5-compliant code for\n    //  - getters and setters\n    export var codeGenTarget: CodeGenTarget = CodeGenTarget.ES3;\n\n    export var moduleGenTarget: ModuleGenTarget = ModuleGenTarget.Synchronous;\n\n    export var optimizeModuleCodeGen = true;\n\n    export function flagsToString(e, flags: number): string {\n        var builder = \"\";\n        for (var i = 1; i < (1 << 31) ; i = i << 1) {\n            if ((flags & i) != 0) {\n                for (var k in e) {\n                    if (e[k] == i) {\n                        if (builder.length > 0) {\n                            builder += \"|\";\n                        }\n                        builder += k;\n                        break;\n                    }\n                }\n            }\n        }\n        return builder;\n    }\n\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export class BlockIntrinsics {\n        public prototype = undefined;\n        public toString = undefined;\n        public toLocaleString = undefined;\n        public valueOf = undefined;\n        public hasOwnProperty = undefined;\n        public propertyIsEnumerable = undefined;\n        public isPrototypeOf = undefined;\n\n        constructor () {\n            // initialize the 'constructor' field\n            this[\"constructor\"] = undefined;\n        }\n    }\n\n    export interface IHashTable {\n        getAllKeys(): string[];\n        add(key: string, data): bool;\n        addOrUpdate(key: string, data): bool;\n        map(fn: (k: string, v, c) => void , context): void;\n        every(fn: (k: string, v, c) => bool, context): bool;\n        some(fn: (k: string, v, c) => bool, context): bool;\n        count(): number;\n        lookup(key: string): any;\n    }\n\n    export class StringHashTable implements IHashTable {\n        public itemCount = 0;\n        public table = <any>(<any> new BlockIntrinsics());\n\n        public getAllKeys(): string[]{\n            var result: string[] = [];\n            for (var k in this.table) {\n                if (this.table[k] != undefined) {\n                    result[result.length] = k;\n                }\n            }\n            return result;\n        }\n\n        public add(key: string, data): bool {\n            if (this.table[key] != undefined) {\n                return false;\n            }\n            this.table[key] = data;\n            this.itemCount++;\n            return true;\n        }\n\n        public addOrUpdate(key: string, data): bool {\n            if (this.table[key] != undefined) {\n                this.table[key] = data;\n                return false;\n            }\n            this.table[key] = data;\n            this.itemCount++;\n            return true;\n        }\n\n        public map(fn: (k: string, v, c) => void , context) {\n            for (var k in this.table) {\n                var data = this.table[k];\n                if (data != undefined) {\n                    fn(k, this.table[k], context);\n                }\n            }\n        }\n\n        public every(fn: (k: string, v, c) => bool, context) {\n            for (var k in this.table) {\n                var data = this.table[k];\n                if (data != undefined) {\n                    if (!fn(k, this.table[k], context)) {\n                        return false;\n                    }\n                }\n            }\n            return true;\n        }\n\n        public some(fn: (k: string, v, c) => bool, context) {\n            for (var k in this.table) {\n                var data = this.table[k];\n                if (data != undefined) {\n                    if (fn(k, this.table[k], context)) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        public count(): number { return this.itemCount; }\n\n        public lookup(key: string) {\n            var data = this.table[key];\n            if (data != undefined) {\n                return data;\n            }\n            else {\n                return (null);\n            }\n        }\n    }\n\n    // The resident table is expected to reference the same table object, whereas the \n    // transientTable may reference different objects over time\n    // REVIEW:  WARNING:  For performance reasons, neither the primary nor secondary table may be null\n    export class DualStringHashTable implements IHashTable {\n\n        public insertPrimary = true;\n\n        constructor (public primaryTable: IHashTable,\n                                        public secondaryTable: IHashTable) { }\n\n        public getAllKeys(): string[]{\n            return this.primaryTable.getAllKeys().concat(this.secondaryTable.getAllKeys());\n        }\n\n        public add(key: string, data): bool {\n            if (this.insertPrimary) {\n                return this.primaryTable.add(key, data);\n            }\n            else {\n                return this.secondaryTable.add(key, data);\n            }\n        }\n\n        public addOrUpdate(key: string, data): bool {\n            if (this.insertPrimary) {\n                return this.primaryTable.addOrUpdate(key, data);\n            }\n            else {\n                return this.secondaryTable.addOrUpdate(key, data);\n            }\n        }\n\n        public map(fn: (k: string, v, c) => void , context) {\n            this.primaryTable.map(fn, context);\n            this.secondaryTable.map(fn, context);\n        }\n\n        public every(fn: (k: string, v, c) => bool, context) {\n            return this.primaryTable.every(fn, context) && this.secondaryTable.every(fn, context);\n        }\n\n        public some(fn: (k: string, v, c) => bool, context) {\n            return this.primaryTable.some(fn, context) || this.secondaryTable.some(fn, context);\n        }\n\n        public count() {\n            return this.primaryTable.count() + this.secondaryTable.count();\n        }\n\n        public lookup(key: string) {\n            var data = this.primaryTable.lookup(key);\n            if (data != undefined) {\n                return data;\n            }\n            else {\n                return this.secondaryTable.lookup(key);\n            }\n        }\n    }\n\n    export function numberHashFn(key: number): number {\n        var c2 = 0x27d4eb2d; // a prime or an odd constant\n        key = (key ^ 61) ^ (key >>> 16);\n        key = key + (key << 3);\n        key = key ^ (key >>> 4);\n        key = key * c2;\n        key = key ^ (key >>> 15);\n        return key;\n    }\n\n    export function combineHashes(key1: number, key2: number) {\n        return key2 ^ ((key1 >> 5) + key1);\n    }\n\n    export class HashEntry {\n        public next: HashEntry;\n\n        constructor (public key, public data) { }\n    }\n\n    export class HashTable {\n        public itemCount: number = 0;\n        public table = new HashEntry[];\n\n        constructor (public size: number, public hashFn: (key) =>number,\n                    public equalsFn: (key1, key2) =>bool) {\n            for (var i: number = 0; i < this.size; i++) {\n                this.table[i] = null;\n            }\n        }\n\n        public add(key, data): bool {\n            var current: HashEntry;\n            var entry: HashEntry = new HashEntry(key, data);\n            var val: number = this.hashFn(key);\n            val = val % this.size;\n\n            for (current = this.table[val]; current != null ; current = current.next) {\n                if (this.equalsFn(key, current.key)) {\n                    return false;\n                }\n            }\n            entry.next = this.table[val];\n            this.table[val] = entry;\n            this.itemCount++;\n            return true;\n        }\n\n        public remove(key) {\n            var current: HashEntry;\n            var val: number = this.hashFn(key);\n            val = val % this.size;\n            var result = null;\n            var prevEntry: HashEntry = null;\n\n            for (current = this.table[val]; current != null ; current = current.next) {\n                if (this.equalsFn(key, current.key)) {\n                    result = current.data;\n                    this.itemCount--;\n                    if (prevEntry) {\n                        prevEntry.next = current.next;\n                    }\n                    else {\n                        this.table[val] = current.next;\n                    }\n                    break;\n                }\n                prevEntry = current;\n            }\n            return result;\n        }\n\n        public count(): number { return this.itemCount; }\n\n        public lookup(key) {\n            var current: HashEntry;\n            var val: number = this.hashFn(key);\n            val = val % this.size;\n            for (current = this.table[val]; current != null ; current = current.next) {\n                if (this.equalsFn(key, current.key)) {\n                    return (current.data);\n                }\n            }\n            return (null);\n        }\n    }\n\n    // Simple Hash table with list of keys and values matching each other at the given index\n    export class SimpleHashTable {\n        private keys = [];\n        private values = [];\n\n        public lookup(key, findValue?: bool) {\n            var searchArray = this.keys;\n            if (findValue) {\n                searchArray = this.values;\n            }\n\n            for (var i = 0; i < searchArray.length; i++) {\n                if (searchArray[i] == key) {\n                    return {\n                        key: this.keys[i],\n                        data: this.values[i],\n                    };\n                }\n            }\n            return null;\n        }\n\n        public add(key, data): bool {\n            var lookupData = this.lookup(key);\n            if (lookupData) {\n                return false;\n            }\n\n            this.keys[this.keys.length] = key;\n            this.values[this.values.length] = data;\n\n            return true;\n        }\n    }\n\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export class IncrementalParser {\n        \n        private astLogger: AstLogger;\n\n        constructor (private logger: TypeScript.ILogger) {\n            this.astLogger = new AstLogger(this.logger);\n        }\n\n        //\n        // Return \"null\" if \"editRange\" cannot be safely determined to be inside a single scope.\n        //\n        public getEnclosingScopeContextIfSingleScopeEdit(previousScript: Script, scriptId: string, newSourceText: ISourceText, editRange: ScriptEditRange): EnclosingScopeContext {\n            this.logger.log(\"checkEditsInsideSingleScope(\\\"\" + scriptId + \"\\\")\");\n\n            if (editRange === null) {\n                throw new Error(\"editRange should be valid\");\n            }\n\n            if (editRange.isUnknown()) {\n                this.logger.log(\"  Bailing out because edit range is unknown\");\n                return null;\n            }\n\n            var scope1 = TypeScript.findEnclosingScopeAt(this.logger, previousScript, newSourceText, editRange.minChar, false/*isMemberCompletion*/);\n            var scope2 = TypeScript.findEnclosingScopeAt(this.logger, previousScript, newSourceText, editRange.limChar, false/*isMemberCompletion*/);\n            if (scope1 == null || scope2 == null) {\n                this.logger.log(\"  Bailing out because containing scopes cannot be determined\");\n                return null;\n            }\n\n            // We only support changes within a single containing scope\n            if (scope1.scopeStartAST !== scope2.scopeStartAST) {\n                this.logger.log(\"  Bailing out because edit overlaps 2 disctint scopes\");\n                return null;\n            }\n\n            var newScopeLength = scope1.scopeStartAST.limChar - scope1.scopeStartAST.minChar + editRange.delta;\n            if (newScopeLength <= 0) {\n                this.logger.log(\"  Bailing out because scope has been entirely removed from new source text\");\n                return null;\n            }\n\n            return scope1;\n        }\n\n        public attemptIncrementalUpdateUnit(previousScript: Script, scriptId: string, newSourceText: ISourceText, editRange: ScriptEditRange): UpdateUnitResult {\n            this.logger.log(\"attemptIncrementalUpdateUnit(\\\"\" + scriptId + \"\\\")\");\n\n            if (editRange === null) {\n                throw new Error(\"editRange should be valid\");\n            }\n\n            var scope1 = this.getEnclosingScopeContextIfSingleScopeEdit(previousScript, scriptId, newSourceText, editRange);\n            if (scope1 === null) {\n                return null;\n            }\n\n            var newScopeLength = scope1.scopeStartAST.limChar - scope1.scopeStartAST.minChar + editRange.delta;\n\n            // Heuristic: if the range to reparse is too big, bail out. \n            // This is because a full parse will be faster than an incremental parse followed by all the necessary fix-ups \n            if (newScopeLength >= newSourceText.getLength() / 2) {\n                this.logger.log(\"  Bailing out because range of scope to reparse (\" + newScopeLength + \" characters) is greater than half the size of the source text\");\n                return null;\n            }\n\n            // Capture parsing errors so that they are part of \"updateResult\"\n            var parseErrors: TypeScript.ErrorEntry[] = [];\n            var errorCapture = function(minChar: number, charLen: number, message: string, unitIndex: number): void {\n                parseErrors.push(new TypeScript.ErrorEntry(unitIndex, minChar, minChar + charLen, message));\n            };\n\n            var quickParseResult = TypeScript.quickParse(this.logger, scope1.scopeStartAST, newSourceText, scope1.scopeStartAST.minChar, scope1.scopeStartAST.minChar + newScopeLength, errorCapture);\n            if (quickParseResult.endLexState != TypeScript.LexState.Start) {\n                this.logger.log(\"  Bailing out because scope contains unterminated comment\");\n                return null;\n            }\n\n            var scriptFragment = quickParseResult.Script;\n            if (scriptFragment.vars.members.length !== 0) {\n                this.logger.log(\"  Bailing out because new source text defines variables\");\n                return null;\n            }\n\n            //if (scriptFragment.scopes.members.length !== 1) {\n            //    logger.log(\"  Bailing out because new source text defines more than one scope (or none)\");\n            //    return null;\n            //}\n\n            // This detects adding close curlies, since they have the side effect of having the parser \n            // parse more members in the scope range.\n            if (scriptFragment.bod.members.length !== 1) {\n                this.logger.log(\"  Bailing out because new source text defines more than one scope (or none)\");\n                return null;\n            }\n\n            var oldScope = scope1.scopeStartAST;\n            var newScope = scriptFragment.bod.members[0];\n\n            if (oldScope.nodeType != newScope.nodeType) {\n                this.logger.log(\"  Bailing out because new source text does not define the same scope type as the existing scope\");\n                return null;\n            }\n\n            if (!(<any>oldScope).leftCurlyCount || !(<any>oldScope).rightCurlyCount) {\n                this.logger.log(\"  Bailing out because sopce doesn't have left/right curly count\");\n                return null;\n            }\n\n            if ((<any>oldScope).leftCurlyCount !== (<any>newScope).leftCurlyCount) {\n                this.logger.log(\"  Bailing out because new source text contains more (or fewer) left curly braces\");\n                return null;\n            }\n\n            if ((<any>oldScope).rightCurlyCount !== (<any>newScope).rightCurlyCount) {\n                this.logger.log(\"  Bailing out because new source text contains more (or fewer) right curly braces\");\n                return null;\n            }\n\n            if (newScope.minChar !== 0) {\n                this.logger.log(\"  Bailing out because new function declaration does not start at position 0\");\n                return null;\n            }\n\n            if (newScope.limChar !== newScopeLength) {\n                this.logger.log(\"  Bailing out because new function declaration does not end at the new end position\");\n                return null;\n            }\n\n            return TypeScript.UpdateUnitResult.singleScopeEdits(previousScript, scriptFragment, oldScope, newScope, editRange, parseErrors);\n        }\n\n        public mergeTrees(updateResult: UpdateUnitResult): void {\n            TypeScript.timeFunction(this.logger, \"mergeTrees()\", () => {\n                var editRange = new ScriptEditRange(updateResult.scope1.minChar, updateResult.scope1.limChar, updateResult.editRange.delta);\n                // Update positions in current ast\n                this.applyDeltaPosition(updateResult.script1, editRange.limChar, editRange.delta);\n                // Update positions in new (partial) ast\n                this.applyDeltaPosition(updateResult.script2, 0, editRange.minChar);\n                // Merge linemaps\n                this.mergeLocationInfo(updateResult.script1, updateResult.script2, editRange);\n                //  Replace old AST for scope with new one\n                this.replaceAST(updateResult.script1, updateResult.scope1, updateResult.scope2);\n            });\n        }\n\n        private replaceAST(script: TypeScript.AST, oldAst: TypeScript.AST, newAst: TypeScript.AST) {\n            var pre = (cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) => {\n                if (cur === oldAst) {\n                    // Transfer comments ownership to new AST. We need this because when \"quick parsing\" the\n                    // new AST, we don't take into account the text before and after the \"minChar/limChar\" pair\n                    // of the scope, which don't include pre/post-comments.\n                    newAst.preComments = cur.preComments;\n                    newAst.postComments = cur.postComments;\n\n                    this.logger.log(\"replaced old AST node with new one in script AST\");\n                    walker.options.stopWalk();\n                    return newAst;\n                }\n\n                // Avoid visiting sub-trees outside of the edit range\n                if (TypeScript.isValidAstNode(cur)) {\n                    if (cur.limChar < oldAst.minChar || cur.minChar > oldAst.limChar) {\n                        walker.options.goChildren = false;\n                    }\n                }\n                return cur;\n            }\n\n            TypeScript.getAstWalkerFactory().walk(script, pre);\n        }\n\n        private mergeLocationInfo(script: TypeScript.Script, partial: TypeScript.Script, editRange: ScriptEditRange) {\n            // Don't merger these fields, as the original script has the right values\n            //script.locationInfo.unitIndex = partial.locationInfo.unitIndex;\n            //script.locationInfo.filename = partial.locationInfo.filename;\n\n            var lineMap1 = script.locationInfo.lineMap;\n            var lineMap2 = partial.locationInfo.lineMap;\n\n            if (this.logger.information()) {\n                this.logger.log(\"lineMap1 (before):\");\n                this.astLogger.logLinemap(lineMap1);\n                this.logger.log(\"lineMap2 (quick parse):\");\n                this.astLogger.logLinemap(lineMap2);\n                this.logger.log(\"EditRange=\" + editRange);\n            }\n\n            // Skip entries < minChar\n            var i1 = 2; // lineMap[0] is always undefined, lineMap[1] is always 0.\n            var i2 = 2; // lineMap[0] is always undefined, lineMap[1] is always 0.\n            var len1 = lineMap1.length;\n            var len2 = lineMap2.length;\n            while (i1 < len1) {\n                if (lineMap1[i1] <= editRange.minChar) {\n                    // Nothing to do for this entry, since it's before the range of the change\n                    i1++;\n                } else if (lineMap1[i1] >= editRange.limChar) {\n                    // Apply delta to this entry, since it's outside the range of the change\n                    lineMap1[i1] += editRange.delta;\n                    i1++;\n                }\n                else {\n                    if (i2 < len2) {\n                        // Add a new entry to lineMap1 corresponding to lineMap2 in new range\n                        lineMap1.splice(i1, 0, lineMap2[i2] + editRange.minChar);\n                        i1++;\n                        len1++;\n                        i2++;\n                    }\n                    else { /* i2 >= len 2 */\n                        // Remove this entry, since there is no corresponding entry in the new map\n                        lineMap1.splice(i1, 1);\n                        len1--;\n                    }\n                }\n            }\n            // Merge the remaining entries in lineMap2 while maintaing the constraint that a lineMap is sorted\n            if (i2 < len2) {\n                // i1 >= len1 && i2 < len2 \n                if (lineMap1[len1 - 1] >= (lineMap2[i2] + editRange.minChar)) {\n                    // lineMap2 needs to be merged within lineMap1\n                    i1 = 2;\n                    while (i1 < len1 && i2 < len2) {\n                        if (lineMap1[i1] < (lineMap2[i2] + editRange.minChar)) {\n                            i1++;\n                        }\n                        else {\n                            lineMap1.splice(i1, 0, lineMap2[i2] + editRange.minChar);\n                            i1++;\n                            len1++;\n                            i2++;\n                        }\n                    }\n                }\n\n                // Append all the remaining entries in lineMap2 to the end of lineMap1\n                for (; i2 < len2; i2++) {\n                    lineMap1.push(lineMap2[i2] + editRange.minChar);\n                }\n            }\n\n            if (this.logger.information()) {\n                this.logger.log(\"lineMap1 (after merge):\");\n                this.astLogger.logLinemap(lineMap1);\n            }\n        }\n\n        private applyDeltaPosition(ast: TypeScript.AST, start: number, delta: number) {\n            var applyDelta = (ast: TypeScript.AST) => {\n                if (ast.minChar !== -1 && ast.minChar >= start) {\n                    ast.minChar += delta;\n                }\n                if (ast.limChar !== -1 && ast.limChar >= start) {\n                    ast.limChar += delta;\n                }\n            }\n\n            var applyDeltaToComments = (comments: TypeScript.Comment[]) => {\n                if (comments && comments.length > 0) {\n                    for (var i = 0; i < comments.length; i++) {\n                        applyDelta(comments[i]);\n                    }\n                }\n            }\n\n            var pre = function(cur: TypeScript.AST, parent: TypeScript.AST, walker: TypeScript.IAstWalker) {\n                // *Before* applying delta to this, check if we need to go to children\n                if (cur.limChar !== -1 && cur.limChar < start) {\n                    walker.options.goChildren = false; // Done with applying Delta for this sub-tree\n                }\n\n                // Apply delta to this node\n                applyDelta(cur);\n                applyDeltaToComments(cur.preComments);\n                applyDeltaToComments(cur.postComments);\n\n                return cur;\n            }\n\n            TypeScript.getAstWalkerFactory().walk(ast, pre);\n        }\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\ninterface IResolvedFile {\n    content: string;\n    path: string;\n}\n\ninterface IFileWatcher {\n    close(): void;\n}\n\ninterface IIO {\n    readFile(path: string): string;\n    writeFile(path: string, contents: string): void;\n    createFile(path: string, useUTF8?: bool): ITextWriter;\n    deleteFile(path: string): void;\n    dir(path: string, re?: RegExp, options?: { recursive?: bool; }): string[];\n    fileExists(path: string): bool;\n    directoryExists(path: string): bool;\n    createDirectory(path: string): void;\n    resolvePath(path: string): string;\n    dirName(path: string): string;\n    findFile(rootPath: string, partialFilePath: string): IResolvedFile;\n    print(str: string): void;\n    printLine(str: string): void;\n    arguments: string[];\n    stderr: ITextWriter;\n    stdout: ITextWriter;\n    watchFile(filename: string, callback: (string) => void ): IFileWatcher;\n    run(source: string, filename: string): void;\n    getExecutingFilePath(): string;\n    quit(exitCode?: number);\n}\n\nmodule IOUtils {\n    // Creates the directory including its parent if not already present\n    function createDirectoryStructure(ioHost: IIO, dirName: string) {\n        if (ioHost.directoryExists(dirName)) {\n            return;\n        }\n\n        var parentDirectory = ioHost.dirName(dirName);\n        if (parentDirectory != \"\") {\n            createDirectoryStructure(ioHost, parentDirectory);\n        }\n        ioHost.createDirectory(dirName);\n    }\n\n    // Creates a file including its directory structure if not already present\n    export function createFileAndFolderStructure(ioHost: IIO, fileName: string, useUTF8?: bool) {\n        var path = ioHost.resolvePath(fileName);\n        var dirName = ioHost.dirName(path);\n        createDirectoryStructure(ioHost, dirName);\n        return ioHost.createFile(path, useUTF8);\n    }\n\n    export function throwIOError(message: string, error: Error) {\n        var errorMessage = message;\n        if (error && error.message) {\n            errorMessage += (\" \" + error.message);\n        }\n        throw new Error(errorMessage);\n    }\n}\n\n// Declare dependencies needed for all supported hosts\ndeclare class Enumerator {\n    public atEnd(): bool;\n    public moveNext();\n    public item(): any;\n    constructor (o: any);\n}\ndeclare function setTimeout(callback: () =>void , ms?: number);\ndeclare var require: any;\ndeclare module process {\n    export var argv: string[];\n    export var platform: string;\n    export function on(event: string, handler: (any) => void ): void;\n    export module stdout {\n        export function write(str: string);\n    }\n    export module stderr {\n        export function write(str: string);\n    }\n    export module mainModule {\n        export var filename: string;\n    }\n    export function exit(exitCode?: number);\n}\n\nvar IO = (function() {\n\n    // Create an IO object for use inside WindowsScriptHost hosts\n    // Depends on WSCript and FileSystemObject\n    function getWindowsScriptHostIO(): IIO {\n        var fso = new ActiveXObject(\"Scripting.FileSystemObject\");\n        var streamObjectPool = [];\n\n        function getStreamObject(): any { \n            if (streamObjectPool.length > 0) {\n                return streamObjectPool.pop();\n            }  else {\n                return new ActiveXObject(\"ADODB.Stream\");\n            }\n        }\n\n        function releaseStreamObject(obj: any) { \n            streamObjectPool.push(obj);\n        }\n\n        var args = [];\n        for (var i = 0; i < WScript.Arguments.length; i++) {\n            args[i] = WScript.Arguments.Item(i);\n        }\n\n        return {\n            readFile: function(path) {\n                try {\n                    var streamObj = getStreamObject();\n                    streamObj.Open();\n                    streamObj.Type = 2; // Text data\n                    streamObj.Charset = 'x-ansi'; // Assume we are reading ansi text\n                    streamObj.LoadFromFile(path);\n                    var bomChar = streamObj.ReadText(2); // Read the BOM char\n                    streamObj.Position = 0; // Position has to be at 0 before changing the encoding\n                    if ((bomChar.charCodeAt(0) == 0xFE && bomChar.charCodeAt(1) == 0xFF)\n                        || (bomChar.charCodeAt(0) == 0xFF && bomChar.charCodeAt(1) == 0xFE)) {\n                        streamObj.Charset = 'unicode';\n                    } else if (bomChar.charCodeAt(0) == 0xEF && bomChar.charCodeAt(1) == 0xBB) {\n                        streamObj.Charset = 'utf-8'; \n                    }\n\n                    // Read the whole file\n                    var str = streamObj.ReadText(-1 /* read from the current position to EOS */);\n                    streamObj.Close();\n                    releaseStreamObject(streamObj);\n                    return <string>str;\n                }\n                catch (err) {\n                    IOUtils.throwIOError(\"Error reading file \\\"\" + path + \"\\\".\", err);\n                }\n            },\n\n            writeFile: function(path, contents) {\n                var file = this.createFile(path);\n                file.Write(contents);\n                file.Close();\n            },\n\n            fileExists: function(path: string): bool {\n                return fso.FileExists(path);\n            },\n\n            resolvePath: function(path: string): string {\n                return fso.GetAbsolutePathName(path);\n            },\n\n            dirName: function(path: string): string {\n                return fso.GetParentFolderName(path);\n            },\n\n            findFile: function(rootPath: string, partialFilePath: string): IResolvedFile {\n                var path = fso.GetAbsolutePathName(rootPath) + \"/\" + partialFilePath;\n\n                while (true) {\n                    if (fso.FileExists(path)) {\n                        try {\n                            var content = this.readFile(path);\n                            return { content: content, path: path };\n                        }\n                        catch (err) {\n                            //Tools.CompilerDiagnostics.debugPrint(\"Could not find \" + path + \", trying parent\");\n                        }\n                    }\n                    else {\n                        rootPath = fso.GetParentFolderName(fso.GetAbsolutePathName(rootPath));\n\n                        if (rootPath == \"\") {\n                            return null;\n                        }\n                        else {\n                            path = fso.BuildPath(rootPath, partialFilePath);\n                        }\n                    }\n                }\n            },\n\n            deleteFile: function(path: string): void {\n                try {\n                    if (fso.FileExists(path)) {\n                        fso.DeleteFile(path, true); // true: delete read-only files\n                    }\n                } catch (e) {\n                    IOUtils.throwIOError(\"Couldn't delete file '\" + path + \"'.\", e);\n                }\n            },\n\n            createFile: function (path, useUTF8?) {\n                try {\n                    var streamObj = getStreamObject();\n                    streamObj.Charset = useUTF8 ? 'utf-8' : 'x-ansi';\n                    streamObj.Open();\n                    return {\n                        Write: function (str) { streamObj.WriteText(str, 0); },\n                        WriteLine: function (str) { streamObj.WriteText(str, 1); },\n                        Close: function() {\n                            try {\n                                streamObj.SaveToFile(path, 2);\n                            } catch (saveError) {\n                                IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", saveError);\n                            }\n                            finally {\n                                if (streamObj.State != 0 /*adStateClosed*/) {\n                                    streamObj.Close();\n                                }\n                                releaseStreamObject(streamObj);\n                            }\n                        }\n                    };\n                } catch (creationError) {\n                    IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", creationError);\n                }\n            },\n\n            directoryExists: function(path) {\n                return <bool>fso.FolderExists(path);\n            },\n\n            createDirectory: function(path) {\n                try {\n                    if (!this.directoryExists(path)) {\n                        fso.CreateFolder(path);\n                    }\n                } catch (e) {\n                    IOUtils.throwIOError(\"Couldn't create directory '\" + path + \"'.\", e);\n                }\n            },\n\n            dir: function(path, spec?, options?) {\n                options = options || <{ recursive?: bool; }>{};\n                function filesInFolder(folder, root): string[]{\n                    var paths = [];\n                    var fc: Enumerator;\n\n                    if (options.recursive) {\n                        fc = new Enumerator(folder.subfolders);\n\n                        for (; !fc.atEnd() ; fc.moveNext()) {\n                            paths = paths.concat(filesInFolder(fc.item(), root + \"/\" + fc.item().Name));\n                        }\n                    }\n\n                    fc = new Enumerator(folder.files);\n\n                    for (; !fc.atEnd() ; fc.moveNext()) {\n                        if (!spec || fc.item().Name.match(spec)) {\n                            paths.push(root + \"/\" + fc.item().Name);\n                        }\n                    }\n\n                    return paths;\n                }\n\n                var folder = fso.GetFolder(path);\n                var paths = [];\n\n                return filesInFolder(folder, path);\n            },\n\n            print: function(str) {\n                WScript.StdOut.Write(str);\n            },\n\n            printLine: function(str) {\n                WScript.Echo(str);\n            },\n\n            arguments: <string[]>args,\n            stderr: WScript.StdErr,\n            stdout: WScript.StdOut,\n            watchFile: null,\n            run: function(source, filename) {\n                try {\n                    eval(source);\n                } catch (e) {\n                    IOUtils.throwIOError(\"Error while executing file '\" + filename + \"'.\", e);\n                }\n            },\n            getExecutingFilePath: function () {\n                return WScript.ScriptFullName;\n            },\n            quit: function (exitCode? : number = 0) {\n                try {\n                    WScript.Quit(exitCode);\n                } catch (e) {\n                }\n            }\n        }\n\n    };\n\n    // Create an IO object for use inside Node.js hosts\n    // Depends on 'fs' and 'path' modules\n    function getNodeIO(): IIO {\n\n        var _fs = require('fs');\n        var _path = require('path');\n        var _module = require('module');\n\n        return {\n            readFile: function(file) {\n                try {\n                    var buffer = _fs.readFileSync(file);\n                    switch (buffer[0]) {\n                        case 0xFE:\n                            if (buffer[1] == 0xFF) {\n                                // utf16-be. Reading the buffer as big endian is not supported, so convert it to \n                                // Little Endian first\n                                var i = 0;\n                                while ((i + 1) < buffer.length) {\n                                    var temp = buffer[i]\n                                    buffer[i] = buffer[i + 1];\n                                    buffer[i + 1] = temp;\n                                    i += 2;\n                                }\n                                return buffer.toString(\"ucs2\", 2);\n                            }\n                            break;\n                        case 0xFF:\n                            if (buffer[1] == 0xFE) {\n                                // utf16-le \n                                return buffer.toString(\"ucs2\", 2);\n                            }\n                            break;\n                        case 0xEF:\n                            if (buffer[1] == 0xBB) {\n                                // utf-8\n                                return buffer.toString(\"utf8\", 3);\n                            }\n                    }\n                    // Default behaviour\n                    return buffer.toString();\n                } catch (e) {\n                    IOUtils.throwIOError(\"Error reading file \\\"\" + file + \"\\\".\", e);\n                }\n            },\n            writeFile: <(path: string, contents: string) => void >_fs.writeFileSync,\n            deleteFile: function(path) {\n                try {\n                    _fs.unlinkSync(path);\n                } catch (e) {\n                    IOUtils.throwIOError(\"Couldn't delete file '\" + path + \"'.\", e);\n                }\n            },\n            fileExists: function(path): bool {\n                return _fs.existsSync(path);\n            },\n            createFile: function(path, useUTF8?) {\n                function mkdirRecursiveSync(path) {\n                    var stats = _fs.statSync(path);\n                    if (stats.isFile()) {\n                        IOUtils.throwIOError(\"\\\"\" + path + \"\\\" exists but isn't a directory.\", null);\n                    } else if (stats.isDirectory()) {\n                        return;\n                    } else {\n                        mkdirRecursiveSync(_path.dirname(path));\n                        _fs.mkdirSync(path, 0775);\n                    }\n                }\n\n                mkdirRecursiveSync(_path.dirname(path));\n\n                try {\n                    var fd = _fs.openSync(path, 'w');\n                } catch (e) {\n                    IOUtils.throwIOError(\"Couldn't write to file '\" + path + \"'.\", e);\n                }\n                return {\n                    Write: function(str) { _fs.writeSync(fd, str); },\n                    WriteLine: function(str) { _fs.writeSync(fd, str + '\\r\\n'); },\n                    Close: function() { _fs.closeSync(fd); fd = null; }\n                };\n            },\n            dir: function dir(path, spec?, options?) {\n                options = options || <{ recursive?: bool; }>{};\n\n                function filesInFolder(folder: string): string[]{\n                    var paths = [];\n\n                    var files = _fs.readdirSync(folder);\n                    for (var i = 0; i < files.length; i++) {\n                        var stat = _fs.statSync(folder + \"/\" + files[i]);\n                        if (options.recursive && stat.isDirectory()) {\n                            paths = paths.concat(filesInFolder(folder + \"/\" + files[i]));\n                        } else if (stat.isFile() && (!spec || files[i].match(spec))) {\n                            paths.push(folder + \"/\" + files[i]);\n                        }\n                    }\n\n                    return paths;\n                }\n\n                return filesInFolder(path);\n            },\n            createDirectory: function(path: string): void {\n                try {\n                    if (!this.directoryExists(path)) {\n                        _fs.mkdirSync(path);\n                    }\n                } catch (e) {\n                    IOUtils.throwIOError(\"Couldn't create directory '\" + path + \"'.\", e);\n                }\n            },\n\n            directoryExists: function(path: string): bool {\n                return _fs.existsSync(path) && _fs.lstatSync(path).isDirectory();\n            },\n            resolvePath: function(path: string): string {\n                return _path.resolve(path);\n            },\n            dirName: function(path: string): string {\n                return _path.dirname(path);\n            },\n            findFile: function(rootPath: string, partialFilePath): IResolvedFile {\n                var path = rootPath + \"/\" + partialFilePath;\n\n                while (true) {\n                    if (_fs.existsSync(path)) {\n                        try {\n                            var content = this.readFile(path);\n                            return { content: content, path: path };\n                        } catch (err) {\n                            //Tools.CompilerDiagnostics.debugPrint((\"Could not find \" + path) + \", trying parent\");\n                        }\n                    }\n                    else {\n                        var parentPath = _path.resolve(rootPath, \"..\");\n\n                        // Node will just continue to repeat the root path, rather than return null\n                        if (rootPath === parentPath) {\n                            return null;\n                        }\n                        else {\n                            rootPath = parentPath;\n                            path = _path.resolve(rootPath, partialFilePath);\n                        }\n                    }\n                }\n            },\n            print: function(str) { process.stdout.write(str) },\n            printLine: function(str) { process.stdout.write(str + '\\n') },\n            arguments: process.argv.slice(2),\n            stderr: {\n                Write: function(str) { process.stderr.write(str); },\n                WriteLine: function(str) { process.stderr.write(str + '\\n'); },\n                Close: function() { }\n            },\n            stdout: {\n                Write: function(str) { process.stdout.write(str); },\n                WriteLine: function(str) { process.stdout.write(str + '\\n'); },\n                Close: function() { }\n            },\n            watchFile: function(filename: string, callback: (string) => void ): IFileWatcher {\n                var firstRun = true;\n                var processingChange = false;\n\n                var fileChanged: any = function(curr, prev) {\n                    if (!firstRun) {\n                        if (curr.mtime < prev.mtime) {\n                            return;\n                        }\n\n                        _fs.unwatchFile(filename, fileChanged);\n                        if (!processingChange) {\n                            processingChange = true;\n                            callback(filename);\n                            setTimeout(function() { processingChange = false; }, 100);\n                        }\n                    }\n                    firstRun = false;\n                    _fs.watchFile(filename, { persistent: true, interval: 500 }, fileChanged);\n                };\n\n                fileChanged();\n                return {\n                    filename: filename,\n                    close: function() {\n                        _fs.unwatchFile(filename, fileChanged);\n                    }\n                };\n            },\n            run: function(source, filename) {\n                require.main.filename = filename;\n                require.main.paths = _module._nodeModulePaths(_path.dirname(_fs.realpathSync(filename)));\n                require.main._compile(source, filename);\n            }, \n            getExecutingFilePath: function () {\n                return process.mainModule.filename;\n            },\n            quit: process.exit\n        }\n    };\n\n    if (typeof ActiveXObject === \"function\")\n        return getWindowsScriptHostIO();\n    else if (typeof require === \"function\")\n        return getNodeIO();\n    else\n        return null; // Unsupported host\n})();\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    // Note: Any addition to the NodeType should also be supported with addition to AstWalkerDetailCallback\n    export enum NodeType {\n        None,\n        Empty,\n        EmptyExpr,\n        True,\n        False,\n        This,\n        Super,\n        QString,\n        Regex,\n        Null,\n        ArrayLit,\n        ObjectLit,\n        Void,\n        Comma,\n        Pos,\n        Neg,\n        Delete,\n        Await,\n        In,\n        Dot,\n        From,\n        Is,\n        InstOf,\n        Typeof,\n        NumberLit,\n        Name,\n        TypeRef,\n        Index,\n        Call,\n        New,\n        Asg,\n        AsgAdd,\n        AsgSub,\n        AsgDiv,\n        AsgMul,\n        AsgMod,\n        AsgAnd,\n        AsgXor,\n        AsgOr,\n        AsgLsh,\n        AsgRsh,\n        AsgRs2,\n        ConditionalExpression,\n        LogOr,\n        LogAnd,\n        Or,\n        Xor,\n        And,\n        Eq,\n        Ne,\n        Eqv,\n        NEqv,\n        Lt,\n        Le,\n        Gt,\n        Ge,\n        Add,\n        Sub,\n        Mul,\n        Div,\n        Mod,\n        Lsh,\n        Rsh,\n        Rs2,\n        Not,\n        LogNot,\n        IncPre,\n        DecPre,\n        IncPost,\n        DecPost,\n        TypeAssertion,\n        FuncDecl,\n        Member,\n        VarDecl,\n        ArgDecl,\n        Return,\n        Break,\n        Continue,\n        Throw,\n        For,\n        ForIn,\n        If,\n        While,\n        DoWhile,\n        Block,\n        Case,\n        Switch,\n        Try,\n        TryCatch,\n        TryFinally,\n        Finally,\n        Catch,\n        List,\n        Script,\n        ClassDeclaration,\n        InterfaceDeclaration,\n        ModuleDeclaration,\n        ImportDeclaration,\n        With,\n        Label,\n        LabeledStatement,\n        EBStart,\n        GotoEB,\n        EndCode,\n        Error,\n        Comment,\n        Debugger,\n        GeneralNode = FuncDecl,\n        LastAsg = AsgRs2,\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path=\"io.ts\" />\n\ninterface IOptions {\n    name?: string;\n    flag?: bool;\n    short?: string;\n    usage?: string;\n    set?: (s: string) => void;\n    type?: string;\n    experimental?: bool;\n}\n\nclass OptionsParser {\n    private DEFAULT_SHORT_FLAG = \"-\";\n    private DEFAULT_LONG_FLAG = \"--\";\n\n    // Find the option record for the given string. Returns null if not found.\n    private findOption(arg: string) {\n\n        for (var i = 0; i < this.options.length; i++) {\n\n            if (arg === this.options[i].short || arg === this.options[i].name) {\n                return this.options[i];\n            }\n        }\n\n        return null;\n    }\n\n    public unnamed: string[] = [];\n\n    public options: IOptions[] = [];\n\n    constructor (public host: IIO) {\n    }\n\n    public printUsage() {\n        this.host.printLine(\"Syntax:   tsc [options] [file ..]\");\n        this.host.printLine(\"\");\n        this.host.printLine(\"Examples: tsc hello.ts\");\n        this.host.printLine(\"          tsc --out foo.js foo.ts\");\n        this.host.printLine(\"          tsc @args.txt\");\n        this.host.printLine(\"\");\n        this.host.printLine(\"Options:\");\n\n        var output = [];\n        var maxLength = 0;\n\n        this.options = this.options.sort(function(a, b) {\n            var aName = a.name.toLowerCase();\n            var bName = b.name.toLowerCase();\n\n            if (aName > bName) {\n                return 1;\n            } else if (aName < bName) {\n                return -1;\n            } else {\n                return 0;\n            }\n        });\n\n        // Build up output array\n        for (var i = 0; i < this.options.length; i++) {\n            var option = this.options[i];\n\n            if (option.experimental) {\n                continue;\n            }\n\n            if (!option.usage) {\n                break;\n            }\n\n            var usageString = \"  \";\n            var type = option.type ? \" \" + option.type.toUpperCase() : \"\";\n\n            if (option.short) {\n                usageString += this.DEFAULT_SHORT_FLAG + option.short + type + \", \";\n            }\n\n            usageString += this.DEFAULT_LONG_FLAG + option.name + type;\n\n            output.push([usageString, option.usage]);\n\n            if (usageString.length > maxLength) {\n                maxLength = usageString.length;\n            }\n        }\n\n        output.push([\"  @<file>\", \"Insert command line options and files from a file.\"]);\n\n        // Print padded output\n        for (var i = 0; i < output.length; i++) {\n            this.host.printLine(output[i][0] + (new Array(maxLength - output[i][0].length + 3)).join(\" \") + output[i][1]);\n        }\n    }\n\n    public option(name: string, config: IOptions, short?: string) {\n        if (!config) {\n            config = <any>short;\n            short = null;\n        }\n\n        config.name = name;\n        config.short = short;\n        config.flag = false;\n\n        this.options.push(config);\n    }\n\n    public flag(name: string, config: IOptions, short?: string) {\n        if (!config) {\n            config = <any>short;\n            short = null;\n        }\n\n        config.name = name;\n        config.short = short;\n        config.flag = true\n\n        this.options.push(config);\n    }\n\n    // Parse an arguments string\n    public parseString(argString: string) {\n        var position = 0;\n        var tokens = argString.match(/\\s+|\"|[^\\s\"]+/g);\n\n        function peek() {\n            return tokens[position];\n        }\n\n        function consume() {\n            return tokens[position++];\n        }\n\n        function consumeQuotedString() {\n            var value = '';\n            consume(); // skip opening quote.\n\n            var token = peek();\n\n            while (token && token !== '\"') {\n                consume();\n\n                value += token;\n\n                token = peek();\n            }\n\n            consume(); // skip ending quote;\n\n            return value;\n        }\n\n        var args: string[] = [];\n        var currentArg = '';\n\n        while (position < tokens.length) {\n            var token = peek();\n\n            if (token === '\"') {\n                currentArg += consumeQuotedString();\n            } else if (token.match(/\\s/)) {\n                if (currentArg.length > 0) {\n                    args.push(currentArg);\n                    currentArg = '';\n                }\n\n                consume();\n            } else {\n                consume();\n                currentArg += token;\n            }\n        }\n\n        if (currentArg.length > 0) {\n            args.push(currentArg);\n        }\n\n        this.parse(args);\n    }\n\n    // Parse arguments as they come from the platform: split into arguments.\n    public parse(args: string[]) {\n        var position = 0;\n\n        function consume() {\n            return args[position++];\n        }\n\n        while (position < args.length) {\n            var current = consume();\n            var match = current.match(/^(--?|@)(.*)/);\n            var value = null;\n\n            if (match) {\n                if (match[1] === '@') {\n                    this.parseString(this.host.readFile(match[2]));\n                } else {\n                    var arg = match[2];\n                    var option = this.findOption(arg);\n\n                    if (option === null) {\n                        this.host.printLine(\"Unknown option '\" + arg +\"'\");\n                        this.host.printLine(\"Use the '--help' flag to see options\");\n                    } else {\n                        if (!option.flag)\n                            value = consume();\n\n                        option.set(value);\n                    }\n                }\n            } else {\n                this.unnamed.push(current);\n            }\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export enum TypeContext {\n        NoTypes = 0,\n        ArraySuffix = 1,\n        Primitive = 2,\n        Named = 4,\n        AllSimpleTypes = Primitive | Named,\n        AllTypes = Primitive | Named | ArraySuffix,\n    }\n\n    export enum ParseState {\n        None,\n        StartScript,\n        StartStatementList,\n        StartStatement,\n        StartFncDecl,\n        FncDeclName,\n        FncDeclArgs,\n        FncDeclReturnType,\n        ForInit,\n        ForInitAfterVar,\n        ForCondStart,\n        EndStmtList,\n        EndScript,\n    }\n\n    export interface IStatementInfo {\n        stmt: Statement;\n        labels: ASTList;\n    }\n\n    export interface ILambdaArgumentContext {\n        preProcessedLambdaArgs: AST;\n    }\n\n    export class QuickParseResult {\n        constructor (public Script: Script, public endLexState: LexState) { }\n    }\n\n    export class Parser {\n        private varLists: ASTList[] = [];\n        private scopeLists: ASTList[] = [];\n        private staticsLists: ASTList[] = [];\n\n        private scanner: IScanner = new Scanner();\n        private currentToken: Token = null;\n\n        private needTerminator = false;\n\n        // TODO: consolidate these\n        private inFunction = false;\n        private inInterfaceDecl = false;\n        public currentClassDecl: NamedDeclaration = null;\n\n        private inFncDecl = false;  // this is only for FuncDecls - not constructors, like inFnc\n        private anonId = new Identifier(\"_anonymous\");\n        public style_requireSemi = false;\n        public style_funcInLoop = true;\n        private incremental = false;\n        public errorRecovery = false;\n        public outfile: ITextWriter = undefined;\n        public errorCallback: (minChar: number, charLen: number, message: string, unit: number) =>void = null;\n        private state: ParseState = ParseState.StartStatementList;\n        private ambientModule = false;\n        private ambientClass = false;\n        private topLevel = true;\n        private allowImportDeclaration = true;\n        private currentUnitIndex = (-1);\n        private prevIDTok: Token = null;\n        private statementInfoStack: IStatementInfo[] = new IStatementInfo[];\n        private hasTopLevelImportOrExport = false; // for imports, only true if it's a dynamic module\n        private strictMode = false;\n        private nestingLevel = 0;\n        private prevExpr: AST = null;\n        private currentClassDefinition: ClassDeclaration = null;\n        private parsingClassConstructorDefinition = false;\n        private parsingDeclareFile = false;\n        private amdDependencies: string[] = [];\n        public inferPropertiesFromThisAssignment = false;\n        public requiresExtendsBlock = false;\n\n        private resetStmtStack() {\n            this.statementInfoStack = new IStatementInfo[];\n        }\n\n        private inLoop() {\n            for (var j = this.statementInfoStack.length - 1; j >= 0; j--) {\n                if (this.statementInfoStack[j].stmt.isLoop()) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private pushStmt(stmt: Statement, labels: ASTList) {\n            // allocate here to avoid always storing this information in statements\n            var info = { stmt: stmt, labels: labels };\n            this.statementInfoStack.push(info);\n        }\n\n        private popStmt(): IStatementInfo {\n            return this.statementInfoStack.pop();\n        }\n\n        private resolveJumpTarget(jump: Jump): void {\n            var resolvedTarget = AST.getResolvedIdentifierName(jump.target);\n            var len = this.statementInfoStack.length;\n            for (var i = len - 1; i >= 0; i--) {\n                var info = this.statementInfoStack[i];\n                if (jump.target) {\n                    if (info.labels && (info.labels.members.length > 0)) {\n                        for (var j = 0, labLen = info.labels.members.length; j < labLen; j++) {\n                            var label = <Label>info.labels.members[j];\n                            if (label.id.text == resolvedTarget) {\n                                jump.setResolvedTarget(this, info.stmt);\n                                return;\n                            }\n                        }\n                    }\n                }\n                else {\n                    if (info.stmt.isLoop()) {\n                        jump.setResolvedTarget(this, info.stmt);\n                        return;\n                    }\n                    else if ((info.stmt.nodeType == NodeType.Switch) && (jump.nodeType == NodeType.Break)) {\n                        jump.setResolvedTarget(this, info.stmt);\n                        return;\n                    }\n                }\n            }\n            // no luck\n            if (jump.target) {\n                this.reportParseError(\"could not find enclosing statement with label \" + jump.target);\n            }\n            else {\n                if (jump.nodeType == NodeType.Break) {\n                    this.reportParseError(\"break statement requires enclosing loop or switch\");\n                }\n                else {\n                    this.reportParseError(\"continue statement requires enclosing loop\");\n                }\n            }\n        }\n\n        public setErrorRecovery(outfile: ITextWriter) {\n            this.outfile = outfile;\n            this.errorRecovery = true;\n        }\n\n        public getSourceLineCol(lineCol: ILineCol, minChar: number): void {\n            getSourceLineColFromMap(lineCol, minChar, this.scanner.lineMap);\n        }\n\n        private createRef(text: string, hasEscapeSequence: bool, minChar: number): Identifier {\n            var id = new Identifier(text, hasEscapeSequence);\n            id.minChar = minChar;\n            return id;\n        }\n\n        private reportParseStyleError(message: string) {\n            this.reportParseError(\"STYLE: \" + message);\n        }\n\n        public reportParseError(message: string, startPos = this.scanner.startPos, pos = this.scanner.pos) {\n            var len = Math.max(1, pos - startPos);\n            if (this.errorCallback) {\n                this.errorCallback(startPos, len, message, this.currentUnitIndex);\n            }\n            else if (this.errorRecovery) {\n                var lineCol = { line: -1, col: -1 };\n                this.getSourceLineCol(lineCol, startPos);\n                if (this.outfile) {\n                    this.outfile.WriteLine(\"// \" + this.fname + \" (\" + lineCol.line + \",\" + lineCol.col + \"): \" + message);\n                }\n            }\n            else {\n                throw new SyntaxError(this.fname + \" (\" + this.scanner.line + \",\" + this.scanner.col + \"): \" + message);\n            }\n        }\n\n        private checkNextToken(tokenId: TokenID, errorRecoverySet: ErrorRecoverySet, errorText: string = null): void {\n            this.currentToken = this.scanner.scan();\n            this.checkCurrentToken(tokenId, errorRecoverySet, errorText);\n        }\n\n        private skip(errorRecoverySet: ErrorRecoverySet) {\n            errorRecoverySet |= ErrorRecoverySet.EOF;\n            var ersTok = ErrorRecoverySet.None;\n            var tokenInfo = lookupToken(this.currentToken.tokenId);\n            if (tokenInfo != undefined) {\n                ersTok = tokenInfo.ers;\n            }\n            var pendingRightCurlies = 0;\n            while (((ersTok & errorRecoverySet) == ErrorRecoverySet.None) ||\n                   (this.currentToken.tokenId == TokenID.CloseBrace) && (pendingRightCurlies > 0)) {\n                if (this.currentToken.tokenId == TokenID.OpenBrace) {\n                    pendingRightCurlies++;\n                }\n                else if (this.currentToken.tokenId == TokenID.CloseBrace) {\n                    pendingRightCurlies--;\n                }\n                this.currentToken = this.scanner.scan();\n                ersTok = ErrorRecoverySet.None;\n                tokenInfo = lookupToken(this.currentToken.tokenId);\n                if (tokenInfo != undefined) {\n                    ersTok = tokenInfo.ers;\n                }\n                // TODO: regex rescan \n            }\n        }\n\n        private checkCurrentToken(tokenId: TokenID, errorRecoverySet: ErrorRecoverySet, errorText: string = null): void {\n            if (this.currentToken.tokenId != tokenId) {\n                errorText = errorText == null ? (\"Expected '\" + tokenTable[tokenId].text + \"'\") : errorText;\n                this.reportParseError(errorText);\n                if (this.errorRecovery) {\n                    this.skip(errorRecoverySet);\n                }\n            }\n            else {\n                this.currentToken = this.scanner.scan();\n            }\n        }\n\n        private pushDeclLists() {\n            this.staticsLists.push(new ASTList());\n            this.varLists.push(new ASTList());\n            this.scopeLists.push(new ASTList());\n        }\n\n        private popDeclLists() {\n            this.staticsLists.pop();\n            this.varLists.pop();\n            this.scopeLists.pop();\n        }\n\n        private topVarList() {\n            return this.varLists[this.varLists.length - 1];\n        }\n\n        private topScopeList() {\n            return this.scopeLists[this.scopeLists.length - 1];\n        }\n\n        private topStaticsList() {\n            return this.staticsLists[this.staticsLists.length - 1];\n        }\n\n        private parseComment(comment: CommentToken) {\n            if (comment) {\n                var c: Comment = new Comment(comment.value, comment.isBlock, comment.endsLine);\n                c.minChar = comment.startPos;\n                c.limChar = comment.startPos + comment.value.length;\n                var lineCol = { line: -1, col: -1 };\n                this.getSourceLineCol(lineCol, c.minChar);\n                c.minLine = lineCol.line;\n                this.getSourceLineCol(lineCol, c.limChar);\n                c.limLine = lineCol.line;\n\n                if (!comment.isBlock && comment.value.length > 3 && comment.value.substring(0, 3) == \"///\") {\n                    var dependencyPath = getAdditionalDependencyPath(comment.value);\n\n                    if (dependencyPath) {\n                        this.amdDependencies.push(dependencyPath);\n                    }\n\n                    if (getImplicitImport(comment.value)) {\n                        this.hasTopLevelImportOrExport = true;\n                    }\n                }\n\n                return c;\n            }\n            else {\n                return null;\n            }\n        }\n\n        private parseCommentsInner(comments: CommentToken[]) {\n            if (comments) {\n                var commentASTs: Comment[] = new Comment[];\n                for (var i = 0; i < comments.length; i++) {\n                    commentASTs.push(this.parseComment(comments[i]));\n                }\n                return commentASTs;\n            } else {\n                return null;\n            }\n        }\n\n        private parseComments() {\n            var comments = this.scanner.getComments();\n            return this.parseCommentsInner(comments);\n        }\n\n        private parseCommentsForLine(line: number) {\n            var comments = this.scanner.getCommentsForLine(line);\n\n            return this.parseCommentsInner(comments);\n        }\n\n        private combineComments(comment1: Comment[], comment2: Comment[]) {\n            if (comment1 == null) {\n                return comment2;\n            }\n            else if (comment2 == null) {\n                return comment1;\n            }\n            else {\n                return comment1.concat(comment2);\n            }\n        }\n\n        private parseEnumDecl(errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers): ModuleDeclaration {\n            var leftCurlyCount = this.scanner.leftCurlyCount;\n            var rightCurlyCount = this.scanner.rightCurlyCount;\n\n            var name: Identifier = null;\n            if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                name = Identifier.fromToken(this.currentToken);\n                name.minChar = this.scanner.startPos;\n                name.limChar = this.scanner.pos;\n                this.currentToken = this.scanner.scan();\n            }\n            else {\n                this.reportParseError(\"Enum declaration requires identifier\");\n                if (this.errorRecovery) {\n                    name = new MissingIdentifier();\n                    name.minChar = this.scanner.startPos;\n                    name.limChar = this.scanner.startPos;\n                    name.flags |= ASTFlags.Error;\n                }\n            }\n\n            var membersMinChar = this.scanner.startPos;\n            this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.ID);\n            this.pushDeclLists();\n            var members = new ASTList();\n            members.minChar = membersMinChar;\n            var mapDecl = new VarDecl(new Identifier(\"_map\"), 0);\n            mapDecl.varFlags |= VarFlags.Exported;\n            mapDecl.varFlags |= VarFlags.Private;\n\n            // REVIEW: Is this still necessary?\n            mapDecl.varFlags |= (VarFlags.Property | VarFlags.Public);\n            mapDecl.init = new UnaryExpression(NodeType.ArrayLit, null);\n            members.append(mapDecl);\n            var lastValue: NumberLiteral = null;\n            for (; ;) {\n                var minChar = this.scanner.startPos;\n                var limChar;\n                var memberName: Identifier = null;\n                var memberValue: AST = null;\n                var preComments = null;\n                var postComments = null;\n\n                if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToIDName(this.currentToken)) {\n                    memberName = Identifier.fromToken(this.currentToken);\n                    memberName.minChar = this.scanner.startPos;\n                    memberName.limChar = this.scanner.pos;\n                }\n                else if (this.currentToken.tokenId == TokenID.CloseBrace) {\n                    break;\n                }\n                else {\n                    this.reportParseError(\"Expected identifer of enum member\");\n                    if (this.errorRecovery) {\n                        memberName = new MissingIdentifier();\n                        memberName.minChar = this.scanner.startPos;\n                        memberName.limChar = this.scanner.startPos;\n                        memberName.flags |= ASTFlags.Error;\n                    }\n                }\n\n                limChar = this.scanner.pos;\n                preComments = this.parseComments();\n                this.currentToken = this.scanner.scan();\n                postComments = this.parseComments();\n\n                if (this.currentToken.tokenId == TokenID.Equals) {\n                    this.currentToken = this.scanner.scan();\n                    memberValue = this.parseExpr(errorRecoverySet, OperatorPrecedence.Comma, true,\n                                          TypeContext.NoTypes);\n                    lastValue = <NumberLiteral>memberValue;\n                    limChar = memberValue.limChar;\n                }\n                else {\n                    if (lastValue == null) {\n                        memberValue = new NumberLiteral(0);\n                        lastValue = <NumberLiteral>memberValue;\n                    }\n                    else {\n                        memberValue = new NumberLiteral(lastValue.value + 1);\n                        lastValue = <NumberLiteral>memberValue;\n                    }\n                    var map: BinaryExpression =\n                        new BinaryExpression(NodeType.Asg,\n                                             new BinaryExpression(NodeType.Index,\n                                                                  new Identifier(\"_map\"),\n                                                                  memberValue),\n                                             new StringLiteral('\"' + memberName.actualText + '\"'));\n                    members.append(map);\n                }\n                var member = new VarDecl(memberName, this.nestingLevel);\n                member.minChar = minChar;\n                member.limChar = limChar;\n                member.init = memberValue;\n                // Note: Leave minChar, limChar as \"-1\" on typeExpr as this is a parsing artifact.\n                member.typeExpr = new TypeReference(this.createRef(name.actualText, name.hasEscapeSequence, -1), 0);\n                member.varFlags |= (VarFlags.Readonly | VarFlags.Property);\n                if (memberValue.nodeType == NodeType.NumberLit) {\n                    member.varFlags |= VarFlags.Constant;\n                }\n                member.preComments = preComments;\n                members.append(member);\n                member.postComments = postComments;\n                // all enum members are exported\n                member.varFlags |= VarFlags.Exported;\n\n                if (this.currentToken.tokenId == TokenID.Comma) {\n                    this.currentToken = this.scanner.scan();\n                    member.postComments = this.combineComments(member.postComments, this.parseCommentsForLine(this.scanner.prevLine));\n                    if ((this.currentToken.tokenId == TokenID.Identifier) || (convertTokToIDName(this.currentToken))) {\n                        continue;\n                    }\n                }\n                break;\n            }\n            var endingToken = new ASTSpan();\n            endingToken.minChar = this.scanner.startPos;\n            endingToken.limChar = this.scanner.pos;\n\n            this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n            members.limChar = this.scanner.lastTokenLimChar();\n            var modDecl = new ModuleDeclaration(name, members, this.topVarList(), this.topScopeList(), endingToken);\n            modDecl.modFlags |= ModuleFlags.IsEnum;\n            this.popDeclLists();\n\n            modDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n            modDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n            return modDecl;\n        }\n\n        private parseDottedName(enclosedList: AST[]): void {\n            this.currentToken = this.scanner.scan();\n            if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                var id = Identifier.fromToken(this.currentToken);\n                id.preComments = this.parseComments();\n                enclosedList[enclosedList.length] = id;\n                id.minChar = this.scanner.startPos;\n                id.limChar = this.scanner.pos;\n                this.currentToken = this.scanner.scan();\n                if (this.currentToken.tokenId == TokenID.Dot) {\n                    this.parseDottedName(enclosedList);\n                }\n            }\n            else {\n                this.reportParseError(\"need identifier after '.'\");\n            }\n        }\n\n        // REVIEW: This is much more lenient than the spec - we're basically just checking to see if the\n        // path is rooted or contains an extension, not if it could potentially be a bogus file path\n        private isValidImportPath(importPath: string) {\n            importPath = stripQuotes(importPath);\n\n            if (!importPath ||\n                importPath.indexOf(':') != -1 || \n                importPath.indexOf('\\\\') != -1 ||\n                //(importPath.indexOf('.') != -1 && importPath.charAt(0) != '.') ||\n                importPath.charAt(0) == '/') {\n                return false;\n            }\n            return true;\n        }\n\n        private parseImportDeclaration(errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers): ImportDeclaration {\n\n            var name: Identifier = null;\n            var alias: AST = null;\n            var importDecl: ImportDeclaration = null;\n            var minChar = this.scanner.startPos;\n            var isDynamicImport = false;\n\n            this.currentToken = this.scanner.scan();\n\n            if (this.currentToken.tokenId == TokenID.Identifier || convertTokToID(this.currentToken, this.strictMode)) {\n                name = Identifier.fromToken(this.currentToken);\n            }\n            else {\n                this.reportParseError(\"Expected identifer after 'import'\");\n                name = new MissingIdentifier();\n            }\n\n            name.minChar = this.scanner.startPos;\n            name.limChar = this.scanner.pos;\n\n            this.currentToken = this.scanner.scan();\n\n            this.checkCurrentToken(TokenID.Equals, errorRecoverySet | ErrorRecoverySet.ID);\n\n            var aliasPreComments = this.parseComments();\n\n            var limChar;\n            if (this.currentToken.tokenId == TokenID.Identifier || convertTokToID(this.currentToken, this.strictMode)) {\n\n                if (this.currentToken.tokenId == TokenID.Module) {\n                    limChar = this.scanner.pos;\n                    this.currentToken = this.scanner.scan();\n                    if (this.currentToken.tokenId == TokenID.OpenParen) {\n                        this.currentToken = this.scanner.scan();\n\n                        if (this.currentToken.tokenId == TokenID.StringLiteral || this.currentToken.tokenId == TokenID.Identifier || convertTokToID(this.currentToken, this.strictMode)) {\n\n                            if (this.currentToken.tokenId == TokenID.StringLiteral) {\n\n                                if (this.topLevel) {\n                                    this.hasTopLevelImportOrExport = true;\n                                } else if (!this.allowImportDeclaration) {\n                                    this.reportParseError(\"Import declaration of external module is permitted only in global or top level dynamic modules\");\n                                }\n\n                                var aliasText = this.currentToken.getText();\n                                alias = Identifier.fromToken(this.currentToken);\n                                alias.minChar = this.scanner.startPos;\n                                alias.limChar = this.scanner.pos;\n\n                                if (!this.isValidImportPath((<Identifier>alias).text)) {\n                                    this.reportParseError(\"Invalid import path\");\n                                }\n\n                                isDynamicImport = true;\n                                this.currentToken = this.scanner.scan();\n                                    \n                                alias.preComments = aliasPreComments;\n                            }\n                            else {\n                                alias = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon,\n                                            OperatorPrecedence.Assignment, true,\n                                            TypeContext.NoTypes);\n                                    \n                                alias.preComments = aliasPreComments;\n                            }\n                        }\n\n                        limChar = this.scanner.pos;\n                        this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.ID);\n\n                        if (alias) {\n                            alias.postComments = this.parseComments();\n                        }\n                    }\n                }\n                else {\n                    alias = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon,\n                                            OperatorPrecedence.Assignment, true,\n                                            TypeContext.NoTypes);\n                    limChar = this.scanner.pos; // Include semicolon if needed\n                }\n            }\n            else {\n                this.reportParseError(\"Expected module name\");\n                alias = new MissingIdentifier();\n                alias.minChar = this.scanner.startPos;\n                if (this.currentToken.tokenId == TokenID.Semicolon) {\n                    alias.limChar = this.scanner.startPos;\n                } else {\n                    alias.limChar = this.scanner.pos;\n                    this.currentToken = this.scanner.scan();\n                }\n                alias.flags |= ASTFlags.Error;\n                limChar = alias.limChar;\n            }\n\n            importDecl = new ImportDeclaration(name, alias);\n            importDecl.isDynamicImport = isDynamicImport;\n\n            importDecl.minChar = minChar;\n            importDecl.limChar = limChar;\n\n            return importDecl;\n        }\n\n        private parseModuleDecl(errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers, preComments: Comment[]): ModuleDeclaration {\n            var leftCurlyCount = this.scanner.leftCurlyCount;\n            var rightCurlyCount = this.scanner.rightCurlyCount;\n\n            var svAmbient = this.ambientModule;\n            var svTopLevel = this.topLevel;\n            this.topLevel = false;\n            if (this.parsingDeclareFile || svAmbient || hasFlag(modifiers, Modifiers.Ambient)) {\n                this.ambientModule = true;\n            }\n\n            this.currentToken = this.scanner.scan();\n            var name: AST = null;\n            var enclosedList: AST[] = null;\n            this.pushDeclLists();\n            var minChar = this.scanner.startPos;\n            var isDynamicMod = false;\n\n            if ((this.currentToken.tokenId == TokenID.Identifier) || (this.currentToken.tokenId == TokenID.StringLiteral) || (!isPrimitiveTypeToken(this.currentToken) && convertTokToID(this.currentToken, this.strictMode))) {\n                var nameText = this.currentToken.getText();\n\n                if (this.currentToken.tokenId == TokenID.StringLiteral) {\n                    isDynamicMod = true;\n                    if (!this.ambientModule) {\n                        this.reportParseError(\"Only ambient dynamic modules may have string literal names\");\n                    }\n\n                    if (!svTopLevel) {\n                        this.reportParseError(\"Dynamic modules may not be nested within other modules\");\n                    }\n                }\n\n                name = Identifier.fromToken(this.currentToken);\n                name.minChar = this.scanner.startPos;\n                name.limChar = this.scanner.pos;\n\n                this.currentToken = this.scanner.scan();\n            }\n            else if (this.currentToken.tokenId == TokenID.OpenBrace) {\n                this.reportParseError(\"Module name missing\");\n                name = new Identifier(\"\");\n                // \"fake\" position of where the ID would be\n                name.minChar = minChar;\n                name.limChar = minChar;\n            }\n\n            if (this.currentToken.tokenId == TokenID.Dot) {\n                enclosedList = new AST[];\n                this.parseDottedName(enclosedList);\n            }\n\n            if (name == null) {\n                name = new MissingIdentifier();\n            }\n\n            var moduleBody = new ASTList();\n            var bodyMinChar = this.scanner.startPos;\n            this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.ID);\n\n            if (svTopLevel && isDynamicMod) {\n                this.allowImportDeclaration = true;\n            } else {\n                this.allowImportDeclaration = false;\n            }\n            this.parseStatementList(\n                errorRecoverySet | ErrorRecoverySet.RCurly, moduleBody,\n                /*sourceElements:*/ true, /*noLeadingCase:*/ true, AllowedElements.Global, modifiers);\n            moduleBody.minChar = bodyMinChar;\n            moduleBody.limChar = this.scanner.pos;\n\n            var endingToken = new ASTSpan();\n            endingToken.minChar = this.scanner.startPos;\n            endingToken.limChar = this.scanner.pos;\n            this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n            var limChar = this.scanner.lastTokenLimChar();\n            var moduleDecl: ModuleDeclaration;\n\n            this.allowImportDeclaration = svTopLevel;\n\n            if (enclosedList && (enclosedList.length > 0)) {\n                var len = enclosedList.length;\n                var innerName = <Identifier>enclosedList[len - 1];\n                var innerDecl = new ModuleDeclaration(innerName, moduleBody, this.topVarList(),\n                                                this.topScopeList(), endingToken);\n                innerDecl.preComments = preComments;\n\n                if (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)) {\n                    innerDecl.modFlags |= ModuleFlags.Ambient;\n                }\n\n                innerDecl.modFlags |= ModuleFlags.Exported;\n\n                // REVIEW: will also possibly need to re-parent comments as well\n                innerDecl.minChar = minChar;\n                innerDecl.limChar = limChar;\n\n                this.popDeclLists();\n                var outerModBod: ASTList;\n                for (var i = len - 2; i >= 0; i--) {\n                    outerModBod = new ASTList();\n                    outerModBod.append(innerDecl);\n                    innerName = <Identifier>enclosedList[i];\n                    innerDecl = new ModuleDeclaration(innerName, outerModBod, new ASTList(),\n                                                new ASTList(), endingToken);\n                    outerModBod.minChar = innerDecl.minChar = minChar;\n                    outerModBod.limChar = innerDecl.limChar = limChar;\n\n                    if (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)) {\n                        innerDecl.modFlags |= ModuleFlags.Ambient;\n                    }\n\n                    innerDecl.modFlags |= ModuleFlags.Exported;\n                }\n                outerModBod = new ASTList();\n                outerModBod.append(innerDecl);\n                outerModBod.minChar = minChar;\n                outerModBod.limChar = limChar;\n                moduleDecl = new ModuleDeclaration(<Identifier>name, outerModBod, new ASTList(),\n                                            new ASTList(), endingToken);\n            }\n            else {\n                moduleDecl = new ModuleDeclaration(<Identifier>name, moduleBody, this.topVarList(), this.topScopeList(), endingToken);\n                moduleDecl.preComments = preComments;\n                this.popDeclLists();\n            }\n\n            if (this.parsingDeclareFile || svAmbient || hasFlag(modifiers, Modifiers.Ambient)) {\n                moduleDecl.modFlags |= ModuleFlags.Ambient;\n            }\n            if (svAmbient || hasFlag(modifiers, Modifiers.Exported)) {\n                moduleDecl.modFlags |= ModuleFlags.Exported;\n            }\n            if (isDynamicMod) {\n                moduleDecl.modFlags |= ModuleFlags.IsDynamic;\n            }\n\n            this.ambientModule = svAmbient;\n\n            this.topLevel = svTopLevel;\n            moduleDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n            moduleDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n            moduleDecl.limChar = moduleBody.limChar;\n            return moduleDecl;\n        }\n\n        private parseTypeReferenceTail(errorRecoverySet: ErrorRecoverySet, minChar: number, term: AST): TypeReference {\n            var result = new TypeReference(term, 0);\n            result.minChar = minChar;\n            while (this.currentToken.tokenId == TokenID.OpenBracket) {\n                this.currentToken = this.scanner.scan();\n                result.arrayCount++;\n                this.checkCurrentToken(TokenID.CloseBracket, errorRecoverySet | ErrorRecoverySet.LBrack);\n            }\n            result.limChar = this.scanner.lastTokenLimChar();\n            return result;\n        }\n\n        // REVIEW: Consider renaming to parseTypeName.\n        private parseNamedType(errorRecoverySet: ErrorRecoverySet, minChar: number, term: AST, tail: bool): AST {\n            this.currentToken = this.scanner.scan();\n            if (this.currentToken.tokenId == TokenID.Dot) {\n                var curpos = this.scanner.pos;\n                this.currentToken = this.scanner.scan();\n                // Don't allow reserved words if immediately after a new line and error recovery is enabled\n                if ((this.currentToken.tokenId == TokenID.Identifier) || ((!this.errorRecovery || !this.scanner.lastTokenHadNewline()) && convertTokToID(this.currentToken, this.strictMode))) {\n                    var op2 = Identifier.fromToken(this.currentToken);\n                    op2.minChar = this.scanner.startPos;\n                    op2.limChar = this.scanner.pos;\n                    var dotNode = new BinaryExpression(NodeType.Dot, term, op2);\n                    dotNode.minChar = term.minChar;\n                    dotNode.limChar = op2.limChar;\n                    return this.parseNamedType(errorRecoverySet, minChar,\n                                            dotNode, tail);\n                }\n                else {\n                    this.reportParseError(\"need identifier after '.'\");\n                    if (this.errorRecovery) {\n                        term.flags |= ASTFlags.DotLHS;\n                        // We set \"limChar\" to be slightly innacurate for completion list behavior\n                        // (last AST node from \"quickParse\" will match DotLHS and be at end of file position)\n                        // This is to match the behavior of TokenId.Dot processing in parsePostfixOperators.\n                        term.limChar = this.scanner.lastTokenLimChar();\n                        return term;\n                    }\n                    else {\n                        var eop2 = new MissingIdentifier();\n                        eop2.minChar = this.scanner.pos;\n                        eop2.limChar = this.scanner.pos;\n                        var edotNode = new BinaryExpression(NodeType.Dot, term, eop2);\n                        edotNode.flags |= ASTFlags.Error;\n                        edotNode.minChar = term.minChar;\n                        edotNode.limChar = eop2.limChar;\n                        return this.parseNamedType(errorRecoverySet, minChar,\n                                                edotNode, tail);\n                    }\n                }\n            }\n            else {\n                if (tail) {\n                    return this.parseTypeReferenceTail(errorRecoverySet, minChar, term);\n                }\n                else {\n                    return term;\n                }\n            }\n        }\n\n        // REVIEW: Reconsider renaming this to parseType to match the grammar.\n        private parseTypeReference(errorRecoverySet: ErrorRecoverySet, allowVoid: bool): AST {\n            var minChar = this.scanner.startPos;\n            var isConstructorMember = false;\n\n            switch (this.currentToken.tokenId) {\n                case TokenID.Void:\n                    if (!allowVoid) {\n                        this.reportParseError(\"void not a valid type in this context\");\n                    }\n                // Intentional fall-through\n                case TokenID.Any:\n                case TokenID.Number:\n                case TokenID.Bool:\n                case TokenID.String: {\n                    var text = tokenTable[this.currentToken.tokenId].text;\n                    var predefinedIdentifier = new Identifier(text);\n                    predefinedIdentifier.minChar = minChar;\n                    predefinedIdentifier.limChar = this.scanner.pos;\n                    this.currentToken = this.scanner.scan();\n                    return this.parseTypeReferenceTail(errorRecoverySet, minChar, predefinedIdentifier);\n                }\n\n                case TokenID.Identifier:\n                    var ident = this.createRef(this.currentToken.getText(), (<IdentifierToken>this.currentToken).hasEscapeSequence, minChar);\n                    ident.limChar = this.scanner.pos;\n                    return this.parseNamedType(errorRecoverySet, minChar, ident, true);\n\n                case TokenID.OpenBrace:\n                    return this.parseObjectType(minChar, errorRecoverySet);\n\n                case TokenID.New:\n                    this.currentToken = this.scanner.scan();\n                    // can't use chkCurrentTok, since we don't want to advance the token\n                    if (this.currentToken.tokenId != TokenID.OpenParen) {\n                        this.reportParseError(\"Expected '('\");\n                    }\n                    else {\n                        isConstructorMember = true;\n                        // fall through...\n                    }\n\n                case TokenID.OpenParen: {\n                    // ( formals ) => type\n                    var formals = new ASTList();\n                    var variableArgList =\n                        this.parseFormalParameterList(errorRecoverySet | ErrorRecoverySet.RParen,\n                                            formals, false, true, false, false, false, false, null, true);\n                    this.checkCurrentToken(TokenID.EqualsGreaterThan, errorRecoverySet);\n                    var returnType = this.parseTypeReference(errorRecoverySet, true);\n                    var funcDecl = new FuncDecl(null, null, false, formals, null, null, null,\n                                                NodeType.FuncDecl);\n                    funcDecl.returnTypeAnnotation = returnType;\n                    funcDecl.variableArgList = variableArgList;\n                    funcDecl.fncFlags |= FncFlags.Signature;\n\n                    if (isConstructorMember) {\n                        funcDecl.fncFlags |= FncFlags.ConstructMember;\n                        funcDecl.hint = \"_construct\";\n                        funcDecl.classDecl = null;\n                    }\n                    funcDecl.minChar = minChar;\n                    return this.parseTypeReferenceTail(errorRecoverySet, minChar, funcDecl);\n                }\n\n                default:\n                    this.reportParseError(\"Expected type name\");\n                    var etr = new TypeReference(null, 0);\n                    etr.flags |= ASTFlags.Error;\n                    etr.minChar = this.scanner.pos;\n                    etr.limChar = this.scanner.pos;\n                    return etr;\n            }\n        }\n\n        private parseObjectType(minChar: number, errorRecoverySet: ErrorRecoverySet): TypeReference {\n            this.currentToken = this.scanner.scan();\n\n            var members = new ASTList();\n            members.minChar = minChar;\n\n            var prevInInterfaceDecl = this.inInterfaceDecl;\n            this.inInterfaceDecl = true;\n            this.parseTypeMemberList(errorRecoverySet | ErrorRecoverySet.RCurly, members);\n            this.inInterfaceDecl = prevInInterfaceDecl;\n\n            this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n            // REVIEW: We're parsing an ObjectType, but we give a NodeType of Interface here.\n            var interfaceDecl = new InterfaceDeclaration(\n                this.anonId, members, /*extends:*/ null, /*implementsL*/ null);\n\n            interfaceDecl.minChar = minChar;\n            interfaceDecl.limChar = members.limChar;    // \"}\"\n\n            return this.parseTypeReferenceTail(errorRecoverySet, minChar, interfaceDecl);\n        }\n\n        private parseFunctionBlock(errorRecoverySet: ErrorRecoverySet,\n                                   allowedElements: AllowedElements,\n                                   parentModifiers: Modifiers,\n                                   bod: ASTList,\n                                   bodMinChar: number): void {\n            this.state = ParseState.StartStatementList;\n            this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.StmtStart);\n            var savedInFunction = this.inFunction;\n            this.inFunction = true;\n            this.parseStatementList(\n                errorRecoverySet | ErrorRecoverySet.RCurly | ErrorRecoverySet.StmtStart,\n                bod, /*sourceElements:*/ true, /*noLeadingCase:*/ false, allowedElements, parentModifiers);\n            bod.minChar = bodMinChar;\n            bod.limChar = this.scanner.pos;\n            this.inFunction = savedInFunction;\n            var ec = new EndCode();\n            ec.minChar = bod.limChar;\n            ec.limChar = ec.minChar;\n            bod.append(ec);\n        }\n\n        private parseFunctionStatements(errorRecoverySet: ErrorRecoverySet,\n                                        name: Identifier,\n                                        isConstructor: bool,\n                                        isMethod: bool,\n                                        args: ASTList,\n                                        allowedElements: AllowedElements,\n                                        minChar: number,\n                                        requiresSignature: bool,\n                                        parentModifiers: Modifiers) {\n\n            this.pushDeclLists();\n            // start new statement stack\n            var svStmtStack = this.statementInfoStack;\n            this.resetStmtStack();\n\n            var bod: ASTList = null;\n            var wasShorthand = false;\n            var isAnonLambda = false;\n            var limChar: number;\n\n            if (requiresSignature) {\n                // If we require a signature, but they provided a block, then give an error, but\n                // still consume the block.\n                limChar = this.scanner.pos;\n                if (this.currentToken.tokenId === TokenID.OpenBrace) {\n                    this.reportParseError(\"Function declarations are not permitted within interfaces, ambient modules or classes\")\n                    bod = new ASTList();\n                    var bodMinChar = this.scanner.startPos;\n\n                    this.parseFunctionBlock(errorRecoverySet, allowedElements, parentModifiers, bod, bodMinChar);\n                    this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n                    // If there's also a semicolon, then just skip over it.  We don't want to report an \n                    // additional error here.\n                    if (this.currentToken.tokenId === TokenID.Semicolon) {\n                        this.currentToken = this.scanner.scan();\n                    }\n                }\n                else {\n                    this.checkCurrentToken(TokenID.Semicolon, errorRecoverySet, \"Expected ';'\");\n                }\n            }\n            else {\n                bod = new ASTList();\n                var bodMinChar = this.scanner.startPos;\n                if (this.currentToken.tokenId == TokenID.EqualsGreaterThan) {\n                    if (isMethod) {\n                        this.reportParseError(\"'=>' may not be used for class methods\");\n                    }\n                    wasShorthand = true;\n                    this.currentToken = this.scanner.scan();\n                }\n\n                if (wasShorthand && this.currentToken.tokenId != TokenID.OpenBrace) {\n                    var retExpr = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon,\n                                            OperatorPrecedence.Assignment, true,\n                                            TypeContext.NoTypes);\n                    var retStmt = new ReturnStatement();\n                    retStmt.returnExpression = retExpr;\n                    retStmt.minChar = retExpr.minChar;\n                    retStmt.limChar = retExpr.limChar;\n                    bod.minChar = bodMinChar;\n                    bod.append(retStmt);\n                }\n                else {\n                    isAnonLambda = wasShorthand;\n                    this.parseFunctionBlock(errorRecoverySet, allowedElements, parentModifiers, bod, bodMinChar);\n                }\n\n                limChar = this.scanner.pos;\n            }\n\n            var funcDecl = new FuncDecl(name, bod, isConstructor, args, this.topVarList(),\n                                        this.topScopeList(), this.topStaticsList(), NodeType.FuncDecl);\n            this.popDeclLists();\n            var scopeList = this.topScopeList();\n            scopeList.append(funcDecl);\n            var staticFuncDecl = false;\n\n            if (!requiresSignature) {\n                if (!wasShorthand || isAnonLambda) {\n                    funcDecl.endingToken = new ASTSpan();\n                    funcDecl.endingToken.minChar = this.scanner.startPos;\n                    funcDecl.endingToken.limChar = this.scanner.pos;\n                    this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n                    if (isAnonLambda) {\n                        funcDecl.fncFlags |= FncFlags.IsFatArrowFunction;\n                    }\n                }\n                else {\n                    funcDecl.fncFlags |= FncFlags.IsFatArrowFunction;\n                    funcDecl.endingToken = new ASTSpan();\n\n                    funcDecl.endingToken.minChar = bod.members[0].minChar;\n                    funcDecl.endingToken.limChar = bod.members[0].limChar;\n                }\n            }\n            funcDecl.minChar = minChar;\n            funcDecl.limChar = limChar;\n\n            if (!requiresSignature) {\n                funcDecl.fncFlags |= FncFlags.Definition;\n            }\n\n            this.statementInfoStack = svStmtStack;\n            return funcDecl;\n        }\n\n        private transformAnonymousArgsIntoFormals(formals: ASTList, argList: AST) : bool {\n\n            var translateBinExOperand = (operand: AST) : bool => {\n                if (operand.nodeType == NodeType.Comma) {\n                    return this.transformAnonymousArgsIntoFormals(formals, operand);\n                }\n                else if (operand.nodeType == NodeType.Name || operand.nodeType == NodeType.Asg) {\n                    var opArg = operand.nodeType == NodeType.Asg ? (<BinaryExpression>operand).operand1 : operand;\n\n                    var arg = new ArgDecl(<Identifier>opArg);\n                    arg.preComments = opArg.preComments;\n                    arg.postComments = opArg.postComments;\n                    arg.minChar = operand.minChar;\n                    arg.limChar = operand.limChar;\n\n                    if (hasFlag(opArg.flags, ASTFlags.PossibleOptionalParameter)) {\n                        arg.isOptional = true;\n                    }\n\n                    if (operand.nodeType == NodeType.Asg) {\n                        arg.init = (<BinaryExpression>operand).operand2;\n                    }\n\n                    formals.append(arg);\n\n                    return arg.isOptional || arg.init;\n                }\n                else {\n                    this.reportParseError(\"Invalid lambda argument\");\n                }\n                return false;\n            }\n\n            if (argList) {\n                if (argList.nodeType == NodeType.Comma) {\n                    var commaList = <BinaryExpression> argList;\n                    if (commaList.operand1.isParenthesized) { \n                        this.reportParseError(\"Invalid lambda argument\", commaList.operand1.minChar, commaList.operand1.limChar);\n                    }\n                    if (commaList.operand2.isParenthesized) { \n                        this.reportParseError(\"Invalid lambda argument\", commaList.operand2.minChar, commaList.operand2.limChar);\n                    }\n                    var isOptional = translateBinExOperand(commaList.operand1);\n                    isOptional = translateBinExOperand(commaList.operand2) || isOptional;\n                    return isOptional;\n                }\n                else {\n                    return translateBinExOperand(argList);\n                }\n            }\n        }\n\n        private parseFormalParameterList(errorRecoverySet: ErrorRecoverySet,\n                                            formals: ASTList,\n                                            isClassConstr: bool,\n                                            isSig: bool,\n                                            isIndexer: bool,\n                                            isGetter: bool,\n                                            isSetter: bool,\n                                            isLambda: bool,\n                                            preProcessedLambdaArgs: AST,\n                                            expectClosingRParen: bool): bool \n        {\n\n            formals.minChar = this.scanner.startPos; // '(' or '['\n            if (isIndexer) {\n                this.currentToken = this.scanner.scan();\n            }\n            else if (!isLambda) {\n                this.checkCurrentToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.RParen);\n            }\n            var sawEllipsis = false;\n            var firstArg = true;\n            var hasOptional = false;\n            var haveFirstArgID = false;\n\n            // if preProcessedLambdaArgs is \"true\", we either have a typeless argument list, or we have\n            // a single identifier node and the current token is the ':' before a typereference\n            if (isLambda && preProcessedLambdaArgs && preProcessedLambdaArgs.nodeType != NodeType.EmptyExpr) {\n                hasOptional = this.transformAnonymousArgsIntoFormals(formals, preProcessedLambdaArgs);\n                haveFirstArgID = true;\n            }\n\n            while (true) {\n                var munchedArg = false;\n                var argFlags = VarFlags.None;\n                var argMinChar = this.scanner.startPos;\n\n                if (this.inferPropertiesFromThisAssignment && this.currentToken.tokenId == TokenID.This) {\n                    if (!isClassConstr) {\n                        this.reportParseError(\"Instance property declarations using 'this' may only be used in class constructors\");\n                    }\n                    this.currentToken = this.scanner.scan(); // consume the '.'\n\n                    argFlags |= (VarFlags.Public | VarFlags.Property);\n                    if (this.currentClassDefinition) {\n                        this.currentClassDefinition.varFlags |= VarFlags.ClassSuperMustBeFirstCallInConstructor;\n                    }\n                }\n                if (this.currentToken.tokenId == TokenID.Public) {\n                    argFlags |= (VarFlags.Public | VarFlags.Property);\n\n                    if (this.currentClassDefinition) {\n                        this.currentClassDefinition.varFlags |= VarFlags.ClassSuperMustBeFirstCallInConstructor;\n                    }\n                }\n                else if (this.currentToken.tokenId == TokenID.Private) {\n                    argFlags |= (VarFlags.Private | VarFlags.Property);\n\n                    if (this.currentClassDefinition) {\n                        this.currentClassDefinition.varFlags |= VarFlags.ClassSuperMustBeFirstCallInConstructor;\n                    }\n                }\n                else if (this.currentToken.tokenId == TokenID.Static && isClassConstr) {\n                    this.reportParseError(\"Static properties can not be declared as parameter properties\");\n                    this.currentToken = this.scanner.scan();\n                }\n\n                if (argFlags != VarFlags.None) {\n                    if (!isClassConstr) {\n                        this.reportParseError(\"only constructor parameters can be properties\");\n                    }\n                    this.currentToken = this.scanner.scan();\n\n                    if (isModifier(this.currentToken)) { \n                        this.reportParseError(\"Multiple modifiers may not be applied to parameters\");\n                        this.currentToken = this.scanner.scan();\n                    }\n\n                    if (this.inferPropertiesFromThisAssignment && this.currentToken.tokenId == TokenID.This) {\n                        if (!isClassConstr) {\n                            this.reportParseError(\"Instance property declarations using 'this' may only be used in class constructors\");\n                        }\n                        this.currentToken = this.scanner.scan(); // consume the '.'\n                        this.currentToken = this.scanner.scan();\n                    }\n                }\n                else if (this.currentToken.tokenId == TokenID.DotDotDot) {\n                    sawEllipsis = true;\n                    this.currentToken = this.scanner.scan();\n\n                    if (!(this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                        this.reportParseError(\"'...' parameters require both a parameter name and an array type annotation to be specified\");\n                        sawEllipsis = false; // Do not treat this parameter as vararg\n                    }\n                }\n\n                var argId: Identifier = null;\n\n                if (!haveFirstArgID && (this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                    argId = Identifier.fromToken(this.currentToken);\n                    argId.minChar = this.scanner.startPos;\n                    argId.limChar = this.scanner.pos;\n                }\n\n                if (haveFirstArgID || argId) {\n                    munchedArg = true;\n                    var type: AST = null;\n                    var arg: ArgDecl = null;\n\n                    if (haveFirstArgID && formals.members.length) {\n                        arg = <ArgDecl>formals.members[formals.members.length - 1];\n\n                        if (arg.isOptional) {\n                            hasOptional = true;\n                        }\n                    }\n                    else {\n                        arg = new ArgDecl(argId);\n\n                        if (isGetter) {\n                            this.reportParseError(\"Property getters may not take any arguments\");\n                        }\n\n                        if (isSetter && !firstArg) {\n                            this.reportParseError(\"Property setters may only take one argument\");\n                        }\n\n                        arg.minChar = argMinChar;\n                        arg.preComments = this.parseComments();\n                        this.currentToken = this.scanner.scan();\n                    }\n\n                    if (this.currentToken.tokenId == TokenID.Question) {\n                        arg.isOptional = true;\n                        hasOptional = true;\n                        this.currentToken = this.scanner.scan();\n                    }\n\n                    if (this.currentToken.tokenId == TokenID.Colon) {\n                        this.currentToken = this.scanner.scan();\n                        type = this.parseTypeReference(errorRecoverySet, false);\n                    }\n\n                    // check for default parameter\n                    // REVIEW: In the case of a typed reference, assume that parseTypeReference or one\n                    // of its children in the call graph advanced tok\n                    if (this.currentToken.tokenId == TokenID.Equals) {\n                        if (isSig) {\n                            this.reportParseError(\"Arguments in signatures may not have default values\");\n                        }\n\n                        hasOptional = true;\n                        this.currentToken = this.scanner.scan();\n                        arg.init = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n                                            OperatorPrecedence.Comma, false,\n                                            TypeContext.NoTypes);\n\n                    }\n\n                    if (hasOptional && !arg.isOptionalArg() && !sawEllipsis) {\n                        this.reportParseError(\"Optional parameters may only be followed by other optional parameters\");\n                    }\n\n                    if (sawEllipsis && arg.isOptionalArg()) {\n                        this.reportParseError(\"Varargs may not be optional or have default parameters\");\n                    }\n\n                    if (sawEllipsis && !type) {\n                        // Ellipsis is missing a type definition\n                        this.reportParseError(\"'...' parameters require both a parameter name and an array type annotation to be specified\");\n                    }\n\n                    // REVIEW: Ok for lambdas?\n                    arg.postComments = this.parseComments();\n                    arg.typeExpr = type;\n                    arg.limChar = this.scanner.lastTokenLimChar();\n                    arg.varFlags |= argFlags;\n                    if (!haveFirstArgID) {\n                        formals.append(arg);\n                    }\n                    else {\n                        haveFirstArgID = false;\n                    }\n                }\n                firstArg = false;\n                if (this.currentToken.tokenId == TokenID.Comma) {\n                    if ((munchedArg) && (!sawEllipsis)) {\n                        this.currentToken = this.scanner.scan();\n                        continue;\n                    }\n                    else {\n                        this.reportParseError(\"Unexpected ',' in argument list\");\n                        if (this.errorRecovery) {\n                            this.currentToken = this.scanner.scan();\n                            continue;\n                        }\n                    }\n                }\n                else {\n                    break;\n                }\n            }\n\n            if (isIndexer) {\n                this.checkCurrentToken(TokenID.CloseBracket, errorRecoverySet | ErrorRecoverySet.LCurly | ErrorRecoverySet.SColon);\n            }\n            else if (expectClosingRParen) {\n                this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.LCurly | ErrorRecoverySet.SColon);\n            }\n            formals.limChar = this.scanner.lastTokenLimChar(); // ')' or ']'\n            return sawEllipsis;\n        }\n\n        private parseFncDecl(errorRecoverySet: ErrorRecoverySet,\n                             isDecl: bool,\n                             requiresSignature: bool,\n                             isMethod: bool,\n                             methodName: Identifier,\n                             indexer: bool,\n                             isStatic: bool,\n                             markedAsAmbient: bool,\n                             modifiers: Modifiers,\n                             lambdaArgContext: ILambdaArgumentContext,\n                             expectClosingRParen: bool): AST {\n\n            var leftCurlyCount = this.scanner.leftCurlyCount;\n            var rightCurlyCount = this.scanner.rightCurlyCount;\n\n            var prevInConstr = this.parsingClassConstructorDefinition;\n            this.parsingClassConstructorDefinition = false;\n\n            var name: Identifier = null;\n            var fnMin = this.scanner.startPos;\n            var minChar = this.scanner.pos;\n            var prevNestingLevel = this.nestingLevel;\n            var preComments = this.parseComments();\n            var isLambda = !!lambdaArgContext;\n            this.nestingLevel = 0;\n            if ((!this.style_funcInLoop) && this.inLoop()) {\n                this.reportParseStyleError(\"function declaration in loop\");\n            }\n            if (!isMethod && !isStatic && !indexer && !lambdaArgContext) {\n                // past function keyword\n                this.currentToken = this.scanner.scan();\n                this.state = ParseState.StartFncDecl;\n                if ((this.currentToken.tokenId != TokenID.Identifier) && (!convertTokToID(this.currentToken, this.strictMode))) {\n                    if (isDecl) {\n                        this.reportParseError(\"Function declaration must include identifier\");\n\n                        this.nestingLevel = prevNestingLevel;\n                        return new IncompleteAST(fnMin, this.scanner.pos);\n                    }\n                }\n                else {\n                    name = Identifier.fromToken(this.currentToken);\n                    name.minChar = this.scanner.startPos;\n                    name.limChar = this.scanner.pos;\n                    this.currentToken = this.scanner.scan();\n                }\n            }\n            else {\n                if (methodName) {\n                    name = methodName;\n                }\n            }\n\n            this.state = ParseState.FncDeclName;\n            var args: ASTList = new ASTList();\n            var variableArgList = false;\n            var isOverload = false;\n            var isGetter = hasFlag(modifiers, Modifiers.Getter);\n            var isSetter = hasFlag(modifiers, Modifiers.Setter);\n            if ((this.currentToken.tokenId == TokenID.OpenParen) || (indexer && (this.currentToken.tokenId == TokenID.OpenBracket)) || (lambdaArgContext && (lambdaArgContext.preProcessedLambdaArgs || this.currentToken.tokenId == TokenID.DotDotDot))) {\n                // arg list\n                variableArgList = this.parseFormalParameterList(errorRecoverySet, args, false, requiresSignature, indexer, isGetter, isSetter, isLambda, lambdaArgContext ? lambdaArgContext.preProcessedLambdaArgs : null, expectClosingRParen);\n            }\n            this.state = ParseState.FncDeclArgs;\n            var returnType: AST = null;\n            if (this.currentToken.tokenId == TokenID.Colon) {\n                this.currentToken = this.scanner.scan();\n                if (hasFlag(modifiers, Modifiers.Setter)) {\n                    this.reportParseError(\"Property setters may not declare a return type\");\n                }\n                returnType = this.parseTypeReference(errorRecoverySet, true);\n            }\n\n            if (indexer && args.members.length == 0) {\n                this.reportParseError(\"Index signatures require a parameter type to be specified\");\n            }\n            this.state = ParseState.FncDeclReturnType;\n\n            if (isLambda && this.currentToken.tokenId != TokenID.EqualsGreaterThan) {\n                this.reportParseError(\"Expected '=>'\");\n            }\n\n            // REVIEW:\n            // Currently, it's imperative that ambient functions *not* be marked as overloads.  At some point, we may\n            // want to unify the two concepts internally\n            if (isDecl && !(this.parsingDeclareFile || markedAsAmbient) && (!isMethod || !(this.ambientModule || this.ambientClass || this.inInterfaceDecl)) && this.currentToken.tokenId == TokenID.Semicolon) {\n                isOverload = true;\n                isDecl = false;\n                requiresSignature = true;\n            }\n            var svInFncDecl = this.inFncDecl;\n            this.inFncDecl = true;\n            var funcDecl: FuncDecl =\n                this.parseFunctionStatements(\n                errorRecoverySet | ErrorRecoverySet.RCurly,\n                name, /*isConstructor:*/ false, isMethod, args, AllowedElements.None,\n                minChar, requiresSignature, Modifiers.None);\n\n            this.inFncDecl = svInFncDecl;\n            funcDecl.variableArgList = variableArgList;\n            funcDecl.isOverload = isOverload;\n\n            if (!requiresSignature) { // REVIEW: What's the point of this?  Why not just use 'Signature' instead of 'Definition'?\n                funcDecl.fncFlags |= FncFlags.Definition;\n            }\n\n            if (isStatic) {\n                funcDecl.fncFlags |= FncFlags.Static;\n            }\n\n            if (requiresSignature) {\n                funcDecl.fncFlags |= FncFlags.Signature;\n            }\n            if (indexer) {\n                funcDecl.fncFlags |= FncFlags.IndexerMember;\n            }\n            funcDecl.returnTypeAnnotation = returnType;\n            if (isMethod) {\n                funcDecl.fncFlags |= FncFlags.Method;\n                // all class property methods are currently exported\n                funcDecl.fncFlags |= FncFlags.ClassPropertyMethodExported;\n            }\n            funcDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n            funcDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n\n            this.nestingLevel = prevNestingLevel;\n            this.parsingClassConstructorDefinition = prevInConstr;\n            funcDecl.preComments = preComments;\n            return funcDecl;\n        }\n\n        private convertToTypeReference(ast: AST): TypeReference {\n            var result: TypeReference;\n            switch (ast.nodeType) {\n                case NodeType.TypeRef:\n                    return <TypeReference>ast;\n                case NodeType.Name:\n                    result = new TypeReference(ast, 0);\n                    result.minChar = ast.minChar;\n                    result.limChar = ast.limChar;\n                    return result;\n                case NodeType.Index: {\n                    var expr = <BinaryExpression>ast;\n                    result = this.convertToTypeReference(expr.operand1);\n                    if (result) {\n                        result.arrayCount++;\n                        result.minChar = expr.minChar;\n                        result.limChar = expr.limChar;\n                        return result;\n                    }\n                    else {\n                        var etr = <TypeReference>new AST(NodeType.Error);\n                        return etr;\n                    }\n                }\n            }\n            return null;\n        }\n\n        private parseArgList(errorRecoverySet: ErrorRecoverySet): ASTList {\n            var args: ASTList = new ASTList();\n            args.minChar = this.scanner.startPos;\n\n            // skip left paren\n            this.currentToken = this.scanner.scan();\n\n            if (this.currentToken.tokenId !== TokenID.CloseParen) {\n                while (true) {\n                    if (args.members.length > 0xffff) {\n                        this.reportParseError(\"max number of args exceeded\");\n                        break;\n                    }\n\n                    var arg = this.parseExpr(\n                        ErrorRecoverySet.Comma | errorRecoverySet,\n                        OperatorPrecedence.Comma, \n                        /*allowIn:*/ true,\n                        TypeContext.NoTypes);\n\n                    args.append(arg);\n                    if (this.currentToken.tokenId != TokenID.Comma) {\n                        break;\n                    }\n\n                    this.currentToken = this.scanner.scan();\n                }\n            }\n\n            args.limChar = this.scanner.pos;\n            return args;\n        }\n\n        private parseBaseList(extendsList: ASTList,\n                              implementsList: ASTList,\n                              errorRecoverySet: ErrorRecoverySet,\n                              isClass: bool): void {\n            var keyword = true;\n            var currentList = extendsList;\n            for (; ;) {\n                if (keyword) {\n                    if (this.currentToken.tokenId === TokenID.Implements) {\n                        currentList = implementsList;\n                    }\n                    else if (this.currentToken.tokenId == TokenID.Extends && !this.requiresExtendsBlock) {\n                        this.requiresExtendsBlock = isClass;\n                    }\n                    this.currentToken = this.scanner.scan();\n                    keyword = false;\n                }\n                var baseName: Identifier = null;\n                if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                    var minChar = this.scanner.startPos;\n                    baseName = Identifier.fromToken(this.currentToken);\n                    baseName.minChar = minChar;\n                    baseName.limChar = this.scanner.pos;\n                    baseName = <Identifier>this.parseNamedType(errorRecoverySet | ErrorRecoverySet.LCurly,\n                                            minChar, baseName, false);\n                }\n                else {\n                    this.reportParseError(\"Expected base name\");\n                    if (this.errorRecovery) {\n                        baseName = new MissingIdentifier();\n                        baseName.minChar = this.scanner.pos;\n                        baseName.limChar = this.scanner.pos;\n                        baseName.flags |= ASTFlags.Error;\n                    }\n                }\n                if (this.currentToken.tokenId == TokenID.OpenParen) {\n                    if (isClass) {\n                        this.reportParseError(\"Base classes may only be initialized via a 'super' call within the constructor body\");\n                    }\n                    else {\n                        this.reportParseError(\"Interfaces may not be extended with a call expression\");\n                    }\n                }\n                else {\n                    currentList.append(baseName);\n                }\n\n                if (isClass && currentList == extendsList && extendsList.members.length > 1) {\n                    this.reportParseError(\"A class may only extend one other class\");\n                }\n\n                if (this.currentToken.tokenId == TokenID.Comma) {\n                    this.currentToken = this.scanner.scan();\n                    continue;\n                }\n\n                else if ((this.currentToken.tokenId == TokenID.Extends) ||\n                         (this.currentToken.tokenId == TokenID.Implements)) {\n\n                    if (this.currentToken.tokenId == TokenID.Extends && !this.requiresExtendsBlock) {\n                        this.requiresExtendsBlock = isClass;\n                    }\n\n                    currentList = extendsList;\n                    keyword = true;\n                    continue;\n                }\n\n                break;\n            }\n        }\n\n        private parseClassDecl(errorRecoverySet: ErrorRecoverySet, minChar: number, modifiers: Modifiers): ClassDeclaration {\n            var leftCurlyCount = this.scanner.leftCurlyCount;\n            var rightCurlyCount = this.scanner.rightCurlyCount;\n\n            if ((modifiers & Modifiers.Readonly) != Modifiers.None) {\n                this.reportParseError(\"const modifier is implicit for class\");\n            }\n\n            // mark the class as ambient, as necessary\n            if (this.parsingDeclareFile || this.ambientModule) {\n                modifiers |= Modifiers.Ambient;\n                modifiers |= Modifiers.Exported;\n            }\n            var classIsMarkedAsAmbient = this.parsingDeclareFile || (modifiers & Modifiers.Ambient) != Modifiers.None;\n            var svAmbientClass = this.ambientClass;\n            this.ambientClass = classIsMarkedAsAmbient;\n\n            // grab the class's name\n            this.currentToken = this.scanner.scan();\n            var name: Identifier = null;\n            if ((this.currentToken.tokenId == TokenID.Identifier) || (!isPrimitiveTypeToken(this.currentToken) && convertTokToID(this.currentToken, this.strictMode)) ) {\n                name = Identifier.fromToken(this.currentToken);\n                name.minChar = this.scanner.startPos;\n                name.limChar = this.scanner.pos;\n                this.currentToken = this.scanner.scan();\n            }\n            else {\n                this.reportParseError(\"class missing name\");\n                if (this.errorRecovery) {\n                    name = new MissingIdentifier();\n                    name.minChar = this.scanner.pos;\n                    name.limChar = this.scanner.pos;\n                    name.flags |= ASTFlags.Error;\n                }\n            }\n\n            var extendsList: ASTList = null;\n            var implementsList: ASTList = null;\n            var requiresSignature = false;\n\n            if ((this.currentToken.tokenId == TokenID.Extends) ||\n                (this.currentToken.tokenId == TokenID.Implements)) {\n                extendsList = new ASTList();\n                implementsList = new ASTList();\n                this.parseBaseList(extendsList, implementsList, errorRecoverySet, /*isClass:*/ true);\n            }\n\n            // REVIEW: Note that we don't set this as the current class decl\n            var classDecl = new ClassDeclaration(name, new ASTList(), extendsList, implementsList);\n\n            this.currentClassDefinition = classDecl;\n\n            // parse the classes members\n            this.parseClassElements(classDecl, errorRecoverySet, modifiers);\n\n            if (this.ambientModule || this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Exported)) {\n                classDecl.varFlags |= VarFlags.Exported;\n            }\n\n            if (this.ambientModule || hasFlag(modifiers, Modifiers.Ambient)) {\n                classDecl.varFlags |= VarFlags.Ambient;\n            }\n\n            classDecl.varFlags |= VarFlags.Class;\n\n            this.ambientClass = svAmbientClass;\n            classDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n            classDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n            return classDecl;\n        }\n\n        private parseClassElements(classDecl: ClassDeclaration, errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers) {\n            var modifiers = parentModifiers;\n            var resetModifiers = false;\n\n            var membersMinChar = this.scanner.startPos;\n            this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet);\n\n            this.nestingLevel++;\n\n            var currentMemberMinChar = this.scanner.startPos;\n            var wasGetOrSetId = false;\n\n            while (!(this.currentToken.tokenId == TokenID.CloseBrace || this.currentToken.tokenId == TokenID.EndOfFile)) {\n                var scanNext = true;\n                var publicOrPrivateFlags = Modifiers.Public | Modifiers.Private;\n\n                // modifiers\n                if (this.currentToken.tokenId == TokenID.Get) {\n                    if (modifiers & Modifiers.Getter) {\n                        this.reportParseError(\"Duplicate 'get' declaration in class body\");\n                    }\n                    if (modifiers & Modifiers.Setter) {\n                        this.reportParseError(\"Getter already marked as a setter\");\n                    }\n                    modifiers |= Modifiers.Getter;\n                }\n                else if (this.currentToken.tokenId == TokenID.Set) {\n                    if (modifiers & Modifiers.Setter) {\n                        this.reportParseError(\"Duplicate 'set' declaration in class body\");\n                    }\n                    if (modifiers & Modifiers.Getter) {\n                        this.reportParseError(\"Setter already marked as a getter\");\n                    }\n                    modifiers |= Modifiers.Setter;\n\n                }\n                else if (this.currentToken.tokenId == TokenID.Private) {\n                    if (modifiers & publicOrPrivateFlags) {\n                        this.reportParseError(\"Multiple modifiers may not be applied to class members\");\n                    }\n                    modifiers |= Modifiers.Private;\n                }\n                else if (this.currentToken.tokenId == TokenID.Public) {\n                    if (modifiers & publicOrPrivateFlags) {\n                        this.reportParseError(\"Multiple modifiers may not be applied to class members\");\n                    }\n                    modifiers |= Modifiers.Public;\n                }\n                else if (this.currentToken.tokenId == TokenID.Static) {\n                    if (modifiers & Modifiers.Static) { // only check for double instances of static\n                        this.reportParseError(\"Multiple modifiers may not be applied to class members\");\n                    }\n                    modifiers |= Modifiers.Static;\n                }  // constructors\n                else if (this.currentToken.tokenId == TokenID.Constructor) {\n\n                    if (modifiers != parentModifiers) {\n                        this.reportParseError(\"Constructors may not have modifiers\");\n                    }\n\n                    this.parseClassConstructorDeclaration(currentMemberMinChar, errorRecoverySet, modifiers);\n                    scanNext = false; // parsing functions advances the token for us\n                    resetModifiers = true;\n                }  // member declarations\n                else if (wasGetOrSetId || this.currentToken.tokenId == TokenID.Identifier || convertTokToIDName(this.currentToken)) {\n\n                    var idText = wasGetOrSetId ? ((modifiers & Modifiers.Getter) ? \"get\" : \"set\") : this.currentToken.getText();\n                    var id = wasGetOrSetId ? new Identifier(idText) : Identifier.fromToken(this.currentToken);\n                    id.minChar = this.scanner.startPos;\n                    id.limChar = this.scanner.pos;\n\n                    // unset the get/set bit, if we're using it for an id\n                    if (wasGetOrSetId) {\n                        modifiers = modifiers ^ ((modifiers & Modifiers.Getter) ? Modifiers.Getter : Modifiers.Setter);\n                        wasGetOrSetId = false;\n                    }\n                    else {\n                        this.currentToken = this.scanner.scan();\n                    }\n\n                    if (this.currentToken.tokenId == TokenID.OpenParen) {\n                        this.parseClassMemberFunctionDeclaration(id, currentMemberMinChar, errorRecoverySet, modifiers);\n                        scanNext = false; // parsing functions advances the token for us\n                    }\n                    else {\n                        if (modifiers & Modifiers.Getter || modifiers & Modifiers.Setter) {\n                            this.reportParseError(\"Property accessors must be functions\");\n                        }\n\n                        var varDecl = this.parseClassMemberVariableDeclaration(id, currentMemberMinChar, false, errorRecoverySet, modifiers);\n\n                        if (varDecl.init && varDecl.init.nodeType == NodeType.FuncDecl) {\n                            if (this.currentToken.tokenId == TokenID.CloseBrace) {\n                                scanNext = false;\n                            }\n                        }\n                        else if (varDecl.init && varDecl.init.nodeType == NodeType.ObjectLit && this.currentToken.tokenId != TokenID.Semicolon) {\n                            scanNext = false;\n                            varDecl.init.flags |= ASTFlags.AutomaticSemicolon;\n                        }\n                        else if (this.currentToken.tokenId != TokenID.Semicolon) {\n                            this.reportParseError(\"Expected ';'\");\n                            scanNext = false;\n                        }\n                    }\n\n                    resetModifiers = true;\n                } // catch errant uses of 'super'\n                else if (this.currentToken.tokenId == TokenID.Super) {\n                    this.reportParseError(\"Base class initializers must be the first statement in a class definition\");\n                }\n                else if (!wasGetOrSetId && ((modifiers & Modifiers.Getter) || (modifiers & Modifiers.Setter)) &&\n                         ((this.currentToken.tokenId == TokenID.OpenParen) || (this.currentToken.tokenId == TokenID.Equals) ||\n                          (this.currentToken.tokenId == TokenID.Colon) || (this.currentToken.tokenId == TokenID.Semicolon))) {\n                             // catch a 'get' or 'set' used as an identifier\n                    wasGetOrSetId = true;\n                    scanNext = false;\n\n                }  // mark anything else as an error\n                else if (this.currentToken.tokenId != TokenID.Semicolon) { // jettison semicolons\n                    this.reportParseError(\"Unexpected '\" + this.currentToken.getText() + \"' in class definition\");\n                    resetModifiers = true;\n                }\n\n                if (scanNext) {\n                    this.currentToken = this.scanner.scan();\n                }\n\n                if (resetModifiers) {\n                    modifiers = parentModifiers;\n                    currentMemberMinChar = this.scanner.startPos;\n                    resetModifiers = false;\n                }\n            }\n\n            var membersLimChar = this.scanner.pos;\n            if (this.currentToken.tokenId == TokenID.CloseBrace) {\n                classDecl.endingToken = new ASTSpan();\n                classDecl.endingToken.minChar = this.scanner.startPos;\n                classDecl.endingToken.limChar = this.scanner.pos;\n\n                // for a class with an empty body, consume any 'dangling' inner comments\n                if (!this.currentClassDefinition.members.members.length) {\n                    this.currentClassDefinition.preComments = this.parseComments();\n                }\n\n                this.currentToken = this.scanner.scan();\n            }\n\n            this.nestingLevel--;\n\n            this.currentClassDefinition.members.minChar = membersMinChar;\n            this.currentClassDefinition.members.limChar = membersLimChar;\n            this.currentClassDefinition.limChar = membersLimChar;\n            this.currentClassDefinition = null;\n        }\n\n        private parseClassConstructorDeclaration(minChar: number, errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers) {\n            this.parsingClassConstructorDefinition = true;\n\n            var isAmbient = this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient);\n\n            var args: ASTList = new ASTList();\n            var variableArgList = false;\n            var preComments = this.parseComments();\n\n            this.currentToken = this.scanner.scan(); // scan past the 'constructor' token\n\n            if (this.currentToken.tokenId == TokenID.OpenParen) {\n                variableArgList = this.parseFormalParameterList(errorRecoverySet, args, true, isAmbient, false, false, false, false, null, true);\n                if (args.members.length > 0) {\n                    var lastArg = args.members[args.members.length - 1];\n                }\n            }\n\n            var requiresSignature = isAmbient || this.currentToken.tokenId == TokenID.Semicolon;\n\n\n            if (requiresSignature) {\n                for (var i = 0; i < args.members.length; i++) {\n                    var arg = <ArgDecl> args.members[i];\n                    if (hasFlag(arg.varFlags, VarFlags.Property)) {\n                        this.reportParseError(\"Overload or ambient signatures may not specify parameter properties\", arg.minChar, arg.limChar);\n                    }\n                }\n            }\n\n            if (!requiresSignature) {\n                this.currentClassDefinition.constructorNestingLevel = this.nestingLevel + 1;\n            }\n\n            var constructorFuncDecl = this.parseFunctionStatements(\n                errorRecoverySet | ErrorRecoverySet.RCurly, this.currentClassDefinition.name, \n                /*isConstructor:*/ true, /*isMethod:*/ false, args, AllowedElements.Properties, \n                minChar, requiresSignature, modifiers);\n\n            constructorFuncDecl.preComments = preComments;\n\n            if (requiresSignature && !isAmbient) {\n                constructorFuncDecl.isOverload = true;\n            }\n\n            constructorFuncDecl.variableArgList = variableArgList;\n            this.currentClassDecl = null;\n            constructorFuncDecl.returnTypeAnnotation = this.convertToTypeReference(this.currentClassDefinition.name);\n            constructorFuncDecl.classDecl = this.currentClassDefinition;\n\n            if (isAmbient) {\n                constructorFuncDecl.fncFlags |= FncFlags.Ambient;\n            }\n\n            if (requiresSignature) {\n                constructorFuncDecl.fncFlags |= FncFlags.Signature;\n            }\n\n            if (this.ambientModule || hasFlag(modifiers, Modifiers.Exported)) {\n                constructorFuncDecl.fncFlags |= FncFlags.Exported;\n            }\n\n\n            if (this.currentClassDefinition.constructorDecl) {\n                if (!isAmbient && !this.currentClassDefinition.constructorDecl.isSignature() && !constructorFuncDecl.isSignature()) {\n                    this.reportParseError(\"Duplicate constructor definition\");\n                }\n            }\n\n            if (isAmbient || !constructorFuncDecl.isSignature()) {\n                this.currentClassDefinition.constructorDecl = constructorFuncDecl;\n            }\n\n            // REVIEW: Should we have a separate flag for class constructors?  (Constructors are not methods)\n            constructorFuncDecl.fncFlags |= FncFlags.ClassMethod;\n\n            this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = constructorFuncDecl;\n\n            this.parsingClassConstructorDefinition = false;\n\n            return constructorFuncDecl;\n        }\n\n        private parseClassMemberVariableDeclaration(text: Identifier, minChar: number, isDeclaredInConstructor: bool, errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers) {\n\n            var varDecl = new VarDecl(text, this.nestingLevel);\n            varDecl.minChar = minChar;\n            var isStatic = false;\n            varDecl.preComments = this.parseComments();\n\n            if (this.currentToken.tokenId == TokenID.Colon) {\n                this.currentToken = this.scanner.scan();\n                varDecl.typeExpr =\n                    this.parseTypeReference(errorRecoverySet | ErrorRecoverySet.Asg | ErrorRecoverySet.Comma, false);\n                if (varDecl.typeExpr && varDecl.typeExpr.nodeType == NodeType.TypeRef) {\n                    var typeExpr = (<TypeReference>varDecl.typeExpr);\n                    if (typeExpr.term && typeExpr.term.nodeType == NodeType.FuncDecl) {\n                        typeExpr.term.preComments = varDecl.preComments;\n                    }\n                }\n            }\n\n            if (this.currentToken.tokenId == TokenID.Equals) {\n                if (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)) {\n                    this.reportParseError(\"context does not permit variable initializer\");\n                    if (this.errorRecovery) {\n                        this.skip(errorRecoverySet);\n                        varDecl.flags |= ASTFlags.Error;\n                        varDecl.limChar = this.scanner.lastTokenLimChar();\n                        return varDecl;\n                    }\n                }\n\n                // TODO: note assignment for language service\n                this.currentToken = this.scanner.scan();\n\n                varDecl.init = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n                                        OperatorPrecedence.Comma, true, TypeContext.NoTypes);\n\n                varDecl.limChar = varDecl.init.limChar;\n\n                // member initializers on instance properties require that super be invoked as the first call within the constructor\n                if (!(modifiers & Modifiers.Static)) {\n                    this.currentClassDefinition.varFlags |= VarFlags.ClassSuperMustBeFirstCallInConstructor;\n                }\n            }\n            else {\n                varDecl.limChar = this.scanner.pos;\n            }\n\n            if (modifiers & Modifiers.Static) {\n                varDecl.varFlags |= VarFlags.Static;\n                isStatic = true;\n            }\n\n            if ((modifiers & Modifiers.Private) != Modifiers.None) {\n                varDecl.varFlags |= VarFlags.Private;\n            }\n            else {\n                varDecl.varFlags |= VarFlags.Public;\n            }\n\n            varDecl.varFlags |= VarFlags.Property;\n\n            if (isDeclaredInConstructor) {\n                varDecl.varFlags |= VarFlags.ClassConstructorProperty;\n            }\n\n            if (!isDeclaredInConstructor && !isStatic) {\n                varDecl.varFlags |= VarFlags.ClassBodyProperty;\n            }\n\n            this.currentClassDefinition.knownMemberNames[text.actualText] = true;\n\n            if (!isDeclaredInConstructor) {\n                this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = varDecl;\n            }\n\n            varDecl.postComments = this.parseComments();\n            return varDecl;\n        }\n\n        private parseClassMemberFunctionDeclaration(methodName: Identifier, minChar: number, errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers) {\n            var wasAccessorID = this.prevIDTok != null;\n            var isAccessor = hasFlag(modifiers, Modifiers.Getter) || hasFlag(modifiers, Modifiers.Setter);\n            var isStatic = hasFlag(modifiers, Modifiers.Static);\n\n            var isAmbient = this.ambientModule || hasFlag(modifiers, Modifiers.Ambient);\n\n            errorRecoverySet |= ErrorRecoverySet.RParen;\n\n            if (isAccessor && (modifiers & Modifiers.Ambient)) {\n                this.reportParseError(\"Property accessors may not be declared in ambient classes\");\n            }\n\n            // REVIEW: Why bother passing in isAmbient for both requiresSignature and isAmbient?  Shouldn't just saying its ambient suffice?\n            var ast: AST = this.parseFncDecl(errorRecoverySet, true, isAmbient, true, methodName, false, isStatic, isAmbient, modifiers, null, true);\n            if (ast.nodeType == NodeType.Error) {\n                return ast;\n            }\n\n            var funcDecl = <FuncDecl>ast;\n\n            funcDecl.minChar = minChar;\n            if (funcDecl.bod !== null)\n                funcDecl.limChar = funcDecl.bod.limChar;\n\n            if (modifiers & Modifiers.Private) {\n                funcDecl.fncFlags |= FncFlags.Private;\n            }\n            else {\n                funcDecl.fncFlags |= FncFlags.Public;\n            }\n\n            if (isStatic) {\n                funcDecl.fncFlags |= FncFlags.Static;\n            }\n\n            if (isAccessor) {\n                // REVIEW: verify return-type annotations and arguments\n                if (hasFlag(modifiers, Modifiers.Getter)) {\n                    funcDecl.fncFlags |= FncFlags.GetAccessor;\n                    funcDecl.hint = \"get\" + funcDecl.name.actualText;\n                }\n                else {\n                    funcDecl.fncFlags |= FncFlags.SetAccessor;\n                    funcDecl.hint = \"set\" + funcDecl.name.actualText;\n                }\n                funcDecl.fncFlags |= FncFlags.IsFunctionExpression;\n                if (codeGenTarget < CodeGenTarget.ES5) {\n                    this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\", funcDecl.minChar, funcDecl.limChar);\n                }\n            }\n\n            funcDecl.fncFlags |= FncFlags.ClassMethod;\n\n            this.currentClassDefinition.knownMemberNames[methodName.actualText] = true;\n\n            this.currentClassDefinition.members.members[this.currentClassDefinition.members.members.length] = funcDecl;\n\n            return funcDecl;\n        }\n\n        private parseTypeMember(errorRecoverySet: ErrorRecoverySet): AST {\n            var minChar = this.scanner.startPos;\n\n            var propertyDecl = this.parsePropertyDeclaration(\n                errorRecoverySet, Modifiers.Public, /*requireSignature:*/ true, /*isStatic:*/ false);\n\n            if (propertyDecl) {\n                propertyDecl.minChar = minChar;\n\n                if (propertyDecl.nodeType == NodeType.VarDecl) {\n                     this.checkCurrentToken(TokenID.Semicolon, errorRecoverySet);\n                }\n            }\n\n            return propertyDecl;\n        }\n\n        private parseTypeMemberList(errorRecoverySet: ErrorRecoverySet, members: ASTList) {\n            errorRecoverySet |= ErrorRecoverySet.TypeScriptS;\n            while (true) {\n                switch (this.currentToken.tokenId) {\n                    case TokenID.CloseBrace:\n                    case TokenID.EndOfFile:\n                        members.limChar = this.scanner.pos;\n                        return;\n                }\n\n                // REVIEW: This code looks suspect.  If parseTypeMember returns null, then \n                // won't we just infinite loop?\n                var element = this.parseTypeMember(errorRecoverySet);\n                if (element) {\n                    members.append(element);\n                }\n            }\n        }\n\n        private parseInterfaceDecl(errorRecoverySet: ErrorRecoverySet, modifiers: Modifiers): InterfaceDeclaration {\n            var leftCurlyCount = this.scanner.leftCurlyCount;\n            var rightCurlyCount = this.scanner.rightCurlyCount;\n\n            this.currentToken = this.scanner.scan();\n            var minChar = this.scanner.pos;\n            var name: Identifier = null;\n            if ((this.currentToken.tokenId == TokenID.Identifier) || (!isPrimitiveTypeToken(this.currentToken) && convertTokToID(this.currentToken, this.strictMode))) {\n                name = Identifier.fromToken(this.currentToken);\n                name.minChar = this.scanner.startPos;\n                name.limChar = this.scanner.pos;\n                this.currentToken = this.scanner.scan();\n            }\n            else {\n                this.reportParseError(\"interface missing name\");\n                if (this.errorRecovery) {\n                    name = new MissingIdentifier();\n                    name.minChar = this.scanner.pos;\n                    name.limChar = this.scanner.pos;\n                    name.flags |= ASTFlags.Error;\n                }\n            }\n\n            var extendsList: ASTList = null;\n            var implementsList: ASTList = null;\n            if (this.currentToken.tokenId === TokenID.Extends || this.currentToken.tokenId === TokenID.Implements) {\n                if (this.currentToken.tokenId === TokenID.Implements) {\n                    this.reportParseError(\"Expected 'extends'\");\n                }\n\n                extendsList = new ASTList();\n                implementsList = new ASTList();\n                extendsList.minChar = this.scanner.startPos;\n                this.parseBaseList(extendsList, implementsList, errorRecoverySet, /*isClass:*/ false);\n            }\n\n            var membersMinChar = this.scanner.startPos;\n            this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.TypeScriptS);\n            var members = new ASTList();\n            members.minChar = membersMinChar;\n            var prevInInterfaceDecl = this.inInterfaceDecl;\n            this.inInterfaceDecl = true;\n            this.parseTypeMemberList(errorRecoverySet | ErrorRecoverySet.RCurly, members);\n            this.inInterfaceDecl = prevInInterfaceDecl;\n            this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n\n            // REVIEW: According to the grammar, an interface declaration should actually just\n            // have an 'ObjectType' and not a list of members.  We may want to consider making that\n            // change.  Note: it would mean breaking aparat TypeDecl into InterfaceDeclaration and \n            // ClassDeclaration.\n            var interfaceDecl = new InterfaceDeclaration(name, members, extendsList, null);\n            if (hasFlag(modifiers, Modifiers.Private)) {\n                interfaceDecl.varFlags |= VarFlags.Private;\n            }\n            if (hasFlag(modifiers, Modifiers.Public)) {\n                interfaceDecl.varFlags |= VarFlags.Public;\n            }\n            if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Exported)) {\n                interfaceDecl.varFlags |= VarFlags.Exported;\n            }\n\n            interfaceDecl.limChar = members.limChar;\n            interfaceDecl.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n            interfaceDecl.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n            return interfaceDecl;\n        }\n\n        private makeVarDecl(id: Identifier, nest: number): VarDecl {\n            var varDecl = new VarDecl(id, nest);\n            var currentVarList = this.topVarList();\n            if (currentVarList) {\n                currentVarList.append(varDecl);\n            }\n            return varDecl;\n        }\n\n        private parsePropertyDeclaration(\n            errorRecoverySet: ErrorRecoverySet,\n            modifiers: Modifiers,\n            requireSignature: bool,\n            isStatic: bool): AST {\n\n            var text: Identifier = null;\n            var minChar = this.scanner.startPos;\n            var nameLimChar = minChar;\n            var isNew = false;\n            var isIndexer = false;\n            var wasAccessorID = this.prevIDTok != null;\n            var isAccessor = hasFlag(modifiers, Modifiers.Getter) || hasFlag(modifiers, Modifiers.Setter);\n\n            if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Ambient)) {\n                requireSignature = true;\n            }\n\n            if (this.currentToken.tokenId == TokenID.OpenParen && !wasAccessorID) {\n                if (!requireSignature && !isStatic) {\n                    this.reportParseError(\"Expected identifier in property declaration\");\n                    if (this.errorRecovery) {\n                        this.skip(errorRecoverySet);\n                        //REVIEW: Use something else than \"Identifier\"?\n                        text = new MissingIdentifier();\n                    }\n                }\n            }\n            else if (this.currentToken.tokenId == TokenID.New) {\n                if (requireSignature) {\n                    this.currentToken = this.scanner.scan();\n                    if (this.currentToken.tokenId == TokenID.OpenParen) {\n                        isNew = true;\n                    }\n                }\n\n                if (!isNew) {\n                    // is identifier\n                    if (!requireSignature) {\n                        this.currentToken = this.scanner.scan();\n                    }\n                    text = new Identifier(\"new\");\n                    text.minChar = this.scanner.pos - 3;\n                    text.limChar = this.scanner.pos;\n                    nameLimChar = this.scanner.pos;\n                }\n            }\n            else if ((this.currentToken.tokenId == TokenID.OpenBracket) && requireSignature) {\n                // indexer signature\n                isIndexer = true;\n                //REVIEW: Should we use a special \"compiler reserved\" identifier node?\n                text = new Identifier(\"__item\");\n            }\n            else if ((this.currentToken.tokenId != TokenID.Identifier) && (!convertTokToIDName(this.currentToken)) && !wasAccessorID) {\n                this.reportParseError(\"Expected identifier in property declaration\");\n                if (this.errorRecovery) {\n                    var eminChar = this.scanner.startPos;\n                    var curpos = this.scanner.pos;\n                    this.skip(errorRecoverySet & (~ErrorRecoverySet.Comma));\n                    if (this.scanner.pos == curpos) {\n                        // ensure progress\n                        this.currentToken = this.scanner.scan();\n                    }\n\n                    var epd = new VarDecl(new MissingIdentifier(), this.nestingLevel);\n                    epd.flags |= ASTFlags.Error;\n                    epd.minChar = eminChar;\n                    epd.limChar = this.scanner.lastTokenLimChar();\n                    return epd;\n                }\n            }\n            else {\n                if (wasAccessorID) {\n                    text = Identifier.fromToken(this.prevIDTok);\n                    text.minChar = this.scanner.lastTokenLimChar() - 3;\n                    text.limChar = this.scanner.lastTokenLimChar();\n                    nameLimChar = text.limChar;\n\n                    if (codeGenTarget < CodeGenTarget.ES5) {\n                        this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n                    }\n\n                    // this block guards against 'get' and 'set' tokens that\n                    // were coerced into identifiers\n                    if (this.currentToken.getText() == text.actualText && this.currentToken != this.prevIDTok) {\n                        this.currentToken = this.scanner.scan();\n                    } // Otherwise, don't update the token - we're already at '('\n\n                    // reset the previous ID Token\n                    this.prevIDTok = null;\n                }\n                else {\n                    text = Identifier.fromToken(this.currentToken);\n                    text.minChar = this.scanner.startPos;\n                    text.limChar = this.scanner.pos;\n                    nameLimChar = this.scanner.pos;\n                    this.currentToken = this.scanner.scan();\n                }\n            }\n\n            if (this.currentToken.tokenId == TokenID.Question) {\n                if (this.inInterfaceDecl && text) {\n                    text.flags |= ASTFlags.OptionalName;\n                }\n                else {\n                    this.reportParseError(\"Optional properties may only be declared on interface or object types\");\n                }\n                this.currentToken = this.scanner.scan();\n            }\n\n            if ((this.currentToken.tokenId == TokenID.OpenParen) ||\n                (isIndexer && (this.currentToken.tokenId == TokenID.OpenBracket))) {\n                var ers = errorRecoverySet | ErrorRecoverySet.RParen;\n                if (isIndexer) {\n                    ers = errorRecoverySet | ErrorRecoverySet.RBrack;\n                }\n                var ast = this.parseFncDecl(ers, true, requireSignature,\n                                       !this.inFncDecl, text, isIndexer, isStatic, (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)), modifiers, null, true);\n                var funcDecl: FuncDecl;\n                if (ast.nodeType == NodeType.Error) {\n                    return ast;\n                }\n                else {\n                    funcDecl = <FuncDecl>ast;\n                }\n                if (funcDecl.name) {\n                    funcDecl.name.minChar = minChar;\n                    funcDecl.name.limChar = nameLimChar;\n                }\n                if ((modifiers & Modifiers.Public) != Modifiers.None) {\n                    funcDecl.fncFlags |= FncFlags.Public;\n                }\n                if ((modifiers & Modifiers.Private) != Modifiers.None) {\n                    funcDecl.fncFlags |= FncFlags.Private;\n                }\n                if (isStatic) {\n                    funcDecl.fncFlags |= FncFlags.Static;\n                }\n                if (this.parsingDeclareFile || hasFlag(modifiers, Modifiers.Ambient)) {\n                    funcDecl.fncFlags |= FncFlags.Ambient;\n                }\n                if (isAccessor) {\n                    // REVIEW: verify return-type annotations and arguments\n                    if (hasFlag(modifiers, Modifiers.Getter)) {\n                        funcDecl.fncFlags |= FncFlags.GetAccessor;\n                        funcDecl.hint = \"get\" + funcDecl.name.actualText;\n                    }\n                    else {\n                        funcDecl.fncFlags |= FncFlags.SetAccessor;\n                        funcDecl.hint = \"set\" + funcDecl.name.actualText;\n                    }\n                    funcDecl.fncFlags |= FncFlags.IsFunctionExpression;\n\n                    if (modifiers & Modifiers.Ambient) {\n                        this.reportParseError(\"Property accessors may not be declared in ambient types\");\n                    }\n                }\n\n                if (text == null) {\n                    if (isNew) {\n                        funcDecl.fncFlags |= FncFlags.ConstructMember;\n                        funcDecl.hint = \"_construct\";\n                        funcDecl.classDecl = this.currentClassDecl;\n                    }\n                    else {\n                        funcDecl.hint = \"_call\";\n                        funcDecl.fncFlags |= FncFlags.CallMember;\n                    }\n                }\n                return funcDecl;\n            }\n            else {\n                var varDecl = new VarDecl(text, this.nestingLevel);\n                varDecl.preComments = this.parseComments();\n                varDecl.minChar = minChar;\n                if (this.currentToken.tokenId == TokenID.Colon) {\n                    this.currentToken = this.scanner.scan();\n                    varDecl.typeExpr =\n                        this.parseTypeReference(errorRecoverySet | ErrorRecoverySet.Asg |\n                                           ErrorRecoverySet.Comma, false);\n                    if (varDecl.typeExpr && varDecl.typeExpr.nodeType == NodeType.TypeRef) {\n                        var typeExpr = (<TypeReference>varDecl.typeExpr);\n                        if (typeExpr.term && typeExpr.term.nodeType == NodeType.FuncDecl) {\n                            typeExpr.term.preComments = varDecl.preComments;\n                        }\n                    }\n                }\n                if (this.currentToken.tokenId == TokenID.Equals) {\n                    if (requireSignature) {\n                        this.reportParseError(\"context does not permit variable initializer\");\n                        if (this.errorRecovery) {\n                            this.skip(errorRecoverySet);\n                            varDecl.flags |= ASTFlags.Error;\n                            varDecl.limChar = this.scanner.lastTokenLimChar();\n                            return varDecl;\n                        }\n                    }\n                    // TODO: note assignment for language service\n                    this.currentToken = this.scanner.scan();\n                    varDecl.init = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n                                           OperatorPrecedence.Comma, true, TypeContext.NoTypes);\n                    varDecl.limChar = varDecl.init.limChar;\n                    if (varDecl.init.nodeType == NodeType.FuncDecl) {\n                        var funcDecl = <FuncDecl>varDecl.init;\n                        funcDecl.hint = varDecl.id.text;\n                        funcDecl.boundToProperty = varDecl;\n                    }\n                    else if (isAccessor) {\n                        this.reportParseError(\"Accessors may only be functions\");\n                    }\n                }\n                else {\n                    varDecl.limChar = this.scanner.pos;\n                }\n                if ((modifiers & Modifiers.Readonly) != Modifiers.None) {\n                    varDecl.varFlags |= VarFlags.Readonly;\n                }\n                if (isStatic) {\n                    varDecl.varFlags |= VarFlags.Static;\n                }\n                if ((modifiers & Modifiers.Public) != Modifiers.None) {\n                    varDecl.varFlags |= VarFlags.Public;\n                }\n                if ((modifiers & Modifiers.Private) != Modifiers.None) {\n                    varDecl.varFlags |= VarFlags.Private;\n                }\n                varDecl.varFlags |= VarFlags.Property;\n                return varDecl;\n            }\n        }\n\n        private parseVariableDeclaration(\n            errorRecoverySet: ErrorRecoverySet,\n            modifiers: Modifiers,\n            allowIn: bool,\n            isStatic: bool): AST {\n\n            var isConst = hasFlag(modifiers, Modifiers.Readonly);\n            var minChar = this.scanner.startPos;\n            var varDecl: VarDecl = null;\n            var declList: ASTList = null;\n            var multivar = false;\n\n            this.currentToken = this.scanner.scan();\n            var varDeclPreComments = this.parseComments();\n\n            while (true) {\n                if ((this.currentToken.tokenId != TokenID.Identifier) && (!convertTokToID(this.currentToken, this.strictMode))) {\n                    this.reportParseError(\"Expected identifier in variable declaration\");\n\n                    if (this.errorRecovery) {\n                        varDecl = new VarDecl(new MissingIdentifier(), this.nestingLevel);\n                        varDecl.minChar = minChar;\n                        this.skip(errorRecoverySet);\n                        varDecl.flags |= ASTFlags.Error;\n                        varDecl.limChar = this.scanner.lastTokenLimChar();\n                        return varDecl;\n                    }\n                }\n\n                var varDeclName = Identifier.fromToken(this.currentToken)\n                if (this.strictMode && (varDeclName.text == \"eval\")) {\n                    this.reportParseError(\"'eval' may not name a variable in strict mode\");\n                }\n\n                varDecl = this.makeVarDecl(varDeclName, this.nestingLevel);\n                varDecl.id.minChar = this.scanner.startPos;\n                varDecl.id.limChar = this.scanner.pos;\n                varDecl.preComments = varDeclPreComments;\n\n                if (isStatic) {\n                    varDecl.varFlags |= VarFlags.Static;\n                }\n                if (hasFlag(modifiers, Modifiers.Readonly)) {\n                    varDecl.varFlags |= VarFlags.Readonly;\n                }\n                if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Ambient)) {\n                    varDecl.varFlags |= VarFlags.Ambient;\n                }\n                if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Exported)) {\n                    varDecl.varFlags |= VarFlags.Exported;\n                }\n                varDecl.minChar = minChar;\n                if (declList) {\n                    declList.append(varDecl);\n                }\n\n                // move past ID; with error recovery need a test \n                this.currentToken = this.scanner.scan();\n                if (this.currentToken.tokenId == TokenID.Colon) {\n                    this.currentToken = this.scanner.scan();\n                    var prevInFncDecl = this.inFncDecl;\n                    this.inFncDecl = false;\n                    varDecl.typeExpr = this.parseTypeReference(\n                        errorRecoverySet | ErrorRecoverySet.Asg | ErrorRecoverySet.Comma, /*allowVoid:*/ false);\n                    this.inFncDecl = prevInFncDecl;\n                }\n\n                if (this.currentToken.tokenId == TokenID.Equals) {\n                    if (hasFlag(varDecl.varFlags, VarFlags.Ambient)) {\n                        this.reportParseError(\"Ambient variable can not have an initializer\");\n                    }\n                    // TODO: note assignment for language service\n                    this.currentToken = this.scanner.scan();\n                    varDecl.init = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n                                           OperatorPrecedence.Comma, allowIn,\n                                           TypeContext.NoTypes);\n                    varDecl.limChar = varDecl.init.limChar;\n                    if (varDecl.init.nodeType == NodeType.FuncDecl) {\n                        // TODO: use 'as' operator when can bootstrap\n                        var funcDecl = <FuncDecl>varDecl.init;\n                        funcDecl.hint = varDecl.id.actualText;\n                    }\n                }\n                else {\n                    if (isConst) {\n                        this.reportParseError(\"const declaration requires initializer\");\n                    }\n                    varDecl.limChar = this.scanner.pos;\n                }\n                varDecl.postComments = this.parseCommentsForLine(this.scanner.line);\n\n                if (this.currentToken.tokenId != TokenID.Comma) {\n                    if (declList) {\n                        declList.limChar = varDecl.limChar;\n                        return declList;\n                    }\n                    else {\n                        return varDecl;\n                    }\n                }\n\n                if (!multivar) {\n                    declList = new ASTList();\n                    declList.minChar = varDecl.minChar;\n                    declList.append(varDecl);\n                    multivar = true;\n                }\n\n                this.currentToken = this.scanner.scan();\n                minChar = this.scanner.startPos;\n            }\n        }\n\n        private parseMemberList(errorRecoverySet: ErrorRecoverySet): ASTList {\n            var elements = new ASTList();\n            if (this.currentToken.tokenId == TokenID.CloseBrace) {\n                return elements;\n            }\n\n            var idHint: string = null;\n            var memberName: AST = null;\n            var memberExpr: AST = null;\n            var member: BinaryExpression = null;\n            var minChar = this.scanner.startPos;\n            var isSet = false;\n            var skippedTokenForGetSetId = false;\n            var getSetTok: Token = null;\n            var getSetStartPos = 0;\n            var getSetPos = 0;\n\n            for (; ;) {\n                var accessorPattern = false;\n                if (this.currentToken.tokenId == TokenID.Get || this.currentToken.tokenId == TokenID.Set) {\n                    isSet = this.currentToken.tokenId == TokenID.Set;\n                    getSetTok = this.currentToken;\n                    getSetStartPos = this.scanner.startPos;\n                    getSetPos = this.scanner.pos;\n\n                    this.currentToken = this.scanner.scan();\n\n                    if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToIDName(this.currentToken)) {\n                        idHint = isSet ? \"set\" : \"get\";\n                        idHint = idHint + this.currentToken.getText();\n                        memberName = Identifier.fromToken(this.currentToken);\n                        memberName.minChar = this.scanner.startPos;\n                        accessorPattern = true;\n                        if (codeGenTarget < CodeGenTarget.ES5) {\n                            this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n                        }\n                    }\n                    else if (this.currentToken.tokenId != TokenID.Colon) {\n                        this.reportParseError(\"Expected identifier, string or number as accessor name\");\n                    }\n                    else {\n                        skippedTokenForGetSetId = true;\n                        memberName = Identifier.fromToken(getSetTok);\n                        memberName.minChar = getSetStartPos;\n                        memberName.limChar = getSetPos;\n                    }\n                }\n                else if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToIDName(this.currentToken)) {\n                    idHint = this.currentToken.getText();\n                    memberName = Identifier.fromToken(this.currentToken);\n                    memberName.minChar = this.scanner.startPos;\n                    memberName.limChar = this.scanner.pos;\n                }\n                else if (this.currentToken.tokenId == TokenID.StringLiteral) {\n                    idHint = this.currentToken.getText();\n                    memberName = new StringLiteral(idHint);\n                    memberName.minChar = this.scanner.startPos;\n                    memberName.limChar = this.scanner.pos;\n                }\n                    // TODO: allow reserved words\n                else if (this.currentToken.tokenId == TokenID.NumberLiteral) {\n                    var ntok = <NumberLiteralToken>this.currentToken;\n                    idHint = ntok.value.toString();\n                    memberName = new StringLiteral(idHint);\n                    memberName.minChar = this.scanner.startPos;\n                    memberName.limChar = this.scanner.pos;\n                }\n                else {\n                    this.reportParseError(\"Expected identifier, string or number as member name\");\n                    if (this.errorRecovery) {\n                        memberName = new MissingIdentifier();\n                        memberName.minChar = this.scanner.startPos;\n                        memberName.flags |= ASTFlags.Error;\n                        this.skip(errorRecoverySet | ErrorRecoverySet.Comma);\n                        memberName.limChar = this.scanner.lastTokenLimChar();\n                    }\n                }\n\n                if (!skippedTokenForGetSetId) {\n                    this.currentToken = this.scanner.scan();\n                }\n                else {\n                    skippedTokenForGetSetId = false;\n                }\n\n                if (this.currentToken.tokenId == TokenID.Question) {\n                    memberName.flags |= ASTFlags.OptionalName;\n                    this.currentToken = this.scanner.scan();\n                }\n\n                if (accessorPattern) {\n                    var args = new ASTList();\n                    this.parseFormalParameterList(errorRecoverySet | ErrorRecoverySet.RParen,\n                                      args, false, true, false, !isSet, isSet, false, null, true);\n\n                    var funcDecl: FuncDecl =\n                        this.parseFunctionStatements(errorRecoverySet | ErrorRecoverySet.RCurly,\n                                                <Identifier>memberName, false, true, args,\n                                                AllowedElements.None,\n                                                this.scanner.startPos, false, Modifiers.None);\n\n                    if (isSet && funcDecl.returnTypeAnnotation) {\n                        this.reportParseError(\"Property setters may not declare a return type\");\n                    }\n\n                    funcDecl.fncFlags |= isSet ? FncFlags.SetAccessor : FncFlags.GetAccessor;\n                    funcDecl.fncFlags |= FncFlags.IsFunctionExpression;\n                    funcDecl.hint = idHint;\n                    memberExpr = funcDecl;\n                    member = new BinaryExpression(NodeType.Member, memberName, memberExpr);\n                    member.minChar = memberName.minChar;\n                    if (memberExpr.nodeType == NodeType.FuncDecl) {\n                        var funcDecl = <FuncDecl>memberExpr;\n                        funcDecl.hint = idHint;\n                    }\n                }\n                else if (this.currentToken.tokenId == TokenID.Colon) {\n                    this.currentToken = this.scanner.scan();\n                    memberExpr = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n                                         OperatorPrecedence.Comma, true, TypeContext.NoTypes);\n                    // If the memberExpr is a type reference, we can be certain that it was an\n                    // array type declaraion that lacked a \"new\".  We can realistically only\n                    // expect call and name ASTs to be the result of this call to parseExpr.\n                    // If it's a constructor without a \"new\", we'll flag it as an invalid\n                    // call site later on.\n                    if (memberExpr.nodeType == NodeType.TypeRef) {\n                        this.reportParseError(\"Expected 'new' on array declaration in member definition\")\n                    }\n                    member = new BinaryExpression(NodeType.Member, memberName, memberExpr);\n                    member.minChar = memberName.minChar;\n                    if (memberExpr.nodeType == NodeType.FuncDecl) {\n                        var funcDecl = <FuncDecl>memberExpr;\n                        funcDecl.hint = idHint;\n                    }\n                }\n                else {\n                    this.reportParseError(\"Expected ':' in member definition\");\n                    if (this.errorRecovery) {\n                        this.skip(errorRecoverySet);\n                        elements.flags |= ASTFlags.Error;\n                        elements.minChar = minChar;\n                        elements.limChar = this.scanner.lastTokenLimChar();\n                        return elements;\n                    }\n                }\n                idHint = null;\n                elements.append(member);\n                member.limChar = this.scanner.lastTokenLimChar();\n                if (this.currentToken.tokenId != TokenID.Comma) {\n                    break;\n                }\n                else {\n                    // munch comma\n                    this.currentToken = this.scanner.scan();\n                }\n\n                // trailing comma allowed\n                if (this.currentToken.tokenId == TokenID.CloseBrace) {\n                    break;\n                }\n            }\n\n            if (member) {\n                elements.limChar = member.limChar;\n            }\n            elements.minChar = minChar;\n            return elements;\n        }\n\n        private parseArrayList(errorRecoverySet: ErrorRecoverySet): ASTList {\n            var elements: ASTList = null;\n            if (this.currentToken.tokenId == TokenID.CloseBracket) {\n                return elements;\n            }\n            else {\n                elements = new ASTList();\n                elements.minChar = this.scanner.startPos;\n            }\n\n            var arg: AST;\n\n            for (; ;) {\n                if ((this.currentToken.tokenId == TokenID.Comma) ||\n                    (this.currentToken.tokenId == TokenID.CloseBracket)) {\n                    arg = new AST(NodeType.EmptyExpr);\n                }\n                else {\n                    arg = this.parseExpr(ErrorRecoverySet.Comma | errorRecoverySet,\n                                  OperatorPrecedence.Comma, true, TypeContext.NoTypes);\n                }\n                elements.append(arg);\n                if (this.currentToken.tokenId != TokenID.Comma) {\n                    break;\n                }\n                this.currentToken = this.scanner.scan();\n            }\n            elements.limChar = this.scanner.lastTokenLimChar();\n            return elements;\n        }\n\n        private parseArrayLiteral(errorRecoverySet: ErrorRecoverySet): UnaryExpression {\n            var arrayLiteral: UnaryExpression = null;\n            arrayLiteral = new UnaryExpression(NodeType.ArrayLit,\n                                             this.parseArrayList(errorRecoverySet));\n            return arrayLiteral;\n        }\n\n        private parseTerm(errorRecoverySet: ErrorRecoverySet, allowCall: bool, typeContext: TypeContext, inCast: bool): AST {\n            var ast: AST = null;\n            var sawId = false;\n            var inNew = false;\n            var minChar = this.scanner.startPos;\n            var limChar = this.scanner.pos;\n            var parseAsLambda = false;\n            var expectlambdaRParen = false;\n\n            // keywords first\n            switch (this.currentToken.tokenId) {\n                case TokenID.Number:\n                case TokenID.Bool:\n                case TokenID.Any:\n                case TokenID.String:\n                    var tid = new Identifier(tokenTable[this.currentToken.tokenId].text);\n                    if (hasFlag(typeContext, TypeContext.Primitive)) {\n                        ast = new TypeReference(tid, 0);\n                        sawId = true;\n                    }\n                    else {\n                        ast = tid;\n                        sawId = true;\n                    }\n                    ast.minChar = minChar;\n                    this.currentToken = this.scanner.scan();\n                    limChar = this.scanner.lastTokenLimChar();\n                    break;\n                case TokenID.This:\n                    ast = new AST(NodeType.This);\n                    ast.minChar = minChar;\n                    this.currentToken = this.scanner.scan();\n                    limChar = this.scanner.lastTokenLimChar();\n                    break;\n                case TokenID.Super:\n                    ast = new AST(NodeType.Super);\n                    ast.minChar = minChar;\n                    this.currentToken = this.scanner.scan();\n                    limChar = this.scanner.lastTokenLimChar();\n                    break;\n                case TokenID.True:\n                    ast = new AST(NodeType.True);\n                    this.currentToken = this.scanner.scan();\n                    ast.minChar = minChar;\n                    break;\n                case TokenID.False:\n                    ast = new AST(NodeType.False);\n                    this.currentToken = this.scanner.scan();\n                    ast.minChar = minChar;\n                    break;\n                case TokenID.Null:\n                    ast = new AST(NodeType.Null);\n                    this.currentToken = this.scanner.scan();\n                    ast.minChar = minChar;\n                    break;\n                case TokenID.New:\n                    minChar = this.scanner.pos;\n                    this.currentToken = this.scanner.scan();\n                    var target = this.parseTerm(errorRecoverySet, false, TypeContext.AllSimpleTypes, inCast);\n\n                    if (target.nodeType == NodeType.Error || (target.nodeType == NodeType.Index && (<BinaryExpression>target).operand1.nodeType == NodeType.TypeRef)) {\n                        this.reportParseError(\"Cannot invoke 'new' on this expression\");\n                    } else {\n                        ast = new CallExpression(NodeType.New, target, null);\n                        ast.minChar = minChar;\n                        limChar = this.scanner.lastTokenLimChar();\n                        inNew = true;\n                    }\n                    break;\n                case TokenID.Function:\n                    minChar = this.scanner.pos;\n                    ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, Modifiers.None, null, true);\n                    (<FuncDecl>ast).fncFlags |= FncFlags.IsFunctionExpression;\n                    ast.minChar = minChar;\n                    limChar = this.scanner.lastTokenLimChar();\n                    ast.limChar = limChar;\n                    break;\n            }\n\n            if (ast == null) {\n                if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n\n                    var idText = this.currentToken.getText();\n                    ast = this.createRef(idText, (<IdentifierToken>this.currentToken).hasEscapeSequence, minChar);\n                    sawId = true;\n \n                    ast.minChar = minChar;\n                    this.currentToken = this.scanner.scan();\n\n                    if (this.currentToken.tokenId == TokenID.Question) {\n                        ast.flags |= ASTFlags.PossibleOptionalParameter;\n                    }\n\n                    limChar = this.scanner.lastTokenLimChar();\n                }\n            }\n\n            if (inCast) {\n                this.checkCurrentToken(TokenID.GreaterThan, errorRecoverySet);\n            }\n\n            if (ast == null) {\n                switch (this.currentToken.tokenId) {\n                    case TokenID.OpenParen:\n                        minChar = this.scanner.pos;\n                        var prevTokId = this.scanner.previousToken().tokenId;\n                        this.currentToken = this.scanner.scan();\n\n                        var couldBeLambda = prevTokId == TokenID.OpenParen || // foo(()=>{});\n                                            prevTokId == TokenID.Comma || // foo(x,()=>{});\n                                            prevTokId == TokenID.EqualsEquals || // var foo = ()=>{};\n                                            prevTokId == TokenID.Colon;    // var x = { foo: ()=> {} };\n\n\n                        if (couldBeLambda && this.currentToken.tokenId == TokenID.CloseParen) {\n                            parseAsLambda = true;\n                            expectlambdaRParen = false;\n                            this.currentToken = this.scanner.scan();\n                        }\n                        else if (couldBeLambda && this.currentToken.tokenId == TokenID.DotDotDot) {\n                            parseAsLambda = true;\n                            expectlambdaRParen = true;\n                        }\n                        else {\n                            ast = this.parseExpr(errorRecoverySet | ErrorRecoverySet.RParen,\n                                          OperatorPrecedence.None, true, TypeContext.NoTypes, couldBeLambda);\n                            limChar = this.scanner.lastTokenLimChar();\n                            parseAsLambda = couldBeLambda && (ast.nodeType == NodeType.Name || ast.nodeType == NodeType.Comma) &&\n                                            (this.currentToken.tokenId == TokenID.Colon || this.currentToken.tokenId == TokenID.Question);\n                            expectlambdaRParen = true;\n                        }\n\n                        // Check for the RParen if it's not an anonymous '=>' function\n                        if ((ast && !parseAsLambda)) {\n                            if (hasFlag(ast.flags, ASTFlags.SkipNextRParen)) {\n                                // REVIEW: parseExpr resulted in a lambda node, the LParen scanned earlier, is the beginning of that node, and not of a parenthesized expression;\n                                //         do not look for a matching RParen for this node, but make sure to remove the flag, so that any enclosing parenthesis are matched correctly.\n                                ast.flags = ast.flags & (~(ASTFlags.SkipNextRParen)); \n                                break;\n                            }\n                            this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet);\n                            ast.isParenthesized = true;\n                        }\n\n                        break;\n                    case TokenID.NumberLiteral: {\n                        var numTok = <NumberLiteralToken>this.currentToken;\n                        this.currentToken = this.scanner.scan();\n                        ast = new NumberLiteral(numTok.value, numTok.hasEmptyFraction);\n                        ast.minChar = minChar;\n                        limChar = this.scanner.lastTokenLimChar();\n                        break;\n                    }\n                    case TokenID.StringLiteral:\n                        ast = new StringLiteral(this.currentToken.getText());\n                        this.currentToken = this.scanner.scan();\n                        ast.minChar = minChar;\n                        limChar = this.scanner.lastTokenLimChar();\n                        break;\n                    case TokenID.RegularExpressionLiteral: {\n                        var rtok = <RegularExpressionLiteralToken>this.currentToken;\n                        ast = new RegexLiteral(rtok.regex);\n                        this.currentToken = this.scanner.scan();\n                        ast.minChar = minChar;\n                        limChar = this.scanner.lastTokenLimChar();\n                        break;\n                    }\n                    case TokenID.OpenBracket:\n                        minChar = this.scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        ast = this.parseArrayLiteral(ErrorRecoverySet.RBrack | errorRecoverySet);\n                        ast.minChar = minChar;\n                        limChar = this.scanner.pos; // ']'\n                        this.checkCurrentToken(TokenID.CloseBracket, errorRecoverySet);\n                        break;\n                    // TODO: rescan regex for TokenID.Div and AsgDiv\n                        case TokenID.OpenBrace:\n                        minChar = this.scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        var members = this.parseMemberList(ErrorRecoverySet.RCurly | errorRecoverySet)\n                        this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n                        ast = new UnaryExpression(NodeType.ObjectLit, members);\n                        ast.minChar = minChar;\n                        limChar = this.scanner.lastTokenLimChar();\n                        members.minChar = minChar;\n                        members.limChar = limChar;\n                        break;\n\n                    case TokenID.LessThan:\n                        minChar = this.scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        var term: AST = this.parseTypeReference(ErrorRecoverySet.BinOp, false);\n                        this.checkCurrentToken(TokenID.GreaterThan, errorRecoverySet);\n                        ast = new UnaryExpression(NodeType.TypeAssertion, this.parseExpr(errorRecoverySet, OperatorPrecedence.Unary, false, TypeContext.NoTypes));\n                        (<UnaryExpression>ast).castTerm = term;\n                        break;\n\n                    default:\n                        if (this.prevExpr && hasFlag(this.prevExpr.flags, ASTFlags.PossibleOptionalParameter)) {\n                            parseAsLambda = true;\n                            ast = this.prevExpr;\n                        }\n                        else {\n                            this.reportParseError(\"Check format of expression term\");\n                            if (this.errorRecovery) {\n                                var ident = new MissingIdentifier();\n                                ident.minChar = minChar;\n                                ident.flags |= ASTFlags.Error;\n                                this.skip(errorRecoverySet | ErrorRecoverySet.Postfix);\n                                if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                                    ident.setText(this.currentToken.getText(), (<IdentifierToken>this.currentToken).hasEscapeSequence);\n                                    this.currentToken = this.scanner.scan();\n                                    limChar = this.scanner.lastTokenLimChar();\n                                }\n                                else {\n                                    limChar = this.scanner.lastTokenLimChar();\n                                    //tok=scanner.scan();\n                                }\n\n                                // REVIEW: set sawId\n                                ast = ident;\n                            }\n                        }\n                }\n            }\n\n            if (parseAsLambda) {\n                // If the next token is an fat arrow or a colon, we either have a parameter list, or can rightly assume\n                // that we have a typed formal, so we proceed with the lambda parse\n                if (\n                    this.currentToken.tokenId == TokenID.Colon ||\n                    this.currentToken.tokenId == TokenID.Comma ||\n                    this.currentToken.tokenId == TokenID.CloseParen ||\n                    this.currentToken.tokenId == TokenID.DotDotDot) {\n\n                        // We won't scan in the ':' case, since keeping the ':' simplifies argument handling in parseFormalParameterList\n                        // Note that we don't set the minchar in this case\n                    ast = this.parseLambdaExpr(errorRecoverySet, ast, true /* skipNextRParen */, expectlambdaRParen);\n                    ast.minChar = minChar;\n                    limChar = this.scanner.lastTokenLimChar();\n                    ast.limChar = limChar;\n                }\n                else if (ast) {\n                    ast.isParenthesized = true;\n                }\n            }\n\n            if (sawId && (typeContext != TypeContext.NoTypes)) {\n                typeContext |= TypeContext.ArraySuffix;\n            }\n\n            var postFix = this.parsePostfixOperators(errorRecoverySet, ast, allowCall, inNew, typeContext, minChar, limChar);\n\n            // Defensive error check...\n            if (postFix) {\n                if (sawId && (postFix.nodeType == NodeType.Index)) {\n                    var binExpr = <BinaryExpression>postFix;\n                    if (binExpr.operand2 == null) {\n                        postFix = this.convertToTypeReference(postFix);\n                    }\n                }\n\n                ///////////////////////////////////////////////////////////\n                //TODO: Eventually, we want to remove \"minChar\" and \"limChar\" assignments here,\n                //      as they are sometimes not specific enough for each expression kind.\n                postFix.minChar = minChar;\n                // Only update \"limChar\" if it is not better than \"lastTokenLimChar()\"\n                postFix.limChar = max(postFix.limChar, this.scanner.lastTokenLimChar());\n                //\n                ///////////////////////////////////////////////////////////\n                return postFix;\n            }\n            else {\n                return new AST(NodeType.Error);\n            }\n\n        }\n\n        private parseLambdaExpr(errorRecoverySet: ErrorRecoverySet, lambdaArgs: AST, skipNextRParen: bool, expectClosingRParen: bool): AST {\n            // REVIEW: Parse the remainder of a lambda expression. The opening paren has been read already, if it existed. \n            //         skipNextRParen sets a flag on the resulting lambda node to tell the calling parseTerm that the LParen it scanned has been matched as part of parsing the formal parameter list\n            //         expectClosingRParen indicates that a closing RParen is expected, in the cases with optional parameter or more than one parameter.\n            var ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, Modifiers.None, { preProcessedLambdaArgs: lambdaArgs }, expectClosingRParen);\n            (<FuncDecl>ast).fncFlags |= FncFlags.IsFunctionExpression;\n            (<FuncDecl>ast).fncFlags |= FncFlags.IsFatArrowFunction;\n            if (!skipNextRParen) {\n                ast.flags |= ASTFlags.SkipNextRParen;\n            }\n            ast.limChar = this.scanner.lastTokenLimChar();;\n            return ast;\n        }\n\n        private parseExpr(errorRecoverySet: ErrorRecoverySet, minPrecedence: number, allowIn: bool,\n            typeContext: TypeContext, possiblyInLambda: bool = false): AST {\n            var ast: AST = null;\n            var tokenInfo = lookupToken(this.currentToken.tokenId);\n            var canAssign: bool = true;\n            var idHint: string = null;\n            var minChar = this.scanner.startPos;\n            var preComments = this.parseComments();\n            var exprIsAnonLambda = false;\n\n            if ((tokenInfo != undefined) && (tokenInfo.unopNodeType != NodeType.None)) {\n                canAssign = false;\n                this.currentToken = this.scanner.scan();\n                var tempExpr = this.parseExpr(ErrorRecoverySet.BinOp | errorRecoverySet,\n                                       tokenInfo.unopPrecedence, allowIn,\n                                       TypeContext.NoTypes);\n\n                // fold unary +- into constants\n                if ((tokenInfo.unopNodeType == NodeType.Pos) &&\n                    (tempExpr.nodeType == NodeType.NumberLit)) {\n                    ast = tempExpr;\n                }\n                else if ((tokenInfo.unopNodeType == NodeType.Neg) &&\n                         (tempExpr.nodeType == NodeType.NumberLit)) {\n                    var numLit = <NumberLiteral>tempExpr;\n                    numLit.value = (-numLit.value);\n                    if (numLit.value == 0) {\n                        numLit.isNegativeZero = true;\n                    }\n                    ast = tempExpr;\n                }\n                else {\n                    ast = new UnaryExpression(tokenInfo.unopNodeType, tempExpr);\n                    ast.limChar = tempExpr.limChar;\n                }\n                ast.minChar = minChar;\n            }\n            else {\n                ast = this.parseTerm(ErrorRecoverySet.BinOp | ErrorRecoverySet.AddOp |\n                              errorRecoverySet, true, typeContext, false);\n                var id: Identifier;\n                var temp: AST;\n                if (ast.nodeType == NodeType.Name) {\n                    id = <Identifier>ast;\n                    idHint = id.actualText;\n                }\n                else if (ast.nodeType == NodeType.Dot) {\n\n                    // If this is within a class declaration, and the circumstances are right, we need to\n                    // transform the dotted expression into a member declaration\n                    var subsumedExpr = false;\n\n                    if (this.inferPropertiesFromThisAssignment && \n                        (this.currentToken.tokenId == TokenID.Colon || this.currentToken.tokenId == TokenID.Equals) &&\n                         this.parsingClassConstructorDefinition &&\n                         this.nestingLevel == this.currentClassDefinition.constructorNestingLevel && // this nesting level means we're at the top-level in the constructor\n                         (<BinaryExpression>ast).operand1.nodeType == NodeType.This) {\n\n                        if ((<BinaryExpression>ast).operand2.nodeType == NodeType.Name) {\n                            var op2ID: Identifier = (<Identifier>(<BinaryExpression>ast).operand2);\n\n                            if (!this.currentClassDefinition.knownMemberNames[op2ID.actualText]) {\n                                ast = this.parseClassMemberVariableDeclaration(op2ID, ast.minChar, true, errorRecoverySet, Modifiers.Public);\n                                subsumedExpr = true;\n                            }\n                        }\n                    }\n\n                    if (!subsumedExpr) {\n                        temp = ast;\n                        while (temp.nodeType == NodeType.Dot) {\n                            var binExpr = <BinaryExpression>temp;\n                            temp = binExpr.operand2;\n                        }\n                        if (temp.nodeType == NodeType.Name) {\n                             id = <Identifier>temp;\n                            idHint = id.actualText;\n                        }\n                    }\n                }\n                if ((!this.scanner.lastTokenHadNewline()) &&\n                    ((this.currentToken.tokenId == TokenID.PlusPlus) || (this.currentToken.tokenId == TokenID.MinusMinus))) {\n                    canAssign = false;\n                    var operand = ast;\n                    ast = new UnaryExpression((this.currentToken.tokenId == TokenID.PlusPlus) ? NodeType.IncPost : NodeType.DecPost, operand);\n                    ast.limChar = this.scanner.pos;\n                    ast.minChar = operand.minChar;\n                    this.currentToken = this.scanner.scan();\n                }\n            }\n            for (; ;) {\n                tokenInfo = lookupToken(this.currentToken.tokenId);\n                if ((tokenInfo == undefined) || (tokenInfo.binopNodeType == NodeType.None)) {\n                    break;\n                }\n                if ((!allowIn) && (tokenInfo.binopNodeType == NodeType.In)) {\n                    break;\n                }\n                if (tokenInfo.binopPrecedence == OperatorPrecedence.Assignment) {\n                    if (tokenInfo.binopPrecedence < minPrecedence) {\n                        break;\n                    }\n                    if (!canAssign) {\n                        this.reportParseError(\"illegal assignment\");\n                    }\n                }\n                else if (tokenInfo.binopPrecedence <= minPrecedence) {\n                    break;\n                }\n\n                if (possiblyInLambda && this.currentToken.tokenId == TokenID.Comma && this.scanner.getLookAheadToken().tokenId == TokenID.DotDotDot) {\n                    // The ellipsis can only exist in the formal list of a lambda expression, so do not attempt to parse the comma token as the comma binary operator\n                    // instead parse it as a lambda\n                    exprIsAnonLambda = true;\n                    canAssign = false;\n                    ast = this.parseLambdaExpr(errorRecoverySet, ast, false, true);\n                    break;\n                }\n\n                // Precedence is high enough. Consume the operator token.\n                this.currentToken = this.scanner.scan();\n                canAssign = false;\n                if (tokenInfo.binopNodeType == NodeType.ConditionalExpression) {\n                    if (possiblyInLambda && \n                        ( this.currentToken.tokenId == TokenID.Equals || this.currentToken.tokenId == TokenID.Colon || this.currentToken.tokenId == TokenID.CloseParen || this.currentToken.tokenId == TokenID.Comma)) {\n                        // The QMark is not a ternary expression, it is a marker for optional parameter in a lambda expression.\n                        exprIsAnonLambda = true;\n                        canAssign = true;\n                    }\n                    else {\n                        this.prevExpr = ast;\n                        var whenTrue = this.parseExpr(\n                            errorRecoverySet | ErrorRecoverySet.Colon, OperatorPrecedence.Assignment, allowIn, TypeContext.NoTypes);\n\n                        // Do not hold onto the prevExpr handle\n                        this.prevExpr = null;\n                        this.checkCurrentToken(TokenID.Colon, errorRecoverySet | ErrorRecoverySet.ExprStart);\n\n                        var whenFalse = this.parseExpr(\n                            errorRecoverySet | ErrorRecoverySet.BinOp, OperatorPrecedence.Assignment, allowIn, TypeContext.NoTypes)\n                        ast = new ConditionalExpression(ast, whenTrue, whenFalse);\n                    }\n                }\n                else {\n                    var tc = TypeContext.NoTypes;\n                    var binExpr2: BinaryExpression;\n\n                    binExpr2 = new BinaryExpression(tokenInfo.binopNodeType, ast,\n                                                    this.parseExpr(errorRecoverySet |\n                                                            ErrorRecoverySet.BinOp,\n                                                            tokenInfo.binopPrecedence,\n                                                            allowIn, TypeContext.NoTypes, possiblyInLambda));\n                    if (binExpr2.operand2.nodeType == NodeType.FuncDecl) {\n                        var funcDecl = <FuncDecl>binExpr2.operand2;\n                        funcDecl.hint = idHint;\n                    }\n\n                    binExpr2.minChar = ast.minChar;\n                    binExpr2.limChar = this.scanner.lastTokenLimChar();\n                    idHint = null;\n                    ast = binExpr2;\n                }\n            }\n            if (canAssign) {\n                ast.flags |= ASTFlags.Writeable;\n            }\n            if (!exprIsAnonLambda) {\n                ///////////////////////////////////////////////////////////\n                //TODO: Eventually, we want to remove \"minChar\" and \"limChar\" assignments here,\n                //      as they are sometimes not specific enough for each statement kind.\n                ast.minChar = minChar;\n                // Only update \"limChar\" if it is not better than \"lastTokenLimChar()\"\n                ast.limChar = max(ast.limChar, this.scanner.lastTokenLimChar());\n                //\n                ///////////////////////////////////////////////////////////\n                ast.preComments = preComments;\n                ast.postComments = this.parseCommentsForLine(this.scanner.line);\n            }\n            return ast;\n        }\n\n        private parsePostfixOperators(errorRecoverySet: ErrorRecoverySet, ast: AST, allowCall: bool, inNew: bool,\n            typeContext: TypeContext, lhsMinChar: number, lhsLimChar: number): AST {\n            var count = 0;\n\n            if (!ast) {\n                ast = new AST(NodeType.EmptyExpr);\n                ast.isParenthesized = true;\n            }\n\n            ast.minChar = lhsMinChar;\n            ast.limChar = lhsLimChar;\n\n            for (; ;) {\n                switch (this.currentToken.tokenId) {\n                    case TokenID.OpenParen:\n                        if (inNew) {\n                            var callExpr = <CallExpression>ast;\n                            callExpr.arguments = this.parseArgList(errorRecoverySet);\n                            inNew = false;\n                        }\n                        else {\n                            if (!allowCall) {\n                                return ast;\n                            }\n                            ast = new CallExpression(NodeType.Call, ast,\n                                                   this.parseArgList(errorRecoverySet));\n                            ast.minChar = lhsMinChar;\n                        }\n                        ast.limChar = this.scanner.pos; // ')'\n                        this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet);\n                        break;\n                    case TokenID.OpenBracket:\n                        this.currentToken = this.scanner.scan();\n                        if (this.currentToken.tokenId == TokenID.CloseBracket) {\n                            if (hasFlag(typeContext, TypeContext.ArraySuffix)) {\n                                this.currentToken = this.scanner.scan();\n                                if (ast.nodeType == NodeType.TypeRef) {\n                                    var typeRef = <TypeReference>ast;\n                                    typeRef.arrayCount++;\n                                }\n                                else {\n                                    ast = new BinaryExpression(NodeType.Index, ast, null);\n                                }\n                                ast.limChar = this.scanner.pos;\n                                break; // note early exit from case\n                            }\n                        }\n\n                        ast = new BinaryExpression(NodeType.Index, ast,\n                                                 this.parseExpr(errorRecoverySet | ErrorRecoverySet.RBrack,\n                                                           OperatorPrecedence.None, true,\n                                                           TypeContext.NoTypes));\n                        ast.minChar = lhsMinChar;\n                        ast.limChar = this.scanner.pos; // ']'\n                        this.checkCurrentToken(TokenID.CloseBracket, errorRecoverySet);\n                        break;\n                    case TokenID.Dot: {\n                        var name: Identifier = null;\n                        var curpos = this.scanner.pos;\n                        this.currentToken = this.scanner.scan();\n                        // Don't allow reserved words if immediately after a new line and error recovery is enabled\n                        if ((this.currentToken.tokenId == TokenID.Identifier) || ((!this.errorRecovery || !this.scanner.lastTokenHadNewline()) && convertTokToIDName(this.currentToken))) {\n                            ast.flags |= ASTFlags.DotLHS;\n                            name = this.createRef(this.currentToken.getText(), (<IdentifierToken>this.currentToken).hasEscapeSequence, this.scanner.startPos);\n                            name.limChar = this.scanner.pos;\n                            this.currentToken = this.scanner.scan();\n                        }\n                        else {\n                            this.reportParseError(\"Expected identifier following dot\");\n                            if (this.errorRecovery) {\n                                this.skip(errorRecoverySet);\n                                ast.flags |= (ASTFlags.Error | ASTFlags.DotLHS);\n                                return ast;\n                            }\n                            else {\n                                name = new MissingIdentifier();\n                            }\n                        }\n                        ast = new BinaryExpression(NodeType.Dot, ast, name);\n                        ast.minChar = lhsMinChar;\n                        ast.limChar = this.scanner.lastTokenLimChar();\n                        break;\n                    }\n                    case TokenID.EqualsGreaterThan:\n                        ast = this.parseFncDecl(errorRecoverySet, false, false, false, null, false, false, false, Modifiers.None, { preProcessedLambdaArgs: ast }, false);\n                        (<FuncDecl>ast).fncFlags |= FncFlags.IsFunctionExpression;\n                        ast.minChar = lhsMinChar;\n                        ast.limChar = this.scanner.lastTokenLimChar();\n                        break;\n                    default:\n                        return ast;\n\n                }\n            }\n        }\n\n        private parseTry(tryNode: Try, errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers): Try {\n            var minChar = this.scanner.startPos;\n            var preComments = this.parseComments();\n            this.currentToken = this.scanner.scan();\n            if (this.currentToken.tokenId != TokenID.OpenBrace) {\n                this.reportParseError(\"Expected '{'\");\n                if (this.errorRecovery) {\n                    var etryNode = tryNode;\n                    etryNode.minChar = minChar;\n                    etryNode.limChar = this.scanner.lastTokenLimChar();\n                    etryNode.flags |= ASTFlags.Error;\n                    return etryNode;\n                }\n            }\n            tryNode.body = this.parseStatement(errorRecoverySet, AllowedElements.None, parentModifiers);\n            tryNode.minChar = minChar;\n            tryNode.limChar = tryNode.body.limChar;\n            tryNode.preComments = preComments;\n            tryNode.postComments = this.parseComments();\n            return tryNode;\n        }\n\n        private parseCatch(errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers): Catch {\n            var catchMinChar = this.scanner.startPos;\n            var preComments = this.parseComments();\n            this.currentToken = this.scanner.scan();\n            this.checkCurrentToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart);\n            if ((this.currentToken.tokenId != TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                this.reportParseError(\"Expected identifier in catch header\");\n                if (this.errorRecovery) {\n                    this.skip(errorRecoverySet);\n\n                    var ecatch = new Catch(new VarDecl(new MissingIdentifier(), this.nestingLevel),\n                                            new Statement(NodeType.Empty));\n                    ecatch.statement.minChar = catchMinChar;\n                    ecatch.statement.limChar = this.scanner.pos;\n                    ecatch.minChar = this.scanner.startPos;\n                    ecatch.limChar = this.scanner.pos;\n                    ecatch.flags |= ASTFlags.Error;\n                    return ecatch;\n                }\n            }\n            var param = new VarDecl(Identifier.fromToken(this.currentToken), this.nestingLevel);\n            param.id.minChar = this.scanner.startPos;\n            param.id.limChar = this.scanner.pos;\n            param.minChar = param.id.minChar;\n            param.limChar = param.id.limChar;\n            this.currentToken = this.scanner.scan();\n            var statementPos = this.scanner.pos;\n            this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.StmtStart);\n            if (this.currentToken.tokenId != TokenID.OpenBrace) {\n                this.reportParseError(\"Expected '{' to start catch body\");\n                if (this.errorRecovery) {\n                    this.skip(errorRecoverySet);\n\n                    var ecatch = new Catch(new VarDecl(new MissingIdentifier(), this.nestingLevel),\n                                            new Statement(NodeType.Empty));\n                    ecatch.statement.minChar = catchMinChar;\n                    ecatch.statement.limChar = statementPos;\n                    ecatch.minChar = this.scanner.startPos;\n                    ecatch.limChar = this.scanner.pos;\n                    ecatch.flags |= ASTFlags.Error;\n                    return ecatch;\n                }\n            }\n\n            var catchStmt = this.parseStatement(errorRecoverySet, AllowedElements.None, parentModifiers);\n            var catchNode = new Catch(param, catchStmt);\n            catchNode.statement.minChar = catchMinChar;\n            catchNode.statement.limChar = statementPos;\n            catchNode.minChar = catchMinChar;\n            catchNode.limChar = catchStmt.limChar;\n            catchNode.preComments = preComments;\n            catchNode.postComments = this.parseComments();\n            return catchNode;\n        }\n\n        private parseFinally(errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers): Finally {\n            var finMinChar = this.scanner.startPos;\n            var preComments = this.parseComments();\n            this.currentToken = this.scanner.scan();\n            if (this.currentToken.tokenId != TokenID.OpenBrace) {\n                this.reportParseError(\"Expected '{' to start body of finally statement\");\n                if (this.errorRecovery) {\n                    this.skip(errorRecoverySet);\n                    var efin = new Finally(new Statement(NodeType.Empty));\n                    efin.flags |= ASTFlags.Error;\n                    efin.minChar = this.scanner.startPos;\n                    efin.limChar = this.scanner.pos;\n                    return efin;\n                }\n            }\n\n            var finBody = this.parseStatement(errorRecoverySet, AllowedElements.None, parentModifiers)\n            var fin = new Finally(finBody);\n            fin.minChar = finMinChar;\n            fin.limChar = fin.body.limChar;\n            fin.preComments = preComments;\n            fin.postComments = this.parseComments();\n            return fin;\n        }\n\n        private parseTryCatchFinally(errorRecoverySet: ErrorRecoverySet, parentModifiers: Modifiers, labelList: ASTList): AST {\n            var tryPart: AST = new Try(null);\n            var tryMinChar = this.scanner.startPos;\n            this.pushStmt(<Statement>tryPart, labelList);\n            this.parseTry(<Try>tryPart, errorRecoverySet | ErrorRecoverySet.Catch, parentModifiers);\n            this.popStmt();\n            var tc: TryCatch = null;\n            var tf: TryFinally = null;\n\n            if (this.currentToken.tokenId == TokenID.Catch) {\n                var catchPart = this.parseCatch(errorRecoverySet | ErrorRecoverySet.Catch, parentModifiers);\n                tc = new TryCatch(<Try>tryPart, catchPart);\n                tc.minChar = tryPart.minChar;\n                tc.limChar = catchPart.limChar;\n            }\n\n            if (this.currentToken.tokenId != TokenID.Finally) {\n                if (tc == null) {\n                    this.reportParseError(\"try with neither catch nor finally\");\n                    if (this.errorRecovery) {\n                        var etf = new TryFinally(tryPart, new Finally(new AST(NodeType.Empty)));\n                        etf.flags |= ASTFlags.Error;\n                        etf.minChar = this.scanner.startPos;\n                        etf.limChar = this.scanner.pos;\n                        return etf;\n                    }\n                    return new TryFinally(tryPart, new Finally(new AST(NodeType.Empty)));\n                }\n                else {\n                    return tc;\n                }\n            }\n            else {\n                if (tc) {\n                    tryPart = tc;\n                }\n                var finallyPart = this.parseFinally(errorRecoverySet, parentModifiers)\n                tf = new TryFinally(tryPart, finallyPart);\n                tf.minChar = tryMinChar;\n                tf.limChar = finallyPart.limChar;\n                return tf;\n            }\n        }\n\n        private parseStatement(errorRecoverySet: ErrorRecoverySet, allowedElements: AllowedElements, parentModifiers: Modifiers): AST {\n            var ast: AST = null;\n            var labelList: ASTList = null;\n            var astList: ASTList = null;\n            var temp: AST;\n            var modifiers = Modifiers.None;\n            var minChar = this.scanner.startPos;\n            var forInOk = false;\n            var needTerminator = false;\n            var fnOrVar: AST = null;\n            var preComments = this.parseComments();\n            this.state = ParseState.StartStatement;\n\n            function isAmbient() {\n                return hasFlag(modifiers, Modifiers.Ambient) || hasFlag(parentModifiers, Modifiers.Ambient);\n            }\n\n            function mayNotBeExported() {\n                if (hasFlag(modifiers, Modifiers.Exported)) {\n                    this.reportError(\"Statement may not be exported\");\n                }\n            }\n\n            for (; ;) {\n                switch (this.currentToken.tokenId) {\n                    case TokenID.EndOfFile:\n                        ast = new AST(NodeType.Error);\n                        ast.minChar = minChar;\n                        ast.limChar = this.scanner.pos;\n                        break;\n                    case TokenID.Function:\n                        if (this.parsingDeclareFile || isAmbient() || this.ambientModule) {\n                            this.currentToken = this.scanner.scan();\n                            fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | ErrorRecoverySet.SColon,\n                                                      modifiers, true, false);\n                            if (fnOrVar.nodeType == NodeType.VarDecl) {\n                                this.reportParseError(\"function keyword can only introduce function declaration\");\n                            }\n                            else if ((fnOrVar.nodeType == NodeType.FuncDecl) && ((<FuncDecl>fnOrVar).fncFlags, FncFlags.IsFatArrowFunction)) {\n                                needTerminator = true;\n                            }\n                            ast = fnOrVar;\n                            if (this.parsingDeclareFile || this.ambientModule && ast.nodeType == NodeType.FuncDecl) {\n                                (<FuncDecl>ast).fncFlags |= FncFlags.Exported;\n                            }\n                        }\n                        else {\n                            ast = this.parseFncDecl(errorRecoverySet, true, false, false, null, false, false, isAmbient(), modifiers, null, true);\n                            if (hasFlag((<FuncDecl>ast).fncFlags, FncFlags.IsFatArrowFunction)) {\n                                needTerminator = true;\n                            }\n                            if (this.ambientModule) {\n                                this.reportParseError(\"function declaration not permitted within ambient module\");\n                            }\n                            if (hasFlag(modifiers, Modifiers.Exported)) {\n                                (<FuncDecl>ast).fncFlags |= FncFlags.Exported;\n                            }\n                        }\n                        break;\n                    case TokenID.Module:\n                        if ((allowedElements & AllowedElements.ModuleDeclarations) == AllowedElements.None) {\n                            this.reportParseError(\"module not allowed in this context\");\n                            this.currentToken = this.scanner.scan();\n                            ast = new AST(NodeType.Error);\n                            ast.minChar = minChar;\n                            ast.limChar = this.scanner.lastTokenLimChar();\n                        }\n                        else {\n                            ast = this.parseModuleDecl(errorRecoverySet, modifiers, preComments);\n                            preComments = null;\n                        }\n                        break;\n                    case TokenID.Import:\n                        if ((allowedElements & AllowedElements.ModuleDeclarations) == AllowedElements.None) {\n                            this.reportParseError(\"module not allowed in this context\");\n                            this.currentToken = this.scanner.scan();\n                            ast = new AST(NodeType.Error);\n                            ast.minChar = minChar;\n                            ast.limChar = this.scanner.lastTokenLimChar();\n                        }\n                        else {\n                            if (hasFlag(modifiers, Modifiers.Exported)) {\n                                this.reportParseError(\"export keyword not permitted on import declaration\");\n                            }\n                            ast = this.parseImportDeclaration(errorRecoverySet, modifiers);\n                            needTerminator = true;\n                        }\n                        break;\n                    case TokenID.Export:\n                        if ((allowedElements & AllowedElements.ModuleDeclarations) == AllowedElements.None) {\n                            this.reportParseError(\"'export' statements are only allowed at the global and module levels\");\n                            this.currentToken = this.scanner.scan();\n                            ast = new AST(NodeType.Error);\n                            ast.minChar = minChar;\n                            ast.limChar = this.scanner.lastTokenLimChar();\n                        }\n                        if (this.topLevel) {\n                            this.hasTopLevelImportOrExport = true;\n                        }\n                        modifiers |= Modifiers.Exported;\n                        this.currentToken = this.scanner.scan();\n                        break;\n                    case TokenID.Private:\n                        modifiers |= Modifiers.Private;\n\n                        this.currentToken = this.scanner.scan();\n\n                        if (this.parsingClassConstructorDefinition) {\n\n                            if (!this.inferPropertiesFromThisAssignment) {\n                                this.reportParseError(\"Property declarations are not permitted within constructor bodies\");\n                            }\n\n                            minChar = this.scanner.pos;\n                            if (this.inferPropertiesFromThisAssignment && (this.currentToken.tokenId != TokenID.This || (this.currentToken = this.scanner.scan()).tokenId != TokenID.Dot)) {\n                                this.reportParseError(\"Expected 'this.' for property declaration\");\n                                this.currentToken = this.scanner.scan();\n                                ast = new AST(NodeType.Error);\n                                ast.minChar = minChar;\n                                ast.limChar = this.scanner.lastTokenLimChar();\n                            }\n                            else {\n                                this.currentToken = this.scanner.scan();\n\n                                var id = Identifier.fromToken(this.currentToken);\n                                id.minChar = this.scanner.startPos;\n                                id.limChar = this.scanner.pos;\n\n                                this.currentToken = this.scanner.scan();\n                                ast = this.parseClassMemberVariableDeclaration(id, minChar, this.parsingClassConstructorDefinition, errorRecoverySet, modifiers);\n                            }\n                        }\n                        else {\n                            if (this.currentToken.tokenId != TokenID.Interface) {\n                                if (this.currentToken.tokenId == TokenID.Get) {\n                                    this.prevIDTok = this.currentToken;\n                                    this.currentToken = this.scanner.scan();\n                                    if (codeGenTarget < CodeGenTarget.ES5) {\n                                        this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n                                    }\n                                    if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                                        modifiers |= Modifiers.Getter;\n                                        this.prevIDTok = null;\n                                    }\n                                }\n                                else if (this.currentToken.tokenId == TokenID.Set) {\n                                    this.prevIDTok = this.currentToken;\n                                    this.currentToken = this.scanner.scan();\n                                    if (codeGenTarget < CodeGenTarget.ES5) {\n                                        this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n                                    }\n                                    if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                                        modifiers |= Modifiers.Setter;\n                                        this.prevIDTok = null;\n                                    }\n                                }\n                                fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | ErrorRecoverySet.SColon,\n                                                          modifiers, isAmbient(), false);\n                                if ((fnOrVar.nodeType == NodeType.VarDecl) ||\n                                    ((fnOrVar.nodeType == NodeType.FuncDecl) && (hasFlag((<FuncDecl>fnOrVar).fncFlags, FncFlags.IsFatArrowFunction)))) {\n                                    needTerminator = true;\n                                }\n                                ast = fnOrVar;\n                            }\n                        }\n                        break;\n                    case TokenID.Public:\n                        if (this.parsingClassConstructorDefinition) {\n\n                            if (!this.inferPropertiesFromThisAssignment) {\n                                this.reportParseError(\"Property declarations are not permitted within constructor bodies\");\n                            }\n\n                            this.currentToken = this.scanner.scan(); \n                            minChar = this.scanner.pos;\n                            modifiers |= Modifiers.Public;\n                            if (this.inferPropertiesFromThisAssignment && (this.currentToken.tokenId != TokenID.This || (this.currentToken = this.scanner.scan()).tokenId != TokenID.Dot)) {\n                                this.reportParseError(\"Expected 'this.' for property declaration\");\n                                this.currentToken = this.scanner.scan();\n                                ast = new AST(NodeType.Error);\n                                ast.minChar = minChar;\n                                ast.limChar = this.scanner.lastTokenLimChar();\n                            }\n                            else {\n                                this.currentToken = this.scanner.scan();\n\n                                var id = Identifier.fromToken(this.currentToken);\n                                id.minChar = this.scanner.startPos;\n                                id.limChar = this.scanner.pos;\n\n                                this.currentToken = this.scanner.scan();\n                                ast = this.parseClassMemberVariableDeclaration(id, minChar, this.parsingClassConstructorDefinition, errorRecoverySet, modifiers);\n                            }\n                        }\n                        else {\n                            if ((allowedElements & AllowedElements.Properties) == AllowedElements.None) {\n                                this.reportParseError(\"'property' statements are only allowed within classes\");\n                                this.currentToken = this.scanner.scan();\n                                ast = new AST(NodeType.Error);\n                                ast.minChar = minChar;\n                                ast.limChar = this.scanner.lastTokenLimChar();\n                            }\n                            else {\n                                modifiers |= Modifiers.Public;\n                                this.currentToken = this.scanner.scan();\n                                if (this.currentToken.tokenId == TokenID.Get) {\n                                    this.prevIDTok = this.currentToken;\n                                    this.currentToken = this.scanner.scan();\n                                    if (codeGenTarget < CodeGenTarget.ES5) {\n                                        this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n                                    }\n                                    if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                                        modifiers |= Modifiers.Getter;\n                                        this.prevIDTok = null;\n                                    }\n                                }\n                                else if (this.currentToken.tokenId == TokenID.Set) {\n                                    this.prevIDTok = this.currentToken;\n                                    this.currentToken = this.scanner.scan();\n                                    if (codeGenTarget < CodeGenTarget.ES5) {\n                                        this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n                                    }\n                                    if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                                        modifiers |= Modifiers.Setter;\n                                        this.prevIDTok = null;\n                                    }\n                                }\n                                fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | ErrorRecoverySet.SColon,\n                                                            modifiers, isAmbient(), false);\n                                if ((fnOrVar.nodeType == NodeType.VarDecl) ||\n                                    ((fnOrVar.nodeType == NodeType.FuncDecl) && hasFlag((<FuncDecl>fnOrVar).fncFlags, FncFlags.IsFatArrowFunction))) {\n                                    needTerminator = true;\n                                }\n                                ast = fnOrVar;\n                            }\n                        }\n                        break;\n                    case TokenID.Declare:\n                        if (!(allowedElements & AllowedElements.AmbientDeclarations)) {\n                            this.reportParseError(\"Ambient declarations are only allowed at the top-level or module scopes\")\n                        }\n                        if (!this.parsingDeclareFile && hasFlag(parentModifiers, Modifiers.Ambient)) {\n                            this.reportParseError(\"Duplicate ambient declaration in this context. (Is the enclosing module or class already ambient?)\")\n                        }\n                        modifiers |= Modifiers.Ambient;\n                        this.currentToken = this.scanner.scan();\n                        break;\n                    case TokenID.Class:\n                        if ((allowedElements & AllowedElements.ClassDeclarations) == AllowedElements.None) {\n                            this.reportParseError(\"class not allowed in this context\");\n                            this.currentToken = this.scanner.scan();\n                            ast = new AST(NodeType.Error);\n                            ast.minChar = minChar;\n                            ast.limChar = this.scanner.lastTokenLimChar();\n                        }\n                        else {\n                            ast = this.parseClassDecl(errorRecoverySet, minChar, modifiers);\n                        }\n                        break;\n                    case TokenID.Interface:\n                        if ((allowedElements & AllowedElements.InterfaceDeclarations) == AllowedElements.None) {\n                            this.reportParseError(\"interface not allowed in this context\");\n                            this.currentToken = this.scanner.scan();\n                            ast = new AST(NodeType.Error);\n                            ast.minChar = minChar;\n                            ast.limChar = this.scanner.lastTokenLimChar();\n                        }\n                        else {\n                            ast = this.parseInterfaceDecl(errorRecoverySet, modifiers);\n                        }\n                        break;\n                    case TokenID.Var:\n                        var declAst: AST = this.parseVariableDeclaration(errorRecoverySet | ErrorRecoverySet.StmtStart, modifiers,\n                                                     true, false);\n                        if (declAst.nodeType == NodeType.VarDecl) {\n                            ast = declAst;\n                        }\n                        else {\n                            ast = new Block(<ASTList>declAst, false);\n                        }\n                        needTerminator = true;\n                        break;\n                    case TokenID.Static:\n\n                        if (this.currentClassDecl == null) {\n                            this.reportParseError(\"Statics may only be class members\");\n                        }\n\n                        mayNotBeExported();\n                        modifiers |= Modifiers.Public;\n                        this.currentToken = this.scanner.scan();\n                        if (this.currentToken.tokenId == TokenID.Get) {\n                            this.prevIDTok = this.currentToken;\n                            this.currentToken = this.scanner.scan();\n                            if (codeGenTarget < CodeGenTarget.ES5) {\n                                this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n                            }\n                            if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                                modifiers |= Modifiers.Getter;\n                                this.prevIDTok = null;\n                            }\n                        }\n                        else if (this.currentToken.tokenId == TokenID.Set) {\n                            this.currentToken = this.scanner.scan();\n                            if (codeGenTarget < CodeGenTarget.ES5) {\n                                this.reportParseError(\"Property accessors are only available when targeting ES5 or greater\");\n                            }\n                            if ((this.currentToken.tokenId == TokenID.Identifier) || convertTokToID(this.currentToken, this.strictMode)) {\n                                modifiers |= Modifiers.Setter;\n                            }\n                        }\n                        if (isAmbient()) {\n                            modifiers |= Modifiers.Ambient;\n                        }\n                        fnOrVar = this.parsePropertyDeclaration(errorRecoverySet | ErrorRecoverySet.SColon,\n                                                  modifiers, this.parsingDeclareFile || (modifiers & Modifiers.Ambient) != Modifiers.None, true);\n\n                        var staticsList = this.topStaticsList();\n                        if (staticsList && fnOrVar.nodeType == NodeType.VarDecl) {\n                            staticsList.append(fnOrVar);\n                        }\n\n                        if (fnOrVar.nodeType == NodeType.VarDecl || ((fnOrVar.nodeType == NodeType.FuncDecl) && hasFlag((<FuncDecl>fnOrVar).fncFlags, FncFlags.IsFatArrowFunction))) {\n                            needTerminator = true;\n                        }\n\n                        ast = fnOrVar;\n                        break;\n                    case TokenID.For:\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"syntax error: for statement does not take modifiers\");\n                        }\n                        minChar = this.scanner.startPos;\n                        this.checkNextToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart | ErrorRecoverySet.Var);\n                        this.state = ParseState.ForInit;\n                        forInOk = true;\n                        switch (this.currentToken.tokenId) {\n                            case TokenID.Var:\n                                temp = this.parseVariableDeclaration(errorRecoverySet | ErrorRecoverySet.SColon |\n                                                  ErrorRecoverySet.In, Modifiers.None, false, false);\n                                break;\n                            case TokenID.Semicolon:\n                                temp = null;\n                                this.state = ParseState.ForCondStart;\n                                break;\n                            default:\n                                temp = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon |\n                                               ErrorRecoverySet.In, OperatorPrecedence.None, false,\n                                               TypeContext.NoTypes);\n                                break;\n                        }\n                        this.state = ParseState.ForInitAfterVar;\n                        if (this.currentToken.tokenId == TokenID.In) {\n                            if ((temp == null) || (!forInOk)) {\n                                this.reportParseError(\"malformed for statement\");\n                                if (this.errorRecovery) {\n                                    this.skip(errorRecoverySet | ErrorRecoverySet.StmtStart);\n                                    ast = new AST(NodeType.Empty);\n                                    ast.flags |= ASTFlags.Error;\n                                }\n                            }\n                            else {\n                                this.currentToken = this.scanner.scan();\n                                var forInStmt = new ForInStatement(temp,\n                                                                 this.parseExpr(ErrorRecoverySet.RParen |\n                                                                           errorRecoverySet,\n                                                                           OperatorPrecedence.Comma,\n                                                                           false,\n                                                                           TypeContext.NoTypes));\n\n                                forInStmt.limChar = this.scanner.pos;\n                                forInStmt.statement.minChar = minChar;\n                                forInStmt.statement.limChar = this.scanner.pos;\n                                this.checkCurrentToken(TokenID.CloseParen, ErrorRecoverySet.StmtStart | errorRecoverySet);\n                                this.pushStmt(forInStmt, labelList);\n                                forInStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n                                this.popStmt();\n                                forInStmt.minChar = minChar;\n                                ast = forInStmt;\n                            }\n                        }\n                        else {\n                            var forStmt: ForStatement = new ForStatement(temp);\n                            forStmt.minChar = minChar;\n                            this.checkCurrentToken(TokenID.Semicolon, errorRecoverySet);\n                            if (this.currentToken.tokenId == TokenID.Semicolon) {\n                                forStmt.cond = null;\n                            }\n                            else {\n                                forStmt.cond = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon |\n                                                       ErrorRecoverySet.RParen,\n                                                       OperatorPrecedence.None, true,\n                                                       TypeContext.NoTypes);\n                                if (this.currentToken.tokenId != TokenID.Semicolon) {\n                                    this.skip(errorRecoverySet | ErrorRecoverySet.StmtStart);\n                                    ast = forStmt;\n                                    ast.flags |= ASTFlags.Error;\n                                }\n                            }\n                            this.currentToken = this.scanner.scan();\n                            if (this.currentToken.tokenId == TokenID.CloseParen) {\n                                forStmt.incr = null;\n                            }\n                            else {\n                                forStmt.incr = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon |\n                                                       ErrorRecoverySet.RParen,\n                                                       OperatorPrecedence.None, true,\n                                                       TypeContext.NoTypes);\n                            }\n                            this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.LCurly);\n                            this.pushStmt(forStmt, labelList);\n                            forStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n                            this.popStmt();\n                            forStmt.limChar = forStmt.body.limChar;\n                            ast = forStmt;\n                        }\n                        break;\n                    case TokenID.With: {\n                        if (codeGenTarget < CodeGenTarget.ES5) {\n                            this.reportParseError(\"'with' statements are only available in ES5 codegen mode or better\");\n                        }\n\n                        if (this.strictMode) {\n                            this.reportParseError(\"'with' statements are not available in strict mode\");\n                        }\n\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"'with' statement does not take modifiers\");\n                        }\n                        minChar = this.scanner.startPos;\n                        this.checkNextToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart | ErrorRecoverySet.Var);\n\n                        var expr = this.parseExpr(errorRecoverySet | ErrorRecoverySet.Colon,\n                                                            OperatorPrecedence.None, true,\n                                                            TypeContext.NoTypes);\n                        this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.LCurly);\n\n                        var withStmt = new WithStatement(expr);\n                        withStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n                        withStmt.minChar = minChar;\n                        withStmt.limChar = withStmt.body.limChar;\n                        ast = withStmt;\n                    }\n                        break;\n                    case TokenID.Switch: {\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"'switch' statement does not take modifiers\");\n                        }\n                        this.checkNextToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart);\n\n                        var switchStmt = new SwitchStatement(this.parseExpr(errorRecoverySet |\n                                                                     ErrorRecoverySet.RParen,\n                                                                     OperatorPrecedence.None,\n                                                                     true,\n                                                                     TypeContext.NoTypes));\n                        switchStmt.statement.minChar = minChar;\n                        switchStmt.statement.limChar = this.scanner.pos;\n                        this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.LCurly);\n                        var caseListMinChar = this.scanner.startPos;\n                         this.checkCurrentToken(TokenID.OpenBrace, errorRecoverySet | ErrorRecoverySet.SCase);\n                        switchStmt.defaultCase = null;\n                        switchStmt.caseList = new ASTList();\n                        var caseStmt: CaseStatement = null;\n                        this.pushStmt(switchStmt, labelList);\n                        for (; ;) {\n                            if ((this.currentToken.tokenId == TokenID.Case) ||\n                                (this.currentToken.tokenId == TokenID.Default)) {\n                                var isDefault = (this.currentToken.tokenId == TokenID.Default);\n                                caseStmt = new CaseStatement();\n                                caseStmt.minChar = this.scanner.startPos;\n                                this.currentToken = this.scanner.scan();\n                                if (isDefault) {\n                                    switchStmt.defaultCase = caseStmt;\n                                }\n                                else {\n                                    caseStmt.expr = this.parseExpr(errorRecoverySet | ErrorRecoverySet.Colon,\n                                                            OperatorPrecedence.None, true,\n                                                            TypeContext.NoTypes);\n                                }\n                                this.checkCurrentToken(TokenID.Colon, errorRecoverySet | ErrorRecoverySet.StmtStart);\n                                caseStmt.body = new ASTList();\n                                this.parseStatementList(errorRecoverySet | ErrorRecoverySet.RCurly,\n                                              caseStmt.body, false, true, allowedElements, modifiers);\n                                caseStmt.limChar = caseStmt.body.limChar;\n                                switchStmt.caseList.append(caseStmt);\n                            }\n                            else {\n                                break;\n                            }\n                        }\n                        // end of switch statement\n                        switchStmt.caseList.minChar = caseListMinChar;\n                        switchStmt.caseList.limChar = this.scanner.pos;\n                        switchStmt.limChar = switchStmt.caseList.limChar;\n                        this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n                        this.popStmt();\n                        ast = switchStmt;\n                        break;\n                    }\n                    case TokenID.While: {\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"'while' statement does not take modifiers\");\n                        }\n                        minChar = this.scanner.startPos;\n                        this.checkNextToken(TokenID.OpenParen, ErrorRecoverySet.ExprStart |\n                                  errorRecoverySet);\n                        var whileStmt = new WhileStatement(this.parseExpr(errorRecoverySet |\n                                                                   ErrorRecoverySet.RParen,\n                                                                   OperatorPrecedence.None,\n                                                                   true, TypeContext.NoTypes));\n                        whileStmt.minChar = minChar;\n                        this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet |\n                                  ErrorRecoverySet.StmtStart);\n                        this.pushStmt(whileStmt, labelList);\n                        whileStmt.body = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n                        whileStmt.limChar = whileStmt.body.limChar;\n                        this.popStmt();\n                        ast = whileStmt;\n                        break;\n                    }\n                    case TokenID.Do: {\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"'do' statement does not take modifiers\");\n                        }\n                        minChar = this.scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        var doStmt = new DoWhileStatement();\n                        doStmt.minChar = minChar;\n                        this.pushStmt(doStmt, labelList);\n                        doStmt.body = this.parseStatement(errorRecoverySet | ErrorRecoverySet.While,\n                                                   allowedElements, parentModifiers);\n                        this.popStmt();\n                        doStmt.whileAST = new Identifier(\"while\");\n                        doStmt.whileAST.minChar = this.scanner.startPos;\n                        this.checkCurrentToken(TokenID.While, errorRecoverySet | ErrorRecoverySet.LParen);\n                        doStmt.whileAST.limChar = doStmt.whileAST.minChar + 5;\n                        this.checkCurrentToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart);\n                        doStmt.cond = this.parseExpr(errorRecoverySet | ErrorRecoverySet.RParen,\n                                              OperatorPrecedence.None, true, TypeContext.NoTypes);\n                        doStmt.limChar = this.scanner.pos;\n                        this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet);\n                        ast = doStmt;\n                        // compatibility; more strict would be to require the ';'\n                        if (this.currentToken.tokenId == TokenID.Semicolon) {\n                            this.currentToken = this.scanner.scan();\n                        }\n                        break;\n                    }\n                    case TokenID.If: {\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"if statement does not take modifiers\");\n                        }\n                        minChar = this.scanner.startPos;\n                        this.checkNextToken(TokenID.OpenParen, errorRecoverySet | ErrorRecoverySet.ExprStart);\n                        var ifStmt = new IfStatement(this.parseExpr(errorRecoverySet |\n                                                             ErrorRecoverySet.LParen,\n                                                             OperatorPrecedence.None, true,\n                                                             TypeContext.NoTypes));\n                        ifStmt.minChar = minChar;\n                        ifStmt.statement.minChar = minChar;\n                        ifStmt.statement.limChar = this.scanner.pos;\n                        this.checkCurrentToken(TokenID.CloseParen, errorRecoverySet | ErrorRecoverySet.StmtStart);\n                        this.pushStmt(ifStmt, labelList);\n                        ifStmt.thenBod = this.parseStatement(ErrorRecoverySet.Else | errorRecoverySet,\n                                                      allowedElements, parentModifiers);\n                        ifStmt.limChar = ifStmt.thenBod.limChar;\n                        if (this.currentToken.tokenId == TokenID.Else) {\n                            this.currentToken = this.scanner.scan();\n                            ifStmt.elseBod = this.parseStatement(errorRecoverySet, allowedElements, parentModifiers);\n                            ifStmt.limChar = ifStmt.elseBod.limChar;\n                        }\n                        this.popStmt();\n                        ast = ifStmt;\n                        break;\n                    }\n                    case TokenID.Try: {\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"try statement does not take modifiers\");\n                        }\n                        minChar = this.scanner.startPos;\n                        ast = this.parseTryCatchFinally(errorRecoverySet, parentModifiers, labelList);\n                        break;\n                    }\n                    case TokenID.OpenBrace: {\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"block does not take modifiers\");\n                        }\n                        minChar = this.scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        var block = new Block(new ASTList(), true);\n                        this.pushStmt(block, labelList);\n                        this.parseStatementList(\n                            errorRecoverySet | ErrorRecoverySet.RCurly, block.statements,\n                            /*sourceElements:*/ false, /*noLeadingCase:*/ false, AllowedElements.None, modifiers);\n                        this.popStmt();\n                        block.statements.minChar = minChar;\n                        block.statements.limChar = this.scanner.pos;\n                        block.minChar = block.statements.minChar;\n                        block.limChar = block.statements.limChar;\n                        this.checkCurrentToken(TokenID.CloseBrace, errorRecoverySet);\n                        ast = block;\n                        break;\n                    }\n                    case TokenID.Semicolon:\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"modifier can not appear here\");\n                        }\n                        ast = new AST(NodeType.Empty);\n                        this.currentToken = this.scanner.scan();\n                        break;\n                    case TokenID.Break:\n                    case TokenID.Continue: {\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"modifiers can not appear before jump statement\");\n                        }\n                        var jump =\n                            new Jump((this.currentToken.tokenId == TokenID.Break) ? NodeType.Break : NodeType.Continue);\n                        this.currentToken = this.scanner.scan();\n                        if ((this.currentToken.tokenId == TokenID.Identifier) && (!this.scanner.lastTokenHadNewline())) {\n                            // Labeled break or continue.\n                            jump.target = this.currentToken.getText();\n                            this.currentToken = this.scanner.scan();\n                        }\n                        this.resolveJumpTarget(jump);\n                        ast = jump;\n                        needTerminator = true;\n                        break;\n                    }\n                    case TokenID.Return: {\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"modifiers can not appear before return statement\");\n                        }\n                        if (!this.inFunction) {\n                            this.reportParseError(\"return statement outside of function body\");\n                        }\n                        minChar = this.scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        var retStmt = new ReturnStatement();\n                        retStmt.minChar = minChar;\n                        if ((this.currentToken.tokenId != TokenID.Semicolon) &&\n                            (this.currentToken.tokenId != TokenID.CloseBrace) &&\n                            (!(this.scanner.lastTokenHadNewline()))) {\n                            retStmt.returnExpression = this.parseExpr(errorRecoverySet |\n                                                               ErrorRecoverySet.SColon,\n                                                               OperatorPrecedence.None,\n                                                               true, TypeContext.NoTypes);\n                        }\n                        needTerminator = true;\n                        retStmt.limChar = this.scanner.lastTokenLimChar();\n                        ast = retStmt;\n                        break;\n                    }\n                    case TokenID.Throw:\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"modifiers can not appear before a throw statement\");\n                        }\n                        minChar = this.scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        if ((this.currentToken.tokenId != TokenID.Semicolon) &&\n                            (this.currentToken.tokenId != TokenID.CloseBrace) &&\n                            (!(this.scanner.lastTokenHadNewline()))) {\n                            temp = this.parseExpr(errorRecoverySet | ErrorRecoverySet.SColon,\n                                           OperatorPrecedence.None, true, TypeContext.NoTypes);\n                        }\n                        else {\n                            this.reportParseError(\"throw with no target\");\n                            temp = null;\n                        }\n                        ast = new UnaryExpression(NodeType.Throw, temp);\n                        ast.limChar = this.scanner.lastTokenLimChar();\n                        needTerminator = true;\n                        break;\n                    case TokenID.Enum:\n                        // TODO: check module allowed here\n                        //minChar=scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        ast = this.parseEnumDecl(errorRecoverySet, modifiers);\n                        ast.minChar = minChar;\n                        ast.limChar = this.scanner.lastTokenLimChar();\n                        if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Ambient)) {\n                            (<ModuleDeclaration>ast).modFlags |= ModuleFlags.Ambient;\n                        }\n                        if (this.parsingDeclareFile || this.ambientModule || hasFlag(modifiers, Modifiers.Exported)) {\n                            (<ModuleDeclaration>ast).modFlags |= ModuleFlags.Exported;\n                        }\n                        break;\n                    case TokenID.Debugger:\n                        mayNotBeExported();\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"modifiers can not appear before debugger statement\");\n                        }\n                        \n                        minChar = this.scanner.startPos;\n                        this.currentToken = this.scanner.scan();\n                        var debuggerStmt = new DebuggerStatement();\n                        debuggerStmt.minChar = minChar;\n                        needTerminator = true;\n                        debuggerStmt.limChar = this.scanner.lastTokenLimChar();\n                        ast = debuggerStmt;\n                        break;\n                    default:\n                        if (modifiers != Modifiers.None) {\n                            this.reportParseError(\"modifiers can not appear before an expression statement or label\");\n                        }\n                        minChar = this.scanner.startPos;\n                        var svPos = this.scanner.pos;\n                        temp = this.parseExpr(ErrorRecoverySet.Colon | ErrorRecoverySet.StmtStart |\n                                       errorRecoverySet, OperatorPrecedence.None, true,\n                                       TypeContext.NoTypes);\n                        if (this.scanner.pos == svPos) {\n                            // no progress\n                            this.currentToken = this.scanner.scan();\n                            ast = temp;\n                        }\n                        else if ((this.currentToken.tokenId == TokenID.Colon) && (!this.scanner.lastTokenHadNewline()) &&\n                                        temp && (temp.nodeType == NodeType.Name)) {\n                                            // It's a label\n                            if (labelList == null) {\n                                labelList = new ASTList();\n                            }\n                            labelList.append(new Label(<Identifier>temp));\n                            this.currentToken = this.scanner.scan();\n                        }\n                        else {\n                            // expression statement\n                            ast = temp;\n                            needTerminator = true;\n                        }\n                }\n                if (ast) {\n                    break;\n                }\n            }\n            if (needTerminator) {\n                switch (this.currentToken.tokenId) {\n                    case TokenID.Semicolon:\n                        this.currentToken = this.scanner.scan();\n                        ast.flags |= ASTFlags.ExplicitSemicolon;\n                        break;\n                    case TokenID.EndOfFile:\n                        // Extend any incomplete statements to include EOF token. This makes sure that this node is in the path \n                        // when completion or parameter help is requested.\n                        ast.limChar = this.scanner.pos;\n                        // IntentionaCloseBracethrough\n                    case TokenID.CloseBrace:\n                        ast.flags |= ASTFlags.AutomaticSemicolon;\n                        if (this.style_requireSemi) {\n                            this.reportParseStyleError(\"no automatic semicolon\");\n                        }\n                        break;\n                    default:\n                        if (!this.scanner.lastTokenHadNewline()) {\n                            this.reportParseError(\"Expected ';'\");\n                        }\n                        else {\n                            ast.flags |= ASTFlags.AutomaticSemicolon;\n                            if (this.style_requireSemi) {\n                                this.reportParseStyleError(\"no automatic semicolon\");\n                            }\n                        }\n                        break;\n                }\n            }\n            if (labelList) {\n                ast = new LabeledStatement(labelList, ast);\n            }\n\n            ///////////////////////////////////////////////////////////\n            //TODO: Eventually, we want to remove \"minChar\" and \"limChar\" assignments here,\n            //      as they are sometimes not specific enough for each statement kind.\n            ast.minChar = minChar;\n            // Only update \"limChar\" if it is not better than \"lastTokenLimChar()\"\n            ast.limChar = max(ast.limChar, this.scanner.lastTokenLimChar());\n            //\n            ///////////////////////////////////////////////////////////\n\n            if (preComments) {\n                ast.preComments = preComments;\n            }\n            if (this.ambientModule && (!this.okAmbientModuleMember(ast))) {\n                this.reportParseError(\"statement not permitted within ambient module\");\n            }\n            ast.flags |= ASTFlags.IsStatement;\n            return ast;\n        }\n\n        private okAmbientModuleMember(ast: AST) {\n            var nt = ast.nodeType;\n            return (nt == NodeType.ClassDeclaration) || (nt == NodeType.ImportDeclaration) || (nt == NodeType.InterfaceDeclaration) || (nt == NodeType.ModuleDeclaration) ||\n                (nt == NodeType.Empty) || (nt == NodeType.VarDecl) || \n                ((nt == NodeType.Block) && !(<Block>ast).isStatementBlock) ||\n                ((nt == NodeType.FuncDecl) && ((<FuncDecl>ast).isMethod()));\n        }\n\n        private parseStatementList(errorRecoverySet: ErrorRecoverySet,\n                                   statements: ASTList,\n                                   sourceElms: bool,\n                                   noLeadingCase: bool,\n                                   allowedElements: AllowedElements,\n                                   parentModifiers: Modifiers): void {\n            var directivePrologue = sourceElms;\n            statements.minChar = this.scanner.startPos;\n            var limChar = this.scanner.pos;\n            var innerStmts = (allowedElements & AllowedElements.ModuleDeclarations) == AllowedElements.None;\n            var classNope = (allowedElements & AllowedElements.ClassDeclarations) == AllowedElements.None;\n\n            errorRecoverySet |= ErrorRecoverySet.TypeScriptS | ErrorRecoverySet.RCurly;\n\n            this.state = ParseState.StartStatementList;\n            var oldStrictMode = this.strictMode;\n            this.nestingLevel++;\n            for (; ;) {\n                if ((this.currentToken.tokenId == TokenID.CloseBrace) ||\n                    (noLeadingCase && ((this.currentToken.tokenId == TokenID.Case) || (this.currentToken.tokenId == TokenID.Default))) ||\n                    (innerStmts && (this.currentToken.tokenId == TokenID.Export)) ||\n                    (classNope && (this.currentToken.tokenId == TokenID.Class)) ||\n                    (this.currentToken.tokenId == TokenID.EndOfFile)) {\n                    this.state = ParseState.EndStmtList;\n                    statements.limChar = limChar;\n                    if (statements.members.length == 0) {\n                        statements.preComments = this.parseComments();\n                    }\n                    else {\n                        statements.postComments = this.parseComments();\n                    }\n                    this.strictMode = oldStrictMode;\n                    this.nestingLevel--;\n                    return;\n                }\n\n                var stmt = this.parseStatement(errorRecoverySet &\n                                        (~(ErrorRecoverySet.Else | ErrorRecoverySet.RParen |\n                                           ErrorRecoverySet.Catch | ErrorRecoverySet.Colon)),\n                                        allowedElements, parentModifiers);\n\n\n                if (stmt) {\n                    stmt.postComments = this.combineComments(stmt.postComments, this.parseCommentsForLine(this.scanner.prevLine));\n                    statements.append(stmt);\n                    limChar = stmt.limChar;\n                    if (directivePrologue) {\n                        if (stmt.nodeType == NodeType.QString) {\n                            var qstring = <StringLiteral>stmt;\n                            if (qstring.text == \"\\\"use strict\\\"\") {\n                                statements.flags |= ASTFlags.StrictMode;\n                                this.strictMode = true;\n                            }\n                            else {\n                                directivePrologue = false;\n                            }\n                        }\n                        else {\n                            directivePrologue = false;\n                        }\n                    }\n                }\n            }\n        }\n\n        private fname = \"\";\n\n        public quickParse(sourceText: ISourceText, filename: string, unitIndex: number): QuickParseResult {\n            //TODO: REVIEW: We set this to avoid adding a \"module\" decl in the resulting script (see parse() method)\n            var svGenTarget = TypeScript.moduleGenTarget;\n            try {\n                TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Local;\n                var script = this.parse(sourceText, filename, unitIndex, AllowedElements.QuickParse);\n                return new QuickParseResult(script, this.scanner.lexState);\n            }\n            finally {\n                TypeScript.moduleGenTarget = svGenTarget;\n            }\n        }\n\n        public parse(sourceText: ISourceText, filename: string, unitIndex: number, allowedElements = AllowedElements.Global): Script {\n            // Reset all parser state here.  This allows us to be resilient to reentrancy if an \n            // exception is thrown.\n            this.fname = filename;\n            this.currentUnitIndex = unitIndex;\n\n            this.currentToken = null;\n            this.needTerminator = false;\n            this.inFunction = false;\n            this.inInterfaceDecl = false;\n            this.inFncDecl = false;\n            this.state = ParseState.StartStatementList;\n            this.ambientModule = false;\n            this.ambientClass = false;\n            this.topLevel = true;\n            this.allowImportDeclaration = true;\n            this.prevIDTok = null;\n            this.statementInfoStack = new IStatementInfo[];\n            this.hasTopLevelImportOrExport = false;\n            this.strictMode = false;\n            this.nestingLevel = 0;\n            this.prevExpr = null;\n            this.currentClassDefinition = null;\n            this.parsingClassConstructorDefinition = false;\n            this.parsingDeclareFile = false;\n            this.amdDependencies = [];\n            this.inferPropertiesFromThisAssignment = false;\n            this.requiresExtendsBlock = false;\n\n            this.scanner.resetComments();\n            this.scanner.setErrorHandler((message) =>this.reportParseError(message));\n            this.scanner.setSourceText(sourceText, LexMode.File);\n\n            var leftCurlyCount = this.scanner.leftCurlyCount;\n            var rightCurlyCount = this.scanner.rightCurlyCount;\n\n            var minChar = this.scanner.pos;\n            this.currentToken = this.scanner.scan();\n            this.pushDeclLists();\n            var bod = new ASTList();\n            bod.minChar = minChar;\n\n            this.state = ParseState.StartScript;\n            this.parsingDeclareFile = isDSTRFile(filename) || isDTSFile(filename);\n\n            while (true) {\n                this.parseStatementList(\n                    ErrorRecoverySet.EOF | ErrorRecoverySet.Func,\n                    bod, /*sourceElements:*/ true, /*noLeadingCase:*/ false,\n                    allowedElements, Modifiers.None);\n\n                if (this.currentToken.tokenId === TokenID.EndOfFile) {\n                    break;\n                }\n\n                // Still have remaining tokens in the file.  Report error for this unexpected token,\n                // skip it, and continue trying to parse statements until we're done. \n                var badToken = tokenTable[this.currentToken.tokenId];\n                this.reportParseError(\"Unexpected statement block terminator '\" + badToken.text + \"'\");\n\n                this.currentToken = this.scanner.scan();\n            }\n\n            this.state = ParseState.EndScript;\n\n            bod.limChar = this.scanner.pos;\n\n            var topLevelMod: ModuleDeclaration = null;\n            if (moduleGenTarget != ModuleGenTarget.Local && this.hasTopLevelImportOrExport) {\n                var correctedFileName = switchToForwardSlashes(filename);\n                var id: Identifier = new Identifier(correctedFileName);\n                topLevelMod = new ModuleDeclaration(id, bod, this.topVarList(), this.topScopeList(), null);\n\n                topLevelMod.modFlags |= ModuleFlags.IsDynamic;\n                topLevelMod.modFlags |= ModuleFlags.IsWholeFile;\n                topLevelMod.modFlags |= ModuleFlags.Exported;\n\n                if (this.parsingDeclareFile) {\n                    topLevelMod.modFlags |= ModuleFlags.Ambient;\n                }\n\n                topLevelMod.minChar = minChar;\n                topLevelMod.limChar = this.scanner.pos;\n                topLevelMod.prettyName = getPrettyName(correctedFileName);\n                topLevelMod.containsUnicodeChar = this.scanner.seenUnicodeChar;\n                topLevelMod.containsUnicodeCharInComment = this.scanner.seenUnicodeCharInComment;\n\n                topLevelMod.amdDependencies = this.amdDependencies;\n\n                bod = new ASTList();\n                bod.minChar = topLevelMod.minChar;\n                bod.limChar = topLevelMod.limChar;\n                bod.append(topLevelMod);\n            }\n\n            var script = new Script(this.topVarList(), this.topScopeList());\n            script.bod = bod;\n            this.popDeclLists();\n            script.minChar = minChar;\n            script.limChar = this.scanner.pos;\n            script.locationInfo = new LocationInfo(filename, this.scanner.lineMap, unitIndex);\n            script.leftCurlyCount = this.scanner.leftCurlyCount - leftCurlyCount;\n            script.rightCurlyCount = this.scanner.rightCurlyCount - rightCurlyCount;\n            script.isDeclareFile = this.parsingDeclareFile;\n            script.topLevelMod = topLevelMod;\n            script.containsUnicodeChar = this.scanner.seenUnicodeChar;\n            script.containsUnicodeCharInComment = this.scanner.seenUnicodeCharInComment;\n            script.requiresExtendsBlock = this.requiresExtendsBlock;\n            return script;\n        }\n    }\n\n    export function quickParse(logger: TypeScript.ILogger, scopeStartAST: AST, sourceText: ISourceText, minChar: number, limChar: number,\n        errorCapture: (minChar: number, charLen: number, message: string, unitIndex: number) => void ): QuickParseResult {\n\n        var fragment = sourceText.getText(minChar, limChar);\n        logger.log(\"Quick parse range (\" + minChar + \",\" + limChar + \"): \\\"\" + TypeScript.stringToLiteral(fragment, 100) + \"\\\"\");\n\n        var quickParser = new Parser();\n        quickParser.setErrorRecovery(null);\n        quickParser.errorCallback = errorCapture;\n\n        // REVIEW: use enclosing scope to determine this\n        // REVIEW: Why even use class here?\n        var quickClassDecl = new ClassDeclaration(null, null, null, null);\n        quickParser.currentClassDecl = quickClassDecl;\n\n        var result = quickParser.quickParse(new StringSourceText(fragment), \"\", 0);\n        return result;\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    // We need to catch both left and right quotes\n    // (depending on your editor's font, this may not be clear...)    \n    export function stripQuotes(str: string) {\n        return str.replace(\"\\\"\", \"\").replace(\"'\", \"\").replace(\"'\", \"\").replace(\"\\\"\", \"\")\n    }\n\n    export function isQuoted(str: string) {\n        return str.indexOf(\"\\\"\") != -1 || str.indexOf(\"'\") != -1 || str.indexOf(\"'\") != -1 || str.indexOf(\"\\\"\") != -1;\n    }\n\n    export function quoteStr(str: string) {\n        return \"\\\"\" + str + \"\\\"\";\n    }\n\n    export function swapQuotes(str: string) {\n\n        if (str.indexOf(\"\\\"\") != -1) {\n            str = str.replace(\"\\\"\", \"'\");\n            str = str.replace(\"\\\"\", \"'\");\n        }\n        else {\n            str = str.replace(\"'\", \"\\\"\");\n            str = str.replace(\"'\", \"\\\"\");\n        }\n\n        return str;\n    }\n\n    export function switchToForwardSlashes(path: string) {\n        return path.replace(/\\\\/g, \"/\");\n    }\n\n    export function trimModName(modName: string) {\n        // in case's it's a declare file...\n        if (modName.length > 6 && modName.substring(modName.length - 6, modName.length) == \".d.str\") {\n            return modName.substring(0, modName.length - 6);\n        }\n        if (modName.length > 4 && modName.substring(modName.length - 4, modName.length) == \".str\") {\n            return modName.substring(0, modName.length - 4);\n        }\n        if (modName.length > 5 && modName.substring(modName.length - 5, modName.length) == \".d.ts\") {\n            return modName.substring(0, modName.length - 5);\n        }\n        if (modName.length > 3 && modName.substring(modName.length - 3, modName.length) == \".ts\") {\n            return modName.substring(0, modName.length - 3);\n        }\n        // in case's it's a .js file\n        if (modName.length > 3 && modName.substring(modName.length - 3, modName.length) == \".js\") {\n            return modName.substring(0, modName.length - 3);\n        }\n\n        return modName;\n    }\n\n    export function getDeclareFilePath(fname: string) {\n        return isSTRFile(fname) ? changePathToDSTR(fname) : isTSFile(fname) ? changePathToDTS(fname) : changePathToDTS(fname);\n    }\n\n    function isFileOfExtension(fname: string, ext: string) {\n        var invariantFname = fname.toLocaleUpperCase();\n        var invariantExt = ext.toLocaleUpperCase();\n        var extLength = invariantExt.length;\n        return invariantFname.length > extLength && invariantFname.substring(invariantFname.length - extLength, invariantFname.length) == invariantExt;\n    }\n\n    export function isJSFile(fname: string) {\n        return isFileOfExtension(fname, \".js\");\n    }\n\n    export function isSTRFile(fname: string) {\n        return isFileOfExtension(fname, \".str\");\n    }\n\n    export function isTSFile(fname: string) {\n        return isFileOfExtension(fname, \".ts\");\n    }\n\n    export function isDSTRFile(fname: string) {\n        return isFileOfExtension(fname, \".d.str\");\n    }\n\n    export function isDTSFile(fname: string) {\n        return isFileOfExtension(fname, \".d.ts\");\n    }\n\n    export function getPrettyName(modPath: string, quote?=true, treatAsFileName?=false) { \n        var modName = treatAsFileName ? switchToForwardSlashes(modPath) : trimModName(stripQuotes(modPath));\n        var components = this.getPathComponents(modName);\n        return components.length ? (quote ? quoteStr(components[components.length - 1]) : components[components.length - 1]) : modPath;\n    }\n\n    export function getPathComponents(path: string) {\n        return path.split(\"/\");\n    }\n\n    export function getRelativePathToFixedPath(fixedModFilePath: string, absoluteModPath: string) {\n        absoluteModPath = switchToForwardSlashes(absoluteModPath);\n\n        var modComponents = this.getPathComponents(absoluteModPath);\n        var fixedModComponents = this.getPathComponents(fixedModFilePath);\n\n        // Find the component that differs\n        var joinStartIndex = 0;\n        for (; joinStartIndex < modComponents.length && joinStartIndex < fixedModComponents.length ; joinStartIndex++) {\n            if (fixedModComponents[joinStartIndex] != modComponents[joinStartIndex]) {\n                break;\n            }\n        }\n\n        // Get the relative path\n        if (joinStartIndex != 0) {\n            var relativePath = \"\";\n            var relativePathComponents = modComponents.slice(joinStartIndex, modComponents.length);\n            for (; joinStartIndex < fixedModComponents.length; joinStartIndex++) {\n                if (fixedModComponents[joinStartIndex] != \"\") {\n                    relativePath = relativePath + \"../\";\n                }\n            }\n\n            return relativePath + relativePathComponents.join(\"/\");\n        }\n\n        return absoluteModPath;\n    }\n\n    export function quoteBaseName(modPath: string) {\n        var modName = trimModName(stripQuotes(modPath));\n        var path = getRootFilePath(modName);\n        if (path == \"\") {\n            return modPath;\n        }\n        else {\n            var components = modName.split(path);\n            var fileIndex = components.length > 1 ? 1 : 0;\n            return quoteStr(components[fileIndex]);\n        }\n    }\n\n    export function changePathToSTR(modPath: string) {\n        return trimModName(stripQuotes(modPath)) + \".str\";\n    }\n\n    export function changePathToDSTR(modPath: string) {\n        return trimModName(stripQuotes(modPath)) + \".d.str\";\n    }\n\n    export function changePathToTS(modPath: string) {\n        return trimModName(stripQuotes(modPath)) + \".ts\";\n    }\n\n    export function changePathToDTS(modPath: string) {\n        return trimModName(stripQuotes(modPath)) + \".d.ts\";\n    }\n\n    export function isRelative(path: string) {\n        return path.charAt(0) == \".\";\n    }\n    export function isRooted(path: string) {\n        return path.charAt(0) == \"\\\\\" || path.charAt(0) == \"/\" || (path.indexOf(\":\\\\\") != -1) || (path.indexOf(\":/\") != -1);\n    }\n\n    export function getRootFilePath(outFname: string) {\n        if (outFname == \"\") {\n            return outFname;\n        }\n        else {\n            var isPath = outFname.indexOf(\"/\") != -1;\n            return isPath ? filePath(outFname) : \"\";\n        }\n    }\n\n    export function filePathComponents(fullPath: string) {\n        fullPath = switchToForwardSlashes(fullPath);\n        var components = getPathComponents(fullPath);\n        return components.slice(0, components.length - 1);\n    }\n\n    export function filePath(fullPath: string) {\n        var path = filePathComponents(fullPath);\n        return path.join(\"/\") + \"/\";\n    }\n\n    export function normalizeURL(url: string): string {\n        var hostDomainAndPortRegex = /^(https?:\\/\\/[\\-\\w\\.]+(:\\d+)?\\/)(.*)$/i;\n        var matches = hostDomainAndPortRegex.exec(url);\n        if (matches) {\n            var hostDomainAndPort = matches[1];\n            var actualPath = matches[3];\n            return hostDomainAndPort + normalizePath(actualPath);\n        }\n        return normalizePath(url);\n    }\n\n    export var pathNormalizeRegExp = /\\//g;\n\n    export function normalizePath(path: string): string {\n        path = switchToForwardSlashes(path);\n        var startedWithSep = path.charAt(0) === \"/\";\n        var parts = this.getPathComponents(path);\n        for (var i = 0; i < parts.length; i++) {\n            if (parts[i] === \".\" || parts[i] === \"\") {\n                parts.splice(i, 1);\n                i--;\n            }\n            if (i > 0 && parts[i] === \"..\" && parts[i - 1] !== \"..\") {\n                parts.splice(i - 1, 2);\n                i -= 2;\n            }\n        }\n        return (startedWithSep ? \"/\" : \"\") + parts.join(\"/\");\n    }\n\n    export function normalizeImportPath(path: string): string {\n        return normalizePath(path);\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    /// Compiler settings\n\n    export class StyleSettings {\n        // bitwise operations not permitted\n        public bitwise = false;  \n        // disallow non-block statements as bodies of compound statements\n        public blockInCompoundStmt = false;\n        // disallow == and !=\n        public eqeqeq = false;\n        // require body of for in loop to start with a filter\n        public forin = false;\n        // empty blocks permitted\n        public emptyBlocks = true;\n        // require result of new expression to be used (no new just for side-effects)\n        public newMustBeUsed = false;\n        // require semicolons to terminate statements\n        public requireSemi = false;\n        // no top-level assignment in conditionals if (a=b) { ...\n        public assignmentInCond = false;\n        // no == null or != null\n        public eqnull = false;\n        // permit eval\n        public evalOK = true;\n        // permit var use if decl in inner scope as in if (c) { var v=10; } v=11;\n        public innerScopeDeclEscape = true;\n        // permit functions in loops\n        public funcInLoop = true;\n        // permit re-declaration of local variable \n        public reDeclareLocal = true;\n        // permit obj['x'] in addition to obj.x\n        public literalSubscript = true;\n        // flag implicit 'any'\n        public implicitAny = false;\n\n        public setOption(opt: string, val: bool): bool {\n            var optExists = this[opt];\n            if (optExists !== undefined) {\n                this[opt] = val;\n                return true;\n            }\n            else {\n                return false;\n            }\n        }\n        \n        public parseOptions(str: string) {\n            var opts=str.split(\";\");\n            for (var i = 0, len = opts.length; i < len; i++) {\n                var opt = opts[i];\n                var val = true;\n                var colonIndex=opt.lastIndexOf(\":\");\n                if (colonIndex >= 0) {\n                    var valStr = opt.substring(colonIndex+1);\n                    opt = opt.substring(0, colonIndex);\n                    if (valStr == \"off\") {\n                        val = false;\n                    }\n                }\n                if (!this.setOption(opt, val)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n    }\n    \n    export class CompilationSettings {\n        public styleSettings = new StyleSettings();\n        public propagateConstants = false;\n        public minWhitespace = false;\n        public parseOnly = false;\n        public errorRecovery = false;\n        public emitComments = false;\n        public watch = false;\n        public exec = false;\n        public resolve = true;\n        public controlFlow = false;\n        public printControlFlow = false;\n        public controlFlowUseDef = false;\n        public errorOnWith = true;\n        public preprocess = true;\n        public canCallDefinitionSignature = false;\n\n        public inferPropertiesFromThisAssignment = false;\n        public useDefaultLib = true;\n\n        public codeGenTarget = CodeGenTarget.ES3;\n        public moduleGenTarget = ModuleGenTarget.Synchronous;\n        // --out option passed. \n        // Default is the \"\" which leads to multiple files generated next to the.ts files\n        public outputOption: string = \"\";\n        public mapSourceFiles = false;\n        public generateDeclarationFiles = false;\n\n        public useCaseSensitiveFileResolution = false;\n\n        public setStyleOptions(str: string) {\n            this.styleSettings.parseOptions(str);\n        }\n    }\n\n    ///\n    /// Preprocessing\n    ///\n    export interface IPreProcessedFileInfo {\n        settings: CompilationSettings;\n        referencedFiles: IFileReference[];\n        importedFiles: IFileReference[];\n        isLibFile: bool;\n    }\n\n    function getFileReferenceFromReferencePath(comment: string): IFileReference {\n        var referencesRegEx = /^(\\/\\/\\/\\s*<reference\\s+path=)('|\")(.+?)\\2\\s*(static=('|\")(.+?)\\2\\s*)*\\/>/gim;\n        var match = referencesRegEx.exec(comment);\n\n        if (match) {\n            var path: string = normalizePath(match[3]);\n            var adjustedPath = normalizePath(path);\n    \n            var isResident = match.length >= 7 && match[6] == \"true\";\n            if (isResident) {\n                CompilerDiagnostics.debugPrint(path + \" is resident\");\n            }\n            return { minChar: 0, limChar: 0, path: switchToForwardSlashes(adjustedPath), isResident: isResident };\n        }\n        else {\n            return null;\n        }\n    }\n\n    // used in the parser, but kept here in case we want to reintegrate it with preprocessing\n    export function getAdditionalDependencyPath(comment: string): string {\n        var amdDependencyRegEx = /^(\\/\\/\\/\\s*<amd-dependency\\s+path=)('|\")(.+?)\\2\\s*(static=('|\")(.+?)\\2\\s*)*\\/>/gim;\n        var match = amdDependencyRegEx.exec(comment);\n\n        if (match) {\n            var path: string = match[3];\n            return path;\n        }\n        else {\n            return null;\n        }\n    }\n\n    export function getImplicitImport(comment: string): bool {\n        var implicitImportRegEx = /^(\\/\\/\\/\\s*<implicit-import\\s*)*\\/>/gim;\n        var match = implicitImportRegEx.exec(comment);\n\n        if (match) {\n            return true;\n        }\n        \n        return false;\n    }\n\n    export function getStyleSettings(comment: string, styleSettings: StyleSettings) {\n        var styleRegEx = /^(\\/\\/\\/\\s*<style\\s+)(([a-zA-Z])+=('|\").+('|\"))\\s*\\/>/gim;\n\n        var settings = styleRegEx.exec(comment);\n\n        if (settings) {\n            var settingsRegEx = /^([a-zA-Z]+=['\"]on['|\"])/gim;\n            settings = settingsRegEx.exec(settings[2]);\n                \n            if (settings) {\n                for (var i = 0; i < settings.length; i++) {\n                    var setting = (<string>settings[i]).split(\"=\");\n                    var on = \"\\\"on\\\"\";\n\n                    switch (setting[0]) {\n                        case \"blockInCompoundStmt\": styleSettings.blockInCompoundStmt = setting[1] == on; break;\n                        case \"eqeqeq\": styleSettings.eqeqeq = setting[1] == on; break;\n                        case \"forin\": styleSettings.forin = setting[1] == on; break;\n                        case \"emptyBlocks\": styleSettings.emptyBlocks = setting[1] == on; break;\n                        case \"newMustBeUsed\": styleSettings.newMustBeUsed = setting[1] == on; break;\n                        case \"requireSemi\": styleSettings.requireSemi = setting[1] == on; break;\n                        case \"assignmentInCond\": styleSettings.assignmentInCond = setting[1] == on; break;\n                        case \"eqnull\": styleSettings.eqnull = setting[1] == on; break;\n                        case \"evalOK\": styleSettings.evalOK = setting[1] == on; break;\n                        case \"innerScopeDeclEscape\": styleSettings.innerScopeDeclEscape = setting[1] == on; break;\n                        case \"funcInLoop\": styleSettings.funcInLoop = setting[1] == on; break;\n                        case \"reDeclareLocal\": styleSettings.reDeclareLocal = setting[1] == on; break;\n                        case \"literalSubscript\": styleSettings.literalSubscript = setting[1] == on; break;\n                        case \"implicitAny\": styleSettings.implicitAny = setting[1] == on; break;                               \n                    }\n                }\n            }\n        }\n    }\n\n    export function getReferencedFiles(sourceText: ISourceText): IFileReference[] {\n        var preProcessInfo = preProcessFile(sourceText, null, false);\n        return preProcessInfo.referencedFiles;\n    }\n\n    export function preProcessFile(sourceText: ISourceText, options=new CompilationSettings(), readImportFiles? = true): IPreProcessedFileInfo {\n        var scanner = new Scanner();\n        scanner.resetComments();\n        scanner.setSourceText(sourceText, LexMode.File);\n\n        var tok: Token = scanner.scan();\n        var comments: CommentToken[] = [];\n        var comment: CommentToken = null;\n        var leftCurlies: Token[] = [];\n\n        var settings: CompilationSettings = options;\n        var referencedFiles: IFileReference[] = [];\n        var importedFiles: IFileReference[] = [];\n        var isLibFile: bool = false;\n\n        // only search out dynamic mods\n        // if you find a dynamic mod, ignore every other mod inside, until you balance rcurlies\n\n        while (tok.tokenId != TokenID.EndOfFile) {\n\n            if (readImportFiles && tok.tokenId == TokenID.Import) {\n\n                tok = scanner.scan();\n\n                if (tok.tokenId == TokenID.Identifier || convertTokToID(tok, false)) {\n                    tok = scanner.scan();\n\n                    if (tok.tokenId == TokenID.Equals) {\n                        tok = scanner.scan();\n\n                        if (tok.tokenId == TokenID.Module) {\n                            tok = scanner.scan();\n                            if (tok.tokenId == TokenID.OpenParen) {\n                                tok = scanner.scan();\n\n                                // import foo = module(\"foo\")\n                                if (tok.tokenId == TokenID.StringLiteral) {\n                                    var ref = { minChar: scanner.startPos, limChar: scanner.pos, path: stripQuotes(switchToForwardSlashes(tok.getText())), isResident: false };\n                                    importedFiles.push(ref);\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (tok.tokenId == TokenID.OpenBrace) {\n                leftCurlies.push(tok);\n            }\n\n            if (tok.tokenId == TokenID.CloseBrace) {\n                leftCurlies.pop();\n            }\n\n            tok = scanner.scan();\n        }\n\n        // deal with comment references, amd dependencies and style settings\n        // REVIEW: We could potentially do this inline with the above, if we\n        // set Scanner::scanComments to 'true'\n        comments = scanner.getComments();\n\n        for (var iComment = 0; iComment < comments.length; iComment++) {\n            comment = comments[iComment];\n            \n            if (!comment.isBlock) {\n                var referencedCode = getFileReferenceFromReferencePath(comment.getText());\n                if (referencedCode) {\n                    referencedCode.minChar = comment.startPos;\n                    referencedCode.limChar = referencedCode.minChar + comment.value.length;\n                    referencedFiles.push(referencedCode);\n                }\n\n                if (settings) {\n                    getStyleSettings(comment.getText(), settings.styleSettings);\n\n                    // is it a lib file?\n                    var isNoLibRegex = /^(\\/\\/\\/\\s*<reference\\s+no-default-lib=)('|\")(.+?)\\2\\s*\\/>/gim;\n                    var isNoLibMatch: any = isNoLibRegex.exec(comment.getText());\n                    if (isNoLibMatch) {\n                        isLibFile = (isNoLibMatch[3] == \"true\");\n                    }\n                }\n            }\n        }\n\n        return { settings: settings, referencedFiles: referencedFiles, importedFiles: importedFiles, isLibFile: isLibFile };\n    }\n\n} // Tools//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    // TODO: refactor indent logic for use in emit\n    export class PrintContext {\n        public builder = \"\";\n        public indent1 = \"  \";\n        public indentStrings: string[] = [];\n        public indentAmt = 0;\n\n        constructor (public outfile: ITextWriter, public parser: Parser) {\n        }\n\n        public increaseIndent() {\n            this.indentAmt++;\n        }\n\n        public decreaseIndent() {\n            this.indentAmt--;\n        }\n\n        public startLine() {\n            if (this.builder.length > 0) {\n                CompilerDiagnostics.Alert(this.builder);\n            }\n            var indentString = this.indentStrings[this.indentAmt];\n            if (indentString === undefined) {\n                indentString = \"\";\n                for (var i = 0; i < this.indentAmt; i++) {\n                    indentString += this.indent1;\n                }\n                this.indentStrings[this.indentAmt] = indentString;\n            }\n            this.builder += indentString;\n        }\n\n        public write(s) {\n            this.builder += s;\n        }\n\n        public writeLine(s) {\n            this.builder += s;\n            this.outfile.WriteLine(this.builder);\n            this.builder = \"\";\n        }\n\n    }\n\n    export function prePrintAST(ast: AST, parent: AST, walker: IAstWalker) {\n        var pc: PrintContext = <PrintContext>walker.state;\n\n        ast.print(pc);\n        pc.increaseIndent();\n        return ast;\n    }\n\n\n    export function postPrintAST(ast: AST, parent: AST, walker: IAstWalker) {\n        var pc: PrintContext = <PrintContext>walker.state;\n        pc.decreaseIndent();\n        return ast;\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export interface IResolvedFile {\n        content: string;\n        path: string;\n    }\n\n    /// This class acts as a convenience class to store path and content information in places\n    /// where we need an ISourceText object\n    export class SourceUnit implements ISourceText, IResolvedFile {\n        public referencedFiles: IFileReference[] = null;\n        constructor(public path: string, public content: string) {\n        }\n\n        public getText(start: number, end: number): string { return this.content.substring(start, end); }\n        public getLength(): number { return this.content.length; }\n    }\n\n    export interface IFileReference {\n        minChar: number;\n        limChar: number;\n        path: string;\n        isResident: bool;\n    }\n\n    /// Limited API for file system manipulation\n    export interface IFileSystemObject {\n        resolvePath(path: string): string;\n        readFile(path: string): string;\n        findFile(rootPath: string, partialFilePath: string): IResolvedFile;\n        dirName(path: string): string;\n    }\n\n    export class CompilationEnvironment {\n        constructor (public compilationSettings: CompilationSettings, public ioHost: IFileSystemObject) { }\n        public residentCode: SourceUnit[] = [];\n        public code: SourceUnit[] = [];\n    }\n\n    export interface IResolutionDispatcher {\n        postResolutionError(errorFile: string, errorMessage: string, errorObject: any): void;\n        postResolution(path: string, source: ISourceText): void;\n    }\n\n    export interface ICodeResolver {\n        resolveCode(referencePath: string, rootPath: string, performSearch:bool, state: IResolutionDispatcher): void;\n    }\n\n    export interface IResolverHost {\n        resolveCompilationEnvironment(preEnvironment: CompilationEnvironment, resolver: ICodeResolver, traceDependencies: bool): CompilationEnvironment;\n    }\n\n    export class CodeResolver implements TypeScript.ICodeResolver {\n        public visited: any = { };\n\n        constructor (public environment: CompilationEnvironment) { }\n\n        public resolveCode(referencePath: string, parentPath: string, performSearch: bool, resolutionDispatcher: TypeScript.IResolutionDispatcher): void {\n            \n            var resolvedFile: IResolvedFile = { content: null, path: referencePath };\n            \n            var ioHost = this.environment.ioHost;\n            \n            // If the path is relative, normalize it, based on the root\n            var isRelativePath = TypeScript.isRelative(referencePath);\n            var isRootedPath = isRelativePath ? false : isRooted(referencePath);\n            var normalizedPath: string = \n                isRelativePath ? ioHost.resolvePath(parentPath + \"/\" + referencePath) : \n                // we only follow the second clause if the path is a non-rooted triple-slash reference path\n                (isRootedPath || !parentPath || performSearch ? referencePath : parentPath + \"/\" + referencePath);\n\n            // We use +=.ts to make sure we don't accidentally pick up \".js\" files or the like\n            if (!isSTRFile(normalizedPath) && !isTSFile(normalizedPath)) {\n                normalizedPath += \".ts\";  //changePathToSTR(normalizedPath);\n            }\n\n            normalizedPath = switchToForwardSlashes(stripQuotes(normalizedPath));\n            var absoluteModuleID = this.environment.compilationSettings.useCaseSensitiveFileResolution ? normalizedPath : normalizedPath.toLocaleUpperCase();\n            // read the file contents - if it doesn't exist, trigger a resolution error\n            if (!this.visited[absoluteModuleID]) {\n\n                // if the path is relative, or came from a reference tag, we don't perform a search\n                if (isRelativePath || isRootedPath || !performSearch) {\n                    try {\n                        CompilerDiagnostics.debugPrint(\"   Reading code from \" + normalizedPath);\n                            \n                        // Look for the .ts file first - if not present, use the .ts, the .d.str and the .d.ts\n                        try {\n                            resolvedFile.content = ioHost.readFile(normalizedPath);\n                        }\n                        catch (err) {\n                            try {\n                                if (isSTRFile(normalizedPath)) {\n                                    normalizedPath = changePathToTS(normalizedPath);\n                                }\n                                else if (isTSFile(normalizedPath)) {\n                                    normalizedPath = changePathToSTR(normalizedPath);\n                                }\n                                CompilerDiagnostics.debugPrint(\"   Reading code from \" + normalizedPath);\n                                resolvedFile.content = ioHost.readFile(normalizedPath);\n                            }\n                            catch (err) {\n                                normalizedPath = changePathToDSTR(normalizedPath);\n                                CompilerDiagnostics.debugPrint(\"   Reading code from \" + normalizedPath);\n\n                                try {\n                                    resolvedFile.content = ioHost.readFile(normalizedPath);\n                                }\n                                catch (err) {\n                                    normalizedPath = changePathToDTS(normalizedPath);\n                                    CompilerDiagnostics.debugPrint(\"   Reading code from \" + normalizedPath);\n                                    resolvedFile.content = ioHost.readFile(normalizedPath);\n                                }\n                            }\n                        }\n                        CompilerDiagnostics.debugPrint(\"   Found code at \" + normalizedPath);\n\n                        resolvedFile.path = normalizedPath;\n                        this.visited[absoluteModuleID] = true;\n                    }\n                    catch (err) {\n                        CompilerDiagnostics.debugPrint(\"   Did not find code for \" + referencePath);\n                    }\n                }\n                else {\n\n                    // if the path is non-relative, we should attempt to search on the relative path\n                    resolvedFile = ioHost.findFile(parentPath, normalizedPath);\n\n                    if (!resolvedFile) {\n                        if (isSTRFile(normalizedPath)) {\n                            normalizedPath = changePathToTS(normalizedPath);\n                        }\n                        else if (isTSFile(normalizedPath)) {\n                            normalizedPath = changePathToSTR(normalizedPath);\n                        }\n                        resolvedFile = ioHost.findFile(parentPath, normalizedPath);\n                    }\n\n                    if (!resolvedFile) {\n                        normalizedPath = changePathToDTS(normalizedPath);\n                        resolvedFile = ioHost.findFile(parentPath, normalizedPath);\n                        if (!resolvedFile) {\n                            normalizedPath = changePathToDSTR(normalizedPath);\n                            resolvedFile = ioHost.findFile(parentPath, normalizedPath);\n                        }\n                    }\n\n                    if (resolvedFile) {\n                        resolvedFile.path = switchToForwardSlashes(TypeScript.stripQuotes(resolvedFile.path));\n                        CompilerDiagnostics.debugPrint(referencePath + \" resolved to: \" + resolvedFile.path);\n                        resolvedFile.content = resolvedFile.content;\n                        this.visited[absoluteModuleID] = true;\n                    }\n                    else {\n                        CompilerDiagnostics.debugPrint(\"Could not find \" + referencePath);\n                    }\n                }\n\n                if (resolvedFile && resolvedFile.content != null) {\n                    // preprocess the file, to gather dependencies\n                    var rootDir = ioHost.dirName(resolvedFile.path);\n                    var sourceUnit = new SourceUnit(resolvedFile.path, resolvedFile.content);\n                    var preProcessedFileInfo = preProcessFile(sourceUnit, this.environment.compilationSettings);\n                    sourceUnit.referencedFiles = preProcessedFileInfo.referencedFiles;\n\n                    // resolve explicit references\n                    for (var i = 0; i < preProcessedFileInfo.referencedFiles.length; i++) {\n                        var referencedFile = preProcessedFileInfo.referencedFiles[i];\n                        var normalizedPath = isRooted(referencedFile.path) ? referencedFile.path : rootDir + \"/\" + referencedFile.path;\n                        normalizedPath = ioHost.resolvePath(normalizedPath);\n                        if (referencePath == normalizedPath) {\n                            resolutionDispatcher.postResolutionError(normalizedPath, \"File contains reference to itself\", null);\n                            continue;\n                        }\n                        this.resolveCode(referencedFile.path, rootDir, false, resolutionDispatcher);\n                    }\n                    \n                    // resolve imports\n                    for (var i = 0; i < preProcessedFileInfo.importedFiles.length; i++) {\n                        this.resolveCode(preProcessedFileInfo.importedFiles[i].path, rootDir, true, resolutionDispatcher);\n                    }\n\n                    // add the file to the appropriate code list\n                    resolutionDispatcher.postResolution(sourceUnit.path, sourceUnit);\n                }\n            }\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export var LexEOF = (-1);\n\n    export var LexCodeNWL = 0x0A;\n    export var LexCodeRET = 0x0D;\n    export var LexCodeLS =  0x2028;\n    export var LexCodePS =  0x2029;\n    export var LexCodeTAB = 0x09;\n    export var LexCodeVTAB = 0x0B;\n    export var LexCode_e = 'e'.charCodeAt(0);\n    export var LexCode_E = 'E'.charCodeAt(0);\n    export var LexCode_x = 'x'.charCodeAt(0);\n    export var LexCode_X = 'X'.charCodeAt(0);\n    export var LexCode_a = 'a'.charCodeAt(0);\n    export var LexCode_A = 'A'.charCodeAt(0);\n    export var LexCode_f = 'f'.charCodeAt(0);\n    export var LexCode_F = 'F'.charCodeAt(0);\n\n    export var LexCode_g = 'g'.charCodeAt(0);\n    export var LexCode_m = 'm'.charCodeAt(0);\n    export var LexCode_i = 'i'.charCodeAt(0);\n\n    export var LexCode_u = 'u'.charCodeAt(0);\n\n    export var LexCode_0 = '0'.charCodeAt(0);\n    export var LexCode_9 = '9'.charCodeAt(0);\n    export var LexCode_8 = '8'.charCodeAt(0);\n    export var LexCode_7 = '7'.charCodeAt(0);\n\n    export var LexCodeBSL = '\\\\'.charCodeAt(0);\n    export var LexCodeSHP = '#'.charCodeAt(0);\n    export var LexCodeBNG = '!'.charCodeAt(0);\n    export var LexCodeQUO = '\"'.charCodeAt(0);\n    export var LexCodeAPO = '\\''.charCodeAt(0);\n    export var LexCodePCT = '%'.charCodeAt(0);\n    export var LexCodeAMP = '&'.charCodeAt(0);\n    export var LexCodeLPR = '('.charCodeAt(0);\n    export var LexCodeRPR = ')'.charCodeAt(0);\n    export var LexCodePLS = '+'.charCodeAt(0);\n    export var LexCodeMIN = '-'.charCodeAt(0);\n    export var LexCodeMUL = '*'.charCodeAt(0);\n    export var LexCodeSLH = '/'.charCodeAt(0);\n    export var LexCodeXOR = '^'.charCodeAt(0);\n    export var LexCodeCMA = ','.charCodeAt(0);\n    export var LexCodeDOT = '.'.charCodeAt(0);\n    export var LexCodeLT = '<'.charCodeAt(0);\n    export var LexCodeEQ = '='.charCodeAt(0);\n    export var LexCodeGT = '>'.charCodeAt(0);\n    export var LexCodeQUE = '?'.charCodeAt(0);\n    export var LexCodeLBR = '['.charCodeAt(0);\n    export var LexCodeRBR = ']'.charCodeAt(0);\n    export var LexCodeUSC = '_'.charCodeAt(0);\n    export var LexCodeLC = '{'.charCodeAt(0);\n    export var LexCodeRC = '}'.charCodeAt(0);\n    export var LexCodeBAR = '|'.charCodeAt(0);\n    export var LexCodeTIL = '~'.charCodeAt(0);\n    export var LexCodeCOL = ':'.charCodeAt(0);\n    export var LexCodeSMC = ';'.charCodeAt(0);\n    export var LexCodeUnderscore = '_'.charCodeAt(0);\n    export var LexCodeDollar = '$'.charCodeAt(0);\n    export var LexCodeSpace = 32;\n    export var LexCodeAtSign = '@'.charCodeAt(0);\n    export var LexCodeASCIIChars = 128;\n\n    export var LexKeywordTable = undefined;\n    // TODO: use new Token[128];\n    var autoToken: Token[] = new Array(LexCodeASCIIChars);\n    var lexIdStartTable: bool[] = new Array(LexCodeASCIIChars);\n\n    // Unicode range maps\n    // REVIEW: These range maps have been extracted from the Unicode specifications, they might be missing values, and/or include \n    //         incorrect ranges. but for the most they seem to be correct. A more accurate and thorough review is needed.\n\n    /*\n        As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers\n        IdentifierStart :: Can contain Unicode 3.0.0  categories Uppercase letter (Lu), Lowercase letter (Ll), Titlecase letter (Lt), Modifier letter (Lm), Other letter (Lo), or Letter number (Nl).\n        IdentifierPart :: Can contain IdentifierStart + Unicode 3.0.0  categories Non-spacing mark (Mn), Combining spacing mark (Mc), Decimal number (Nd), or Connector punctuation (Pc).\n                    \n        Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at:\n        http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt\n    */\n    var unicodeES3IdStart = [\n		170, 170,181, 181,186, 186,192, 214,216, 246,248, 543,546, 563,592, 685,688, 696,699, 705,720, 721,736, 740,750, 750,890, 890,902, 902,904, 906,908, 908,910, 929,931, 974,976, 983,986, 1011,1024, 1153,1164, 1220,1223, 1224,1227, 1228,1232, 1269,1272, 1273,1329, 1366,1369, 1369,1377, 1415,1488, 1514,\n		1520, 1522,1569, 1594,1600, 1610,1649, 1747,1749, 1749,1765, 1766,1786, 1788,1808, 1808,1810, 1836,1920, 1957,2309, 2361,2365, 2365,2384, 2384,2392, 2401,2437, 2444,2447, 2448,2451, 2472,2474, 2480,2482, 2482,2486, 2489,2524, 2525,2527, 2529,2544, 2545,2565, 2570,2575, 2576,2579, 2600,2602, 2608,2610, 2611,\n		2613, 2614,2616, 2617,2649, 2652,2654, 2654,2674, 2676,2693, 2699,2701, 2701,2703, 2705,2707, 2728,2730, 2736,2738, 2739,2741, 2745,2749, 2749,2768, 2768,2784, 2784,2821, 2828,2831, 2832,2835, 2856,2858, 2864,2866, 2867,2870, 2873,2877, 2877,2908, 2909,2911, 2913,2949, 2954,2958, 2960,2962, 2965,2969, 2970,\n		2972, 2972,2974, 2975,2979, 2980,2984, 2986,2990, 2997,2999, 3001,3077, 3084,3086, 3088,3090, 3112,3114, 3123,3125, 3129,3168, 3169,3205, 3212,3214, 3216,3218, 3240,3242, 3251,3253, 3257,3294, 3294,3296, 3297,3333, 3340,3342, 3344,3346, 3368,3370, 3385,3424, 3425,3461, 3478,3482, 3505,3507, 3515,3517, 3517,\n		3520, 3526,3585, 3632,3634, 3635,3648, 3654,3713, 3714,3716, 3716,3719, 3720,3722, 3722,3725, 3725,3732, 3735,3737, 3743,3745, 3747,3749, 3749,3751, 3751,3754, 3755,3757, 3760,3762, 3763,3773, 3773,3776, 3780,3782, 3782,3804, 3805,3840, 3840,3904, 3911,3913, 3946,3976, 3979,4096, 4129,4131, 4135,4137, 4138,\n		4176, 4181,4256, 4293,4304, 4342,4352, 4441,4447, 4514,4520, 4601,4608, 4614,4616, 4678,4680, 4680,4682, 4685,4688, 4694,4696, 4696,4698, 4701,4704, 4742,4744, 4744,4746, 4749,4752, 4782,4784, 4784,4786, 4789,4792, 4798,4800, 4800,4802, 4805,4808, 4814,4816, 4822,4824, 4846,4848, 4878,4880, 4880,4882, 4885,\n		4888, 4894,4896, 4934,4936, 4954,5024, 5108,5121, 5740,5743, 5750,5761, 5786,5792, 5866,6016, 6067,6176, 6263,6272, 6312,7680, 7835,7840, 7929,7936, 7957,7960, 7965,7968, 8005,8008, 8013,8016, 8023,8025, 8025,8027, 8027,8029, 8029,8031, 8061,8064, 8116,8118, 8124,8126, 8126,8130, 8132,8134, 8140,8144, 8147,\n		8150, 8155,8160, 8172,8178, 8180,8182, 8188,8319, 8319,8450, 8450,8455, 8455,8458, 8467,8469, 8469,8473, 8477,8484, 8484,8486, 8486,8488, 8488,8490, 8493,8495, 8497,8499, 8505,8544, 8579,12293, 12295,12321, 12329,12337, 12341,12344, 12346,12353, 12436,12445, 12446,12449, 12538,12540, 12542,12549, 12588,\n		12593, 12686,12704, 12727,13312, 13312,19893, 19893,19968, 19968,40869, 40869,40960, 42124,44032, 44032,55203, 55203,63744, 64045,64256, 64262,64275, 64279,64285, 64285,64287, 64296,64298, 64310,64312, 64316,64318, 64318,64320, 64321,64323, 64324,64326, 64433,64467, 64829,64848, 64911,64914, 64967,\n		65008, 65019,65136, 65138,65140, 65140,65142, 65276,65313, 65338,65345, 65370,65382, 65470,65474, 65479,65482, 65487,65490, 65495,65498, 65500\n	];\n\n	var unicodeES3IdCont = [\n		768, 846,864, 866,1155, 1158,1425, 1441,1443, 1465,1467, 1469,1471, 1471,1473, 1474,1476, 1476,1611, 1621,1632, 1641,1648, 1648,1750, 1756,1759, 1764,1767, 1768,1770, 1773,1776, 1785,1809, 1809,1840, 1866,1958, 1968,2305, 2307,2364, 2364,2366, 2381,2385, 2388,2402, 2403,2406, 2415,2433, 2435,2492, 2492,\n		2494, 2500,2503, 2504,2507, 2509,2519, 2519,2530, 2531,2534, 2543,2562, 2562,2620, 2620,2622, 2626,2631, 2632,2635, 2637,2662, 2673,2689, 2691,2748, 2748,2750, 2757,2759, 2761,2763, 2765,2790, 2799,2817, 2819,2876, 2876,2878, 2883,2887, 2888,2891, 2893,2902, 2903,2918, 2927,2946, 2947,3006, 3010,3014, 3016,\n		3018, 3021,3031, 3031,3047, 3055,3073, 3075,3134, 3140,3142, 3144,3146, 3149,3157, 3158,3174, 3183,3202, 3203,3262, 3268,3270, 3272,3274, 3277,3285, 3286,3302, 3311,3330, 3331,3390, 3395,3398, 3400,3402, 3405,3415, 3415,3430, 3439,3458, 3459,3530, 3530,3535, 3540,3542, 3542,3544, 3551,3570, 3571,3633, 3633,\n		3636, 3642,3655, 3662,3664, 3673,3761, 3761,3764, 3769,3771, 3772,3784, 3789,3792, 3801,3864, 3865,3872, 3881,3893, 3893,3895, 3895,3897, 3897,3902, 3903,3953, 3972,3974, 3975,3984, 3991,3993, 4028,4038, 4038,4140, 4146,4150, 4153,4160, 4169,4182, 4185,4969, 4977,6068, 6099,6112, 6121,6160, 6169,6313, 6313,\n		8255, 8256,8400, 8412,8417, 8417,12330, 12335,12441, 12442,12539, 12539,64286, 64286,65056, 65059,65075, 65076,65101, 65103,65296, 65305,65343, 65343,65381, 65381\n	];\n\n\n    /*\n        As per ECMAScript Language Specification 5th Edition, Section 7.6: Identifier Names and Identifiers\n        IdentifierStart :: Can contain Unicode 6.2  categories Uppercase letter (Lu), Lowercase letter (Ll), Titlecase letter (Lt), Modifier letter (Lm), Other letter (Lo), or Letter number (Nl).\n        IdentifierPart :: Can contain IdentifierStart + Unicode 6.2  categories Non-spacing mark (Mn), Combining spacing mark (Mc), Decimal number (Nd), Connector punctuation (Pc), <ZWNJ>, or <ZWJ>.\n                    \n        Codepoint ranges for ES5 Identifiers are extracted from the Unicode 6.2 specification at:\n        http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt\n    */\n	var unicodeES5IdStart = [\n		170, 170,181, 181,186, 186,192, 214,216, 246,248, 705,710, 721,736, 740,748, 748,750, 750,880, 884,886, 887,890, 893,902, 902,904, 906,908, 908,910, 929,931, 1013,1015, 1153,1162, 1319,1329, 1366,1369, 1369,1377, 1415,1488, 1514,1520, 1522,1568, 1610,1646, 1647,1649, 1747,1749, 1749,1765, 1766,1774, 1775,\n		1786, 1788,1791, 1791,1808, 1808,1810, 1839,1869, 1957,1969, 1969,1994, 2026,2036, 2037,2042, 2042,2048, 2069,2074, 2074,2084, 2084,2088, 2088,2112, 2136,2208, 2208,2210, 2220,2308, 2361,2365, 2365,2384, 2384,2392, 2401,2417, 2423,2425, 2431,2437, 2444,2447, 2448,2451, 2472,2474, 2480,2482, 2482,2486, 2489,\n		2493, 2493,2510, 2510,2524, 2525,2527, 2529,2544, 2545,2565, 2570,2575, 2576,2579, 2600,2602, 2608,2610, 2611,2613, 2614,2616, 2617,2649, 2652,2654, 2654,2674, 2676,2693, 2701,2703, 2705,2707, 2728,2730, 2736,2738, 2739,2741, 2745,2749, 2749,2768, 2768,2784, 2785,2821, 2828,2831, 2832,2835, 2856,2858, 2864,\n		2866, 2867,2869, 2873,2877, 2877,2908, 2909,2911, 2913,2929, 2929,2947, 2947,2949, 2954,2958, 2960,2962, 2965,2969, 2970,2972, 2972,2974, 2975,2979, 2980,2984, 2986,2990, 3001,3024, 3024,3077, 3084,3086, 3088,3090, 3112,3114, 3123,3125, 3129,3133, 3133,3160, 3161,3168, 3169,3205, 3212,3214, 3216,3218, 3240,\n		3242, 3251,3253, 3257,3261, 3261,3294, 3294,3296, 3297,3313, 3314,3333, 3340,3342, 3344,3346, 3386,3389, 3389,3406, 3406,3424, 3425,3450, 3455,3461, 3478,3482, 3505,3507, 3515,3517, 3517,3520, 3526,3585, 3632,3634, 3635,3648, 3654,3713, 3714,3716, 3716,3719, 3720,3722, 3722,3725, 3725,3732, 3735,3737, 3743,\n		3745, 3747,3749, 3749,3751, 3751,3754, 3755,3757, 3760,3762, 3763,3773, 3773,3776, 3780,3782, 3782,3804, 3807,3840, 3840,3904, 3911,3913, 3948,3976, 3980,4096, 4138,4159, 4159,4176, 4181,4186, 4189,4193, 4193,4197, 4198,4206, 4208,4213, 4225,4238, 4238,4256, 4293,4295, 4295,4301, 4301,4304, 4346,4348, 4680,\n		4682, 4685,4688, 4694,4696, 4696,4698, 4701,4704, 4744,4746, 4749,4752, 4784,4786, 4789,4792, 4798,4800, 4800,4802, 4805,4808, 4822,4824, 4880,4882, 4885,4888, 4954,4992, 5007,5024, 5108,5121, 5740,5743, 5759,5761, 5786,5792, 5866,5870, 5872,5888, 5900,5902, 5905,5920, 5937,5952, 5969,5984, 5996,5998, 6000,\n		6016, 6067,6103, 6103,6108, 6108,6176, 6263,6272, 6312,6314, 6314,6320, 6389,6400, 6428,6480, 6509,6512, 6516,6528, 6571,6593, 6599,6656, 6678,6688, 6740,6823, 6823,6917, 6963,6981, 6987,7043, 7072,7086, 7087,7098, 7141,7168, 7203,7245, 7247,7258, 7293,7401, 7404,7406, 7409,7413, 7414,7424, 7615,7680, 7957,\n		7960, 7965,7968, 8005,8008, 8013,8016, 8023,8025, 8025,8027, 8027,8029, 8029,8031, 8061,8064, 8116,8118, 8124,8126, 8126,8130, 8132,8134, 8140,8144, 8147,8150, 8155,8160, 8172,8178, 8180,8182, 8188,8305, 8305,8319, 8319,8336, 8348,8450, 8450,8455, 8455,8458, 8467,8469, 8469,8473, 8477,8484, 8484,8486, 8486,\n		8488, 8488,8490, 8493,8495, 8505,8508, 8511,8517, 8521,8526, 8526,8544, 8584,11264, 11310,11312, 11358,11360, 11492,11499, 11502,11506, 11507,11520, 11557,11559, 11559,11565, 11565,11568, 11623,11631, 11631,11648, 11670,11680, 11686,11688, 11694,11696, 11702,11704, 11710,11712, 11718,11720, 11726,\n		11728, 11734,11736, 11742,11823, 11823,12293, 12295,12321, 12329,12337, 12341,12344, 12348,12353, 12438,12445, 12447,12449, 12538,12540, 12543,12549, 12589,12593, 12686,12704, 12730,12784, 12799,13312, 13312,19893, 19893,19968, 19968,40908, 40908,40960, 42124,42192, 42237,42240, 42508,42512, 42527,\n		42538, 42539,42560, 42606,42623, 42647,42656, 42735,42775, 42783,42786, 42888,42891, 42894,42896, 42899,42912, 42922,43000, 43009,43011, 43013,43015, 43018,43020, 43042,43072, 43123,43138, 43187,43250, 43255,43259, 43259,43274, 43301,43312, 43334,43360, 43388,43396, 43442,43471, 43471,43520, 43560,\n		43584, 43586,43588, 43595,43616, 43638,43642, 43642,43648, 43695,43697, 43697,43701, 43702,43705, 43709,43712, 43712,43714, 43714,43739, 43741,43744, 43754,43762, 43764,43777, 43782,43785, 43790,43793, 43798,43808, 43814,43816, 43822,43968, 44002,44032, 44032,55203, 55203,55216, 55238,55243, 55291,\n		63744, 64109,64112, 64217,64256, 64262,64275, 64279,64285, 64285,64287, 64296,64298, 64310,64312, 64316,64318, 64318,64320, 64321,64323, 64324,64326, 64433,64467, 64829,64848, 64911,64914, 64967,65008, 65019,65136, 65140,65142, 65276,65313, 65338,65345, 65370,65382, 65470,65474, 65479,65482, 65487,\n		65490, 65495,65498, 65500\n	];\n\n	var unicodeES5IdCont = [\n		768, 879,1155, 1159,1425, 1469,1471, 1471,1473, 1474,1476, 1477,1479, 1479,1552, 1562,1611, 1641,1648, 1648,1750, 1756,1759, 1764,1767, 1768,1770, 1773,1776, 1785,1809, 1809,1840, 1866,1958, 1968,1984, 1993,2027, 2035,2070, 2073,2075, 2083,2085, 2087,2089, 2093,2137, 2139,2276, 2302,2304, 2307,2362, 2364,\n		2366, 2383,2385, 2391,2402, 2403,2406, 2415,2433, 2435,2492, 2492,2494, 2500,2503, 2504,2507, 2509,2519, 2519,2530, 2531,2534, 2543,2561, 2563,2620, 2620,2622, 2626,2631, 2632,2635, 2637,2641, 2641,2662, 2673,2677, 2677,2689, 2691,2748, 2748,2750, 2757,2759, 2761,2763, 2765,2786, 2787,2790, 2799,2817, 2819,\n		2876, 2876,2878, 2884,2887, 2888,2891, 2893,2902, 2903,2914, 2915,2918, 2927,2946, 2946,3006, 3010,3014, 3016,3018, 3021,3031, 3031,3046, 3055,3073, 3075,3134, 3140,3142, 3144,3146, 3149,3157, 3158,3170, 3171,3174, 3183,3202, 3203,3260, 3260,3262, 3268,3270, 3272,3274, 3277,3285, 3286,3298, 3299,3302, 3311,\n		3330, 3331,3390, 3396,3398, 3400,3402, 3405,3415, 3415,3426, 3427,3430, 3439,3458, 3459,3530, 3530,3535, 3540,3542, 3542,3544, 3551,3570, 3571,3633, 3633,3636, 3642,3655, 3662,3664, 3673,3761, 3761,3764, 3769,3771, 3772,3784, 3789,3792, 3801,3864, 3865,3872, 3881,3893, 3893,3895, 3895,3897, 3897,3902, 3903,\n		3953, 3972,3974, 3975,3981, 3991,3993, 4028,4038, 4038,4139, 4158,4160, 4169,4182, 4185,4190, 4192,4194, 4196,4199, 4205,4209, 4212,4226, 4237,4239, 4253,4957, 4959,5906, 5908,5938, 5940,5970, 5971,6002, 6003,6068, 6099,6109, 6109,6112, 6121,6155, 6157,6160, 6169,6313, 6313,6432, 6443,6448, 6459,6470, 6479,\n		6576, 6592,6600, 6601,6608, 6617,6679, 6683,6741, 6750,6752, 6780,6783, 6793,6800, 6809,6912, 6916,6964, 6980,6992, 7001,7019, 7027,7040, 7042,7073, 7085,7088, 7097,7142, 7155,7204, 7223,7232, 7241,7248, 7257,7376, 7378,7380, 7400,7405, 7405,7410, 7412,7616, 7654,7676, 7679,8204, 8205,8255, 8256,8276, 8276,\n		8400, 8412,8417, 8417,8421, 8432,11503, 11505,11647, 11647,11744, 11775,12330, 12335,12441, 12442,42528, 42537,42607, 42607,42612, 42621,42655, 42655,42736, 42737,43010, 43010,43014, 43014,43019, 43019,43043, 43047,43136, 43137,43188, 43204,43216, 43225,43232, 43249,43264, 43273,43302, 43309,43335, 43347,\n		43392, 43395,43443, 43456,43472, 43481,43561, 43574,43587, 43587,43596, 43597,43600, 43609,43643, 43643,43696, 43696,43698, 43700,43703, 43704,43710, 43711,43713, 43713,43755, 43759,43765, 43766,44003, 44010,44012, 44013,44016, 44025,64286, 64286,65024, 65039,65056, 65062,65075, 65076,65101, 65103,\n		65296, 65305,65343, 65343\n	];\n\n    export function LexLookUpUnicodeMap(code: number, map: number[]) : bool {\n        // Perform binary search in one of the unicode range maps\n        var lo: number = 0;\n        var hi: number = map.length;\n        var mid: number;\n\n        while (lo + 1 < hi)\n        {\n            mid = lo + (hi - lo) / 2;\n            // mid has to be even to catch a range's beginning\n            mid -= mid % 2;\n            if (map[mid] <= code && code <= map[mid + 1])\n                return true;\n            if (code < map[mid])\n                hi = mid;\n            else\n                lo = mid + 2;\n        }\n        return false;\n    }\n\n    export function LexIsUnicodeDigit(code: number): bool {\n        if (codeGenTarget == CodeGenTarget.ES3) {\n            return LexLookUpUnicodeMap(code, unicodeES3IdCont);\n        } else {\n            return LexLookUpUnicodeMap(code, unicodeES5IdCont);\n        }\n    }\n\n    export function LexIsUnicodeIdStart(code: number): bool {\n        if (codeGenTarget == CodeGenTarget.ES3) {\n            return LexLookUpUnicodeMap(code, unicodeES3IdStart);\n        } else {\n            return LexLookUpUnicodeMap(code, unicodeES5IdStart);\n        }\n    }\n    export function LexInitialize() {\n        initializeStaticTokens();\n        autoToken[LexCodeLPR] = staticTokens[TokenID.OpenParen];\n        autoToken[LexCodeRPR] = staticTokens[TokenID.CloseParen];\n        autoToken[LexCodeCMA] = staticTokens[TokenID.Comma];\n        autoToken[LexCodeSMC] = staticTokens[TokenID.Semicolon];\n        autoToken[LexCodeLBR] = staticTokens[TokenID.OpenBracket];\n        autoToken[LexCodeRBR] = staticTokens[TokenID.CloseBracket];\n        autoToken[LexCodeTIL] = staticTokens[TokenID.Tilde];\n        autoToken[LexCodeQUE] = staticTokens[TokenID.Question];\n        autoToken[LexCodeLC] = staticTokens[TokenID.OpenBrace];\n        autoToken[LexCodeRC] = staticTokens[TokenID.CloseBrace];\n        autoToken[LexCodeCOL] = staticTokens[TokenID.Colon];\n        LexKeywordTable = new StringHashTable();\n        for (var i in (<any>TokenID)._map) {\n            if ((<number><any>i) <= TokenID.LimKeyword) {\n                LexKeywordTable.add((<any>TokenID)._map[i].toLowerCase(), i);\n            }\n        }\n        for (var j = 0; j < LexCodeASCIIChars; j++) {\n            if (LexIsIdentifierStartChar(j)) {\n                lexIdStartTable[j] = true;\n            }\n            else {\n                lexIdStartTable[j] = false;\n            }\n        }\n    }\n\n    export function LexAdjustIndent(code, indentAmt) {\n        if ((code == LexCodeLBR) || (code == LexCodeLC) || (code == LexCodeLPR)) {\n            return indentAmt + 1;\n        }\n        else if ((code == LexCodeRBR) || (code == LexCodeRC) || (code == LexCodeRPR)) {\n            return indentAmt - 1;\n        }\n        else return indentAmt;\n    }\n\n    export function LexIsIdentifierStartChar(code): bool {\n        return (((code >= 97) && (code <= 122)) ||\n                ((code >= 65) && (code <= 90)) ||\n                (code == LexCodeDollar) ||\n                (code == LexCodeUnderscore));\n    }\n\n    export function LexIsDigit(code): bool {\n        return ((code >= 48) && (code <= 57));\n    }\n\n    export function LexIsIdentifierChar(code:number) {\n        return lexIdStartTable[code] || LexIsDigit(code);\n    }\n\n    export function LexMatchingOpen(code) {\n        if (code == LexCodeRBR)\n            return LexCodeLBR;\n        else if (code == LexCodeRC)\n            return LexCodeLC;\n        else if (code == LexCodeRPR)\n            return LexCodeLPR;\n        else return 0;\n    }\n\n    export enum NumberScanState {\n        Start,\n        InFraction,\n        InEmptyFraction,\n        InExponent\n    }\n\n    export enum LexState {\n        Start,\n        InMultilineComment,\n        InMultilineSingleQuoteString,\n        InMultilineDoubleQuoteString,\n    }\n\n    export enum LexMode {\n        Line,\n        File,\n    }\n\n    export enum CommentStyle {\n        Line,\n        Block\n    }\n\n    // Represent a piece of source code which can be read in multiple segments\n    export interface ISourceText {\n        getText(start: number, end: number): string;\n        getLength(): number;\n    }\n\n    // Implementation on top of a contiguous string\n    export class StringSourceText implements ISourceText {\n        constructor (public text: string) {\n        }\n\n        public getText(start: number, end: number): string {\n            return this.text.substring(start, end);\n        }\n\n        public getLength(): number {\n            return this.text.length;\n        }\n    }\n\n    export class SourceTextSegment implements ISourceTextSegment {\n        constructor (public segmentStart: number,\n                    public segmentEnd: number,\n                    public segment: string) {\n        }\n\n        charCodeAt(index: number): number {\n            return this.segment.charCodeAt(index - this.segmentStart);\n        }\n\n        substring(start: number, end: number): string {\n            return this.segment.substring(start - this.segmentStart, end - this.segmentStart);\n        }\n    }\n\n    export class AggerateSourceTextSegment implements ISourceTextSegment {\n\n        constructor (public seg1: SourceTextSegment, public seg2: SourceTextSegment) { }\n\n        public charCodeAt(index: number): number {\n            if (this.seg1.segmentStart <= index && index < this.seg1.segmentEnd)\n                return this.seg1.segment.charCodeAt(index - this.seg1.segmentStart);\n\n            return this.seg2.segment.charCodeAt(index - this.seg2.segmentStart);\n        }\n\n        public substring(start: number, end: number): string {\n            if (this.seg1.segmentStart <= start && end <= this.seg1.segmentEnd)\n                return this.seg1.segment.substring(start - this.seg1.segmentStart, end - this.seg1.segmentStart);\n\n            return this.seg2.segment.substring(start - this.seg2.segmentStart) + this.seg1.segment.substring(0, end - this.seg1.segmentStart);\n        }\n    }\n\n    export interface ISourceTextSegment {\n        charCodeAt(index: number): number;\n        substring(start: number, end: number): string;\n    }\n\n    export class ScannerTextStream {\n        static emptySegment = new SourceTextSegment(0, 0, \"\");\n        public agg: AggerateSourceTextSegment;\n        public len: number;\n\n        constructor (public sourceText: ISourceText) {\n            this.agg = new AggerateSourceTextSegment(ScannerTextStream.emptySegment, ScannerTextStream.emptySegment);\n            this.len = this.sourceText.getLength();\n        }\n\n        public max(a: number, b: number): number {\n            return a >= b ? a : b;\n        }\n\n        public min(a: number, b: number): number {\n            return a <= b ? a : b;\n        }\n\n        public fetchSegment(start: number, end: number): ISourceTextSegment {\n            // Common case\n            if (this.agg.seg1.segmentStart <= start && end <= this.agg.seg1.segmentEnd)\n                return this.agg.seg1;\n\n            // Common overlap case\n            if (this.agg.seg2.segmentStart <= start && end <= this.agg.seg1.segmentEnd)\n                return this.agg;\n\n            // if overlapping outside of fetched segment(s), fetch a new segment\n            var prev = this.agg.seg1;\n\n            var s = prev.segmentEnd;\n            var e = max(s + 512, end); // ensure we move forward at least 512 characters or \"end\"\n            e = min(e, this.len);    // but don't go past the end of the source text\n\n            var src = this.sourceText.getText(s, e);\n            var newSeg = new SourceTextSegment(s, e, src);\n            this.agg.seg2 = prev;\n            this.agg.seg1 = newSeg;\n            return this.agg;\n        }\n\n        public charCodeAt(index: number): number {\n            return this.fetchSegment(index, index + 1).charCodeAt(index);\n        }\n\n        public substring(start: number, end: number) {\n            return this.fetchSegment(start, end).substring(start, end);\n        }\n    }\n\n    export interface IScanner {\n        startPos: number;\n        pos: number;\n        scan(): Token;\n        previousToken(): Token;\n        prevLine: number;\n        line: number;\n        col: number;\n        leftCurlyCount: number;\n        rightCurlyCount: number;\n        lastTokenLimChar(): number;\n        lastTokenHadNewline(): bool;\n        lexState: number;\n        getComments(): CommentToken[];\n        getCommentsForLine(line: number): CommentToken[];\n        resetComments(): void;\n        lineMap: number[];\n        setSourceText(newSrc: ISourceText, textMode: number): void;\n        setErrorHandler(reportError: (message: string) => void): void;\n        seenUnicodeChar: bool;\n        seenUnicodeCharInComment: bool;\n        getLookAheadToken(): Token;\n    }\n\n    export class SavedTokens implements IScanner {\n        public prevToken: Token = null;\n        public curSavedToken: SavedToken = null;\n        public prevSavedToken: SavedToken = null;\n        public currentTokenIndex: number;\n        public currentTokens: SavedToken[];\n        public tokensByLine: SavedToken[][];\n        public lexStateByLine: LexState[];\n        private prevToken: SavedToken = null;\n        public previousToken(): Token { return this.prevToken; }\n        public currentToken = 0;\n        public tokens = new SavedToken[];\n        public startPos: number;\n        public pos: number;\n        public seenUnicodeChar: bool = false;\n        seenUnicodeCharInComment: bool = false;\n\n        public close() {\n            this.currentToken = 0;\n        }\n\n        public addToken(tok: Token, scanner: IScanner) {\n            this.tokens[this.currentToken++] = new SavedToken(tok, scanner.startPos, scanner.pos);\n        }\n\n        public scan(): Token {\n            // TODO: curly count\n            this.startLine = this.line;\n            this.startPos = this.col;\n            if (this.currentTokenIndex == this.currentTokens.length) {\n                if (this.line < this.lineMap.length) {\n                    this.line++;\n                    this.col = 0;\n                    this.currentTokenIndex = 0;\n                    this.currentTokens = this.tokensByLine[this.line];\n                }\n                else {\n                    return staticTokens[TokenID.EndOfFile];\n                }\n            }\n            if (this.currentTokenIndex < this.currentTokens.length) {\n                this.prevToken = this.curSavedToken.tok;\n                this.prevSavedToken = this.curSavedToken;\n                this.curSavedToken = this.currentTokens[this.currentTokenIndex++];\n                var curToken = this.curSavedToken.tok;\n                this.pos = this.curSavedToken.limChar;\n                this.col += (this.curSavedToken.limChar - this.curSavedToken.minChar);\n                this.startPos = this.curSavedToken.minChar;\n                this.prevLine = this.line;\n                return curToken;\n            }\n            else {\n                return staticTokens[TokenID.EndOfFile];\n            }\n        }\n        public startLine: number;\n        public prevLine = 1;\n        public line = 1;\n        public col = 0;\n        public leftCurlyCount: number;\n        public rightCurlyCount: number;\n\n        public syncToTok(offset: number): number {\n            this.line = getLineNumberFromPosition(this.lineMap, offset);\n            this.currentTokenIndex = 0;\n            var tmpCol = offset - this.lineMap[this.line];\n            while ((this.lexStateByLine[this.line] == LexState.InMultilineComment) && (this.line > 0)) {\n                this.line--;\n                tmpCol = 0;\n            }\n            var lenMin1 = this.lineMap.length - 1;\n            this.currentTokens = this.tokensByLine[this.line];\n            while ((this.currentTokens.length == 0) && (this.line < lenMin1)) {\n                this.line++;\n                this.currentTokens = this.tokensByLine[this.line];\n                tmpCol = 0;\n            }\n            if (this.line <= lenMin1) {\n                while ((this.currentTokenIndex < this.currentTokens.length) &&\n                       (tmpCol > this.currentTokens[this.currentTokenIndex].limChar)) {\n                    this.currentTokenIndex++;\n                }\n                if (this.currentTokenIndex < this.currentTokens.length) {\n                    this.col = this.currentTokens[this.currentTokenIndex].minChar;\n                    return this.col + this.lineMap[this.line];\n                }\n            }\n            return -1;\n        }\n\n        public lastTokenLimChar(): number {\n            if (this.prevSavedToken !== null) {\n                return this.prevSavedToken.limChar;\n            }\n            else {\n                return 0;\n            }\n        }\n\n        public lastTokenHadNewline(): bool {\n            return this.prevLine != this.startLine;\n        }\n\n        public lexState = LexState.Start;\n\n        public commentStack: CommentToken[] = new CommentToken[];\n\n        public pushComment(comment: CommentToken) {\n            this.commentStack.push(comment);\n        }\n\n        public getComments() {\n            var stack = this.commentStack;\n            this.commentStack = [];\n            return stack;\n        }\n\n        public getCommentsForLine(line: number) {\n            var comments: CommentToken[] = null;\n            while ((this.commentStack.length > 0) && (this.commentStack[0].line == line)) {\n                if (comments == null) {\n                    comments = [this.commentStack.shift()];\n                }\n                else {\n                    comments = comments.concat([this.commentStack.shift()]);\n                }\n\n            }\n            return comments;\n        }\n\n        public resetComments() {\n            this.commentStack = [];\n        }\n\n        public lineMap: number[] = [];\n        public setSourceText(newSrc: ISourceText, textMode: number) {\n        }\n        public setErrorHandler(reportError: (message: string) => void ) { \n        }\n        public getLookAheadToken(): Token {\n            throw new Error(\"Invalid operation.\");\n        }\n    }\n\n    export class Scanner implements IScanner {\n        // REVIEW: When adding new variables make sure to handle storing them in getLookAheadToken. \n        //         The method works by storing the state before scanning and restoring it later on, missing a member variable \n        //         could result in an inconsistent state.\n        public prevLine = 1;\n        public line = 1;\n        public col = 0;\n        public pos = 0;\n        public startPos = 0;\n        public startCol: number;\n        public startLine: number;\n        public src: string;\n        public len = 0;\n        public lineMap: number[] = [];\n        \n        public ch = LexEOF;\n        public lexState = LexState.Start;\n        public mode = LexMode.File;\n        public scanComments: bool = true;\n        public interveningWhitespace = false; // Was there a whitespace token between the last token and the current one?\n        private interveningWhitespacePos = 0; //  If yes, this contains the start position of the whitespace\n        public leftCurlyCount = 0;\n        public rightCurlyCount = 0;\n        public commentStack: CommentToken[] = new CommentToken[];\n        public saveScan: SavedTokens = null;\n        public seenUnicodeChar: bool = false;\n        seenUnicodeCharInComment: bool = false;\n\n        private reportError: (message: string) =>void;\n\n        constructor () {\n            this.startCol = this.col;\n            this.startLine = this.line;            \n            this.lineMap[1] = 0;\n            \n            if (!LexKeywordTable) {\n                LexInitialize();\n            }            \n        }\n\n        private prevTok = staticTokens[TokenID.EndOfFile];\n        public previousToken() { return this.prevTok; }\n\n        public setSourceText(newSrc: ISourceText, textMode: number) {\n            this.mode = textMode;\n            this.scanComments = (this.mode === LexMode.Line);\n            this.pos = 0;\n            this.interveningWhitespacePos = 0;\n            this.startPos = 0;\n            this.line = 1;\n            this.col = 0;\n            this.startCol = this.col;\n            this.startLine = this.line;\n            this.len = 0;\n            this.src = newSrc.getText(0, newSrc.getLength());\n            this.len = this.src.length;\n            this.lineMap = [];\n            this.lineMap[1] = 0;\n            this.commentStack = [];\n            this.leftCurlyCount = 0;\n            this.rightCurlyCount = 0;\n            this.seenUnicodeChar = false;\n            this.seenUnicodeCharInComment = false;\n        }\n\n        public setErrorHandler(reportError: (message: string) => void ) { \n            this.reportError = reportError;\n        }\n\n        public setSaveScan(savedTokens: SavedTokens) {\n            this.saveScan = savedTokens;\n        }\n\n        public setText(newSrc: string, textMode: number) {\n            this.setSourceText(new StringSourceText(newSrc), textMode);\n        }\n\n        public setScanComments(value: bool) {\n            this.scanComments = value;\n        }\n\n        public getLexState(): number {\n            return this.lexState;\n        }\n\n        public tokenStart() {\n            this.startPos = this.pos;\n            this.startLine = this.line;\n            this.startCol = this.col;\n            this.interveningWhitespace = false;\n        }\n\n        public peekChar(): number {\n            if (this.pos < this.len) {\n                return this.src.charCodeAt(this.pos);\n            }\n            else {\n                return LexEOF;\n            }\n        }\n\n        public peekCharAt(index: number): number {\n            if (index < this.len) {\n                return this.src.charCodeAt(index);\n            }\n            else {\n                return LexEOF;\n            }\n        }\n\n        public IsHexDigit(c: number) {\n            return ((c >= LexCode_0) && (c <= LexCode_9)) || ((c >= LexCode_A) && (c <= LexCode_F)) ||\n                ((c >= LexCode_a) && (c <= LexCode_f));\n        }\n\n        public IsOctalDigit(c: number) {\n            return ((c >= LexCode_0) && (c <= LexCode_7)) ||\n                ((c >= LexCode_a) && (c <= LexCode_f));\n        }\n\n        public scanHexDigits(): Token {\n            var atLeastOneDigit = false;\n            for (; ;) {\n                if (this.IsHexDigit(this.ch)) {\n                    this.nextChar();\n                    atLeastOneDigit = true;\n                }\n                else {\n                    if (atLeastOneDigit) {\n                        return new NumberLiteralToken(parseInt(this.src.substring(this.startPos, this.pos)));\n                    }\n                    else {\n                        return null;\n                    }\n                }\n            }\n\n        }\n\n        public scanOctalDigits(): Token {\n            var atLeastOneDigit = false;\n            for (; ;) {\n                if (this.IsOctalDigit(this.ch)) {\n                    this.nextChar();\n                    atLeastOneDigit = true;\n                }\n                else {\n                    if (atLeastOneDigit) {\n                        return new NumberLiteralToken(parseInt(this.src.substring(this.startPos, this.pos)));\n                    }\n                    else {\n                        return null;\n                    }\n                }\n            }\n\n        }\n\n        public scanDecimalNumber(state: number): Token {\n            var atLeastOneDigit = false;\n            var svPos = this.pos;\n            var svCol = this.col;\n            for (; ;) {\n                if (LexIsDigit(this.ch)) {\n                    atLeastOneDigit = true;\n                    if (this.ch != LexCode_0 && state == NumberScanState.InEmptyFraction) {\n                        state = NumberScanState.InFraction;\n                    }\n                    this.nextChar();\n                }\n                else if (this.ch == LexCodeDOT) {\n                    if (state == NumberScanState.Start) {\n                        // DecimalDigit* .\n                        this.nextChar();\n                        state = NumberScanState.InEmptyFraction;\n                    }\n                    else {\n                        // dot not part of number\n                        if (atLeastOneDigit) {\n                            // DecimalDigit* . DecimalDigit+\n                            return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);\n                        }\n                        else {\n                            this.pos = svPos;\n                            this.col = svCol;\n                            return null;\n                        }\n                    }\n                } else if ((this.ch == LexCode_e) || (this.ch == LexCode_E)) {\n                    if (state == NumberScanState.Start) {\n                        if (atLeastOneDigit) {\n                            // DecimalDigit+ (. DecimalDigit*) [eE] [+-]DecimalDigit+\n                            atLeastOneDigit = false;\n                            this.nextChar();\n                            state = NumberScanState.InExponent;\n                        }\n                        else {\n                            this.pos = svPos;\n                            this.col = svCol;\n                            return null;\n                        }\n                    }\n                    else if (state == NumberScanState.InFraction || state == NumberScanState.InEmptyFraction) {\n                        // DecimalDigit+ . DecimalDigit* [eE]\n                        this.nextChar();\n                        state = NumberScanState.InExponent;\n                        atLeastOneDigit = false;\n                    }\n                    else {\n                        // DecimalDigit+ . DecimalDigit* [eE] DecimalDigit+\n                        if (atLeastOneDigit) {\n                            return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)));\n                        }\n                        else {\n                            this.pos = svPos;\n                            this.col = svCol;\n                            return null;\n                        }\n                    }\n                }\n                else if ((this.ch == LexCodePLS) || (this.ch == LexCodeMIN)) {\n                    if (state == NumberScanState.InExponent) {\n                        if (!atLeastOneDigit) {\n                            this.nextChar();\n                        }\n                        else {\n                            this.pos = svPos;\n                            this.col = svCol;\n                            return null;\n                        }\n                    }\n                    else if (state == NumberScanState.InEmptyFraction || state == NumberScanState.InFraction) {\n                        // This case will not generate bad javascript if we miss the fractional part, but we just want to be consistent with the dot case\n                        return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);\n                    }\n                    else {\n                        if (!atLeastOneDigit) {\n                            this.pos = svPos;\n                            this.col = svCol;\n                            return null;\n                        }\n                        else {\n                            return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)));\n                        }\n                    }\n                }\n                else {\n                    if (!atLeastOneDigit) {\n                        this.pos = svPos;\n                        this.col = svCol;\n                        return null;\n                    }\n                    else {\n                        return new NumberLiteralToken(parseFloat(this.src.substring(this.startPos, this.pos)), state == NumberScanState.InEmptyFraction);\n                    }\n                }\n            }\n        }\n\n        // 0 [xX] hexDigits\n        // 0 octalDigits\n        // 0 [89] decimalDigits\n        // decimalDigits? fraction? exponent?\n\n        public scanNumber(): Token {\n            if (this.peekChar() == LexCode_0) {\n                switch (this.peekCharAt(this.pos + 1)) {\n                    case LexCode_x:\n                    case LexCode_X:\n                        // Hex\n                        this.advanceChar(2);\n                        return this.scanHexDigits();\n                    case LexCode_8:\n                    case LexCode_9:\n                    case LexCodeDOT:\n                        return this.scanDecimalNumber(NumberScanState.Start);\n                    default:\n                        // Octal\n                        return this.scanOctalDigits();\n                }\n            }\n            else {\n                return this.scanDecimalNumber(NumberScanState.Start);\n            }\n        }\n\n        public scanFraction(): Token {\n            return this.scanDecimalNumber(NumberScanState.InFraction);\n        }\n\n        public newLine() {\n            this.col = 0;\n            if (this.mode == LexMode.File) {\n                this.line++;\n                this.lineMap[this.line] = this.pos + 1;\n            }\n        }\n\n        public finishMultilineComment(): bool {\n            var ch2: number;\n            this.lexState = LexState.InMultilineComment;\n            while (this.pos < this.len) {\n                if (this.ch == LexCodeMUL) {\n                    ch2 = this.peekCharAt(this.pos + 1);\n                    if (ch2 == LexCodeSLH) {\n                        this.advanceChar(2);\n                        if (this.mode == LexMode.File) {\n                            this.tokenStart();\n                        }\n                        this.lexState = LexState.Start;\n                        return true;\n                    }\n                }\n                else if (this.ch == LexCodeNWL) {\n                    this.newLine();\n                    if (this.mode == LexMode.Line) {\n                        this.nextChar();\n                        return false;\n                    }\n                } \n                else if (this.ch >= LexCodeASCIIChars) { \n                    this.seenUnicodeCharInComment = true;\n                }\n                this.nextChar();\n            }\n            return false;\n        }\n\n        public pushComment(comment: CommentToken) {\n            this.commentStack.push(comment);\n        }\n\n        public getComments() {\n            var stack = this.commentStack;\n            this.commentStack = [];\n            return stack;\n        }\n\n        public getCommentsForLine(line: number) {\n            var comments: CommentToken[] = null;\n            while ((this.commentStack.length > 0) && (this.commentStack[0].line == line)) {\n                if (comments == null) {\n                    comments = [this.commentStack.shift()];\n                }\n                else {\n                    comments = comments.concat([this.commentStack.shift()]);\n                }\n\n            }\n            return comments;\n        }\n\n        public resetComments() {\n            this.commentStack = [];\n        }\n\n        public endsLine(c: number) {\n            return (c == LexCodeNWL) || (c == LexCodeRET) || (c == LexCodeLS) || (c == LexCodePS);\n        }\n\n        public finishSinglelineComment() {\n            while (this.pos < this.len) {\n                if (this.endsLine(this.ch))\n                    break;\n                if (this.ch >= LexCodeASCIIChars) { \n                    this.seenUnicodeCharInComment = true;\n                }\n                this.nextChar();\n            }\n\n            if (this.mode == LexMode.File) {\n                this.tokenStart();\n            }\n        }\n\n        public tokenText(): string {\n            return this.src.substring(this.startPos, this.pos);\n        }\n\n        public findClosingSLH() {\n            var index = this.pos;\n            var ch2 = this.src.charCodeAt(index);\n            var prevCh = 0;\n            var liveEsc = false;\n            while (!this.endsLine(ch2) && (index < this.len)) {\n                if ((ch2 == LexCodeSLH) && (!liveEsc)) {\n                    return index;\n                }\n                prevCh = ch2;\n                index++;\n                if (liveEsc) {\n                    liveEsc = false;\n                }\n                else {\n                    liveEsc = (prevCh == LexCodeBSL);\n                }\n\n                ch2 = this.src.charCodeAt(index);\n            }\n            return -1;\n        }\n\n        public speculateRegex(): Token {\n            if (noRegexTable[this.prevTok.tokenId] != undefined) {\n                return null;\n            }\n            var svPos = this.pos;\n            var svCol = this.col;\n            // first char is '/' and has been skipped\n            var index = this.findClosingSLH();\n            if (index > 0) {\n                // found closing /\n                var pattern = this.src.substring(svPos, index);\n                var flags = \"\";\n                this.pos = index + 1;\n                this.ch = this.peekChar();\n                var flagsStart = this.pos;\n                // TODO: check for duplicate flags\n                while ((this.ch == LexCode_i) || (this.ch == LexCode_g) || (this.ch == LexCode_m)) {\n                    this.nextChar();\n                }\n                if ((this.pos - flagsStart) > 3) {\n                    return null;\n                }\n                else {\n                    flags = this.src.substring(flagsStart, this.pos);\n                }\n                var regex = undefined;\n                try {\n                    regex = new RegExp(pattern, flags);\n                }\n                catch (regexException) {\n                }\n                if (regex) {\n                    // no line boundary in regex string\n                    this.col = svCol + (this.pos - this.startPos);\n                    return new RegularExpressionLiteralToken(regex);\n                }\n            }\n            this.pos = svPos;\n            this.col = svCol;\n            return null;\n        }\n\n        public lastTokenHadNewline() {\n            return this.prevLine != this.startLine;\n        }\n\n        public lastTokenLimChar() {\n            return this.interveningWhitespace ? this.interveningWhitespacePos : this.startPos;\n        }\n\n        // use only when known not to skip line terminators\n        public advanceChar(amt: number) {\n            this.pos += amt;\n            this.col += amt;\n            this.ch = this.peekChar();\n        }\n\n        public nextChar() {\n            this.pos++;\n            this.col++;\n            this.ch = this.peekChar();\n        }\n\n        public getLookAheadToken(): Token {\n            // REVIEW: This method is only used for parsing varargs in lambda expressions. If this functionality is needed for more common cases, \n            //         it needs to be designed. \n            //         Look-ahead token needs to be integrated in the scanner design to allow for an efficient lookup.\n\n            // Store the scanner state\n            var prevLine = this.prevLine;\n            var line = this.line;\n            var col = this.col;\n            var pos = this.pos;\n            var startPos = this.startPos;\n            var startCol = this.startCol;\n            var startLine = this.startLine;\n            var ch = this.ch;\n            var prevTok = this.prevTok;\n            var lexState = this.lexState;\n            var interveningWhitespace = this.interveningWhitespace;\n            var interveningWhitespacePos = this.interveningWhitespacePos;\n            var leftCurlyCount = this.leftCurlyCount;\n            var rightCurlyCount = this.rightCurlyCount;\n            var seenUnicodeChar = this.seenUnicodeChar;\n            var seenUnicodeCharInComment = this.seenUnicodeCharInComment;\n            var commentStackLength = this.commentStack.length;\n\n            var lookAheadToken = this.scan();\n\n            // Restore state\n            this.prevLine = prevLine;\n            this.line = line;\n            this.col = col;\n            this.pos = pos;\n            this.startPos = startPos;\n            this.startCol = startCol;\n            this.startLine = startLine;\n            this.ch = ch;\n            this.prevTok = prevTok;\n            this.lexState = lexState;\n            this.interveningWhitespace = interveningWhitespace;\n            this.interveningWhitespacePos = interveningWhitespacePos;\n            this.leftCurlyCount = leftCurlyCount;\n            this.rightCurlyCount = rightCurlyCount;\n            this.seenUnicodeChar = seenUnicodeChar;\n            this.seenUnicodeCharInComment = seenUnicodeCharInComment;\n            this.commentStack.length = commentStackLength;\n\n            return lookAheadToken;\n        }\n\n        public scanInLine(): Token {\n            if ((this.lexState == LexState.InMultilineComment) && (this.scanComments)) {\n                this.ch = this.peekChar();\n                var commentLine = this.line;\n                this.finishMultilineComment();\n                if (this.startPos < this.pos) {\n                    var commentText = this.src.substring(this.startPos, this.pos);\n                    this.tokenStart();\n                    return new CommentToken(TokenID.Comment, commentText,/*isBlock*/true, this.startPos, commentLine,/*endsLine*/true);\n                }\n                else {\n                    return staticTokens[TokenID.EndOfFile];\n                }\n            } \n            else if (this.lexState == LexState.InMultilineSingleQuoteString && this.pos < this.len) { \n                this.ch = LexCodeAPO;\n                this.lexState = LexState.Start;\n                return this.scanStringConstant();\n            }\n            else if (this.lexState == LexState.InMultilineDoubleQuoteString && this.pos < this.len) { \n                this.ch = LexCodeQUO;\n                this.lexState = LexState.Start;\n                return this.scanStringConstant();\n            }\n            this.prevLine = this.line;\n            var prevTok = this.innerScan();\n\n            // Ingore white spaces\n            if (prevTok.tokenId != TokenID.Whitespace) {\n                this.prevTok = prevTok;\n            }\n            return prevTok;\n        }\n\n        public scan(): Token {\n            this.prevLine = this.line;\n            this.prevTok = this.innerScan();\n            if (this.saveScan) {\n                this.saveScan.addToken(this.prevTok, this);\n            }\n            return this.prevTok;\n        }\n\n        private isValidUnicodeIdentifierChar(): bool {\n            var valid = LexIsUnicodeIdStart(this.ch) || LexIsUnicodeDigit(this.ch);\n            this.seenUnicodeChar = this.seenUnicodeChar || valid;\n            return valid;\n        }\n\n        private scanStringConstant(): Token {\n            var endCode = this.ch;\n            \n            // Skip the first quote\n            this.nextChar();\n            \n            // Accumulate with escape characters\n            scanStringConstantLoop:\n            for (;;) {\n                switch (this.ch) {\n                    case LexEOF:\n                        // Unexpected end of file\n                        this.reportScannerError(\"Unterminated string constant\");\n                        break scanStringConstantLoop;\n\n                    case LexCodeLS:\n                    case LexCodePS:\n                        this.seenUnicodeChar = true;\n                    // Intentional fall through\n                    case LexCodeRET:\n                    case LexCodeNWL:\n                        this.reportScannerError(\"Unterminated string constant\");\n                        break scanStringConstantLoop;\n\n                    case LexCodeAPO:\n                    case LexCodeQUO:\n                        if (this.ch == endCode) {\n                            // Found string terminator. Skip past end code.\n                            this.nextChar();\n                            break scanStringConstantLoop;\n                        }\n                        break;\n\n                    case LexCodeBSL:\n                        // Consume the current slash\n                        this.nextChar();\n\n                        switch (this.ch) {\n                            case LexCodeAPO:\n                            case LexCodeQUO:\n                            case LexCodeBSL:\n                                // Valid escape sequences\n                                this.nextChar();\n                                continue scanStringConstantLoop;\n\n                            case LexCodeLS:\n                            case LexCodePS:\n                                this.seenUnicodeChar = true;\n                            // Intentional fall through\n                            case LexCodeRET:\n                            case LexCodeNWL:\n                                // Skip /r in a /r/n sequence\n                                if (this.ch == LexCodeRET && this.peekCharAt(this.pos + 1) == LexCodeNWL) {\n                                    this.nextChar();\n                                }\n\n                                // Consume the new line char\n                                this.nextChar();\n\n                                // Record new line\n                                this.newLine();\n\n                                if (this.mode == LexMode.Line) {\n                                    this.lexState = endCode == LexCodeAPO ? LexState.InMultilineSingleQuoteString : LexState.InMultilineDoubleQuoteString;\n                                    break scanStringConstantLoop;\n                                }\n                                break;\n\n                            case LexCode_x:\n                            case LexCode_u:\n                                var expectedHexDigits = this.ch == LexCode_x ? 2 : 4;\n                                this.nextChar();\n                                for (var i = 0; i < expectedHexDigits; i++) {\n                                    if (this.IsHexDigit(this.ch)) {\n                                        this.nextChar();\n                                    }\n                                    else {\n                                        this.reportScannerError(\"Invalid Unicode escape sequence\");\n                                        break;\n                                    }\n                                }\n                                continue scanStringConstantLoop;\n                        }\n                        break;\n                }\n\n                // Record seeing a Unicode char\n                if (this.ch >= LexCodeASCIIChars) {\n                    this.seenUnicodeChar = true;\n                }\n\n                this.nextChar();\n            }\n\n            return new StringLiteralToken(this.src.substring(this.startPos, this.pos));\n        }\n\n        private scanIdentifier(): Token {\n            var hasEscape = false;\n            var isFirstChar = (this.ch == LexCodeBSL);\n            var hasUnicode: any = false;\n\n            for (; ;) {\n                while (lexIdStartTable[this.ch] || LexIsDigit(this.ch) || \n                      (this.ch >= LexCodeASCIIChars && this.isValidUnicodeIdentifierChar())) {\n                    this.nextChar();\n                }\n                if (this.ch == LexCodeBSL) {\n                    this.nextChar();\n                    if (this.ch == LexCode_u) {\n                        // 4 hex digits\n                        this.nextChar();\n                        for (var h = 0; h < 4 ; h++) {\n                            if (this.IsHexDigit(this.ch)) {\n                                this.nextChar();\n                            }\n                            else {\n                                this.reportScannerError(\"Invalid Unicode escape sequence\");\n                                return staticTokens[TokenID.Error];\n                            }\n                        }\n                        var hexChar = parseInt(this.src.substring(this.pos - 4, this.pos), 16);\n\n                        // Verify is valid ID char \n                        if (lexIdStartTable[hexChar] || (!isFirstChar && LexIsDigit(hexChar)) ||\n                            (hexChar >= LexCodeASCIIChars && (LexIsUnicodeIdStart(hexChar) || (!isFirstChar && LexIsUnicodeDigit(hexChar))))) {\n                        }\n                        else { \n                            this.reportScannerError(\"Invalid identifier character\");\n                            return staticTokens[TokenID.Error];\n                        }\n\n                        hasEscape = true;\n                        isFirstChar = false;\n                        continue;\n                    }\n\n                    this.reportScannerError(\"Invalid Unicode escape sequence\");\n                    return staticTokens[TokenID.Error];\n                }\n                break;\n            }\n\n            var id: number;\n            var text = this.src.substring(this.startPos, this.pos);\n            if (!hasEscape && (id = LexKeywordTable.lookup(text)) != null) {\n                return staticTokens[id];\n            }\n            else {\n                return new IdentifierToken(text, hasEscape);\n            }\n        }\n\n        public innerScan(): Token {\n            var rtok;\n            this.tokenStart();\n            this.ch = this.peekChar();\n\n            start: while (this.pos < this.len) {\n                 if (lexIdStartTable[this.ch] || this.ch == LexCodeBSL || (this.ch >= LexCodeASCIIChars && LexIsUnicodeIdStart(this.ch))) {\n                    // identifier or keyword\n                    return this.scanIdentifier();\n                }\n                else if (this.ch == LexCodeSpace) {\n                    if (!this.interveningWhitespace) {\n                        this.interveningWhitespacePos = this.pos;\n                    }\n                    do {\n                        this.nextChar();\n                    } while (this.ch == LexCodeSpace);\n                    if (this.mode == LexMode.Line) {\n                        var whitespaceText = this.src.substring(this.startPos, this.pos);\n                        return new WhitespaceToken(TokenID.Whitespace, whitespaceText);\n                    }\n                    else {\n                        this.tokenStart();\n                        this.interveningWhitespace = true;\n                    }\n                }\n                else if (this.ch == LexCodeSLH) {\n                    this.nextChar();\n                    var commentText;\n                    if (this.ch == LexCodeSLH) {\n                        if (!this.interveningWhitespace) {\n                            this.interveningWhitespacePos = this.pos - 1;\n                        }\n                        var commentStartPos = this.pos - 1;\n                        var commentStartLine = this.line;\n                        this.finishSinglelineComment();\n                        var commentText = this.src.substring(commentStartPos, this.pos);\n                        var commentToken = new CommentToken(TokenID.Comment, commentText,/*isBlock*/false, commentStartPos, commentStartLine,/*endsLine*/false);\n                        if (this.scanComments) {\n                            // respect scanner contract: when returning a token, startPos is the start position of the token\n                            this.startPos = commentStartPos;\n                            return commentToken;\n                        }\n                        else {\n                            this.pushComment(commentToken);\n                        }\n\n                        this.interveningWhitespace = true;\n                    }\n                    else if (this.ch == LexCodeMUL) {\n                        if (!this.interveningWhitespace) {\n                            this.interveningWhitespacePos = this.pos - 1;\n                        }\n                        var commentStartPos = this.pos - 1;\n                        var commentStartLine = this.line;\n                        this.nextChar();  // Skip the \"*\"\n                        this.finishMultilineComment();\n                        var commentText = this.src.substring(commentStartPos, this.pos);\n                        var endsLine = this.endsLine(this.peekChar());\n                        var commentToken = new CommentToken(TokenID.Comment, commentText,/*isBlock*/true, commentStartPos, commentStartLine, endsLine);\n                        if (this.scanComments) {\n                            // respect scanner contract: when returning a token, startPos is the start position of the token\n                            this.startPos = commentStartPos;\n                            return commentToken;\n                        }\n                        else {\n                            this.pushComment(commentToken);\n                        }\n                        this.interveningWhitespace = true;\n                    }\n                    else {\n                        var regexTok = this.speculateRegex();\n                        if (regexTok) {\n                            return regexTok;\n                        }\n                        else {\n                            if (this.peekCharAt(this.pos) == LexCodeEQ) {\n                                this.nextChar();\n                                return staticTokens[TokenID.SlashEquals];\n                            }\n                            else {\n                                return staticTokens[TokenID.Slash];\n                            }\n                        }\n                    }\n                }\n                else if (this.ch == LexCodeSMC) {\n                    this.nextChar();\n                    return staticTokens[TokenID.Semicolon];\n                }\n                else if ((this.ch == LexCodeAPO) || (this.ch == LexCodeQUO)) {\n                    return this.scanStringConstant();\n                }\n                else if (autoToken[this.ch]) {\n                    var atok = autoToken[this.ch];\n                    if (atok.tokenId == TokenID.OpenBrace) {\n                        this.leftCurlyCount++;\n                    }\n                    else if (atok.tokenId == TokenID.CloseBrace) {\n                        this.rightCurlyCount++;\n                    }\n                    this.nextChar();\n                    return atok;\n                }\n                else if ((this.ch >= LexCode_0) && (this.ch <= LexCode_9)) {\n                    rtok = this.scanNumber();\n                    if (rtok) {\n                        return rtok;\n                    }\n                    else {\n                        this.nextChar();\n                        return staticTokens[TokenID.Error];\n                    }\n                }\n                else switch (this.ch) {\n                    // TAB\n                    case LexCodeTAB:\n                    case LexCodeVTAB:\n                        if (!this.interveningWhitespace) {\n                            this.interveningWhitespacePos = this.pos;\n                        }\n                        if (this.mode == LexMode.Line) {\n                            do {\n                                this.nextChar();\n                            } while ((this.ch == LexCodeSpace) || (this.ch == 9));\n                            var wsText = this.src.substring(this.startPos, this.pos);\n                            return new WhitespaceToken(TokenID.Whitespace, wsText);\n                        }\n                        else {\n                            this.interveningWhitespace = true;\n                        }\n                     // Newlines and BOM\n                    case 0xFF: // UTF16 SEQUENCE\n                    case 0xFE:\n                    case 0xEF:    // UTF8 SEQUENCE\n                    case 0xBB:\n                    case 0xBF:\n                    case LexCodeLS:\n                    case LexCodePS:\n                    case LexCodeNWL:\n                    case LexCodeRET:\n                        if (this.ch == LexCodeNWL) {\n                            this.newLine();\n                            if (this.mode == LexMode.Line) {\n                                return staticTokens[TokenID.EndOfFile];\n                            }\n                        }\n                        if (!this.interveningWhitespace) {\n                            this.interveningWhitespacePos = this.pos;\n                        }\n                        this.nextChar();\n                        this.tokenStart();\n                        this.interveningWhitespace = true;\n                        break;\n                    case LexCodeDOT: {\n                        if (this.peekCharAt(this.pos + 1) == LexCodeDOT) {\n                            if (this.peekCharAt(this.pos + 2) == LexCodeDOT) {\n                                this.advanceChar(3);\n                                return staticTokens[TokenID.DotDotDot];\n                            }\n                            else {\n                                this.nextChar();\n                                return staticTokens[TokenID.Dot];\n                            }\n                        }\n                        else {\n                            this.nextChar();\n                            rtok = this.scanFraction();\n                            if (rtok) {\n                                return rtok;\n                            }\n                            else {\n                                return staticTokens[TokenID.Dot];\n                            }\n                        }\n                        // break;\n                    }\n                    case LexCodeEQ:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            if (this.peekCharAt(this.pos + 2) == LexCodeEQ) {\n                                this.advanceChar(3);\n                                return staticTokens[TokenID.EqualsEqualsEquals];\n                            }\n                            else {\n                                this.advanceChar(2);\n                                return staticTokens[TokenID.EqualsEquals];\n                            }\n                        }\n                        else if (this.peekCharAt(this.pos + 1) == LexCodeGT) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.EqualsGreaterThan];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.Equals];\n                        }\n                    // break;\n                    case LexCodeBNG:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            if (this.peekCharAt(this.pos + 2) == LexCodeEQ) {\n                                this.advanceChar(3);\n                                return staticTokens[TokenID.ExclamationEqualsEquals];\n                            }\n                            else {\n                                this.advanceChar(2);\n                                return staticTokens[TokenID.ExclamationEquals];\n                            }\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.Exclamation];\n                        }\n                    // break;\n                    case LexCodePLS:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.PlusEquals];\n                        }\n                        else if (this.peekCharAt(this.pos + 1) == LexCodePLS) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.PlusPlus];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.Plus];\n                        }\n                    // break;\n                    case LexCodeMIN:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.MinusEquals];\n                        }\n                        else if (this.peekCharAt(this.pos + 1) == LexCodeMIN) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.MinusMinus];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.Minus];\n                        }\n                    // break;\n                    case LexCodeMUL:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.AsteriskEquals];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.Asterisk];\n                        }\n                    // break;\n                    case LexCodePCT:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.PercentEquals];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.Percent];\n                        }\n                    // break;\n                    case LexCodeLT:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeLT) {\n                            if (this.peekCharAt(this.pos + 2) == LexCodeEQ) {\n                                this.advanceChar(3);\n                                return staticTokens[TokenID.LessThanLessThanEquals];\n                            }\n                            else {\n                                this.advanceChar(2);\n                                return staticTokens[TokenID.LessThanLessThan];\n                            }\n                        }\n                        else if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.LessThanEquals];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.LessThan];\n                        }\n                    //  break;\n                    case LexCodeGT:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeGT) {\n                            if (this.peekCharAt(this.pos + 2) == LexCodeEQ) {\n                                this.advanceChar(3);\n                                return staticTokens[TokenID.GreaterThanGreaterThanEquals];\n                            }\n                            else if (this.peekCharAt(this.pos + 2) == LexCodeGT) {\n                                if (this.peekCharAt(this.pos + 3) == LexCodeEQ) {\n                                    this.advanceChar(4);\n                                    return staticTokens[TokenID.GreaterThanGreaterThanGreaterThanEquals];\n                                }\n                                else {\n                                    this.advanceChar(3);\n                                    return staticTokens[TokenID.GreaterThanGreaterThanGreaterThan];\n                                }\n                            }\n                            else {\n                                this.advanceChar(2);\n                                return staticTokens[TokenID.GreaterThanGreaterThan];\n                            }\n                        }\n                        else if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.GreaterThanEquals];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.GreaterThan];\n                        }\n                    // break;\n                    case LexCodeXOR:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.CaretEquals];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.Caret];\n                        }\n                    //  break;\n                    case LexCodeBAR:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.BarEquals];\n                        }\n                        else if (this.peekCharAt(this.pos + 1) == LexCodeBAR) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.BarBar];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.Bar];\n                        }\n                    //  break;\n                    case LexCodeAMP:\n                        if (this.peekCharAt(this.pos + 1) == LexCodeEQ) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.AmpersandEquals];\n                        }\n                        else if (this.peekCharAt(this.pos + 1) == LexCodeAMP) {\n                            this.advanceChar(2);\n                            return staticTokens[TokenID.AmpersandAmpersand];\n                        }\n                        else {\n                            this.nextChar();\n                            return staticTokens[TokenID.And];\n                        }\n                    //  break;\n                    default:\n                        // Report error\n                        this.reportScannerError(\"Invalid character\");\n                        this.nextChar();\n\n                        continue start;\n                }\n            }\n            return staticTokens[TokenID.EndOfFile];\n        }\n\n        private reportScannerError(message: string) { \n            if (this.reportError) { \n                this.reportError(message);\n            }\n        }\n    }\n\n    // Reseverved words only apply to Identifiers, not IdentifierNames\n    export function convertTokToIDName(tok: Token): bool {\n        return convertTokToIDBase(tok, true, false);\n    }\n\n    export function convertTokToID(tok: Token, strictMode: bool): bool {\n        return convertTokToIDBase(tok, false, strictMode);\n    }\n\n    function convertTokToIDBase(tok: Token, identifierName: bool, strictMode: bool): bool {\n        if (tok.tokenId <= TokenID.LimKeyword) {\n            var tokInfo = lookupToken(tok.tokenId);\n            if (tokInfo != undefined) {\n                var resFlags = Reservation.Javascript | Reservation.JavascriptFuture;\n                if (strictMode) {\n                    resFlags |= Reservation.JavascriptFutureStrict;\n                }\n                if (identifierName || !hasFlag(tokInfo.reservation, resFlags)) {\n                    return true;\n                }\n            }\n            else {\n                return false;\n            }\n        }\n        else {\n            return false;\n        }\n    }\n\n    // Return the (1-based) line number from a character offset using the provided linemap.\n    export function getLineNumberFromPosition(lineMap: number[], position: number): number {\n        if (position === -1)\n            return 0;\n\n        // Binary search\n        var min = 0;\n        var max = lineMap.length - 1;\n        while (min < max) {\n            var med = (min + max) >> 1;\n            if (position < lineMap[med]) {\n                max = med - 1;\n            }\n            else if (position < lineMap[med + 1]) {\n                min = max = med; // found it\n            }\n            else {\n                min = med + 1;\n            }\n        }\n\n        return min;\n    }\n\n    /// Return the [line, column] data for a given offset and a lineMap.\n    /// Note that the returned line is 1-based, while the column is 0-based.\n    export function getSourceLineColFromMap(lineCol: ILineCol, minChar: number, lineMap: number[]): void {\n        var line = getLineNumberFromPosition(lineMap, minChar);\n\n        if (line > 0) {\n            lineCol.line = line;\n            lineCol.col = (minChar - lineMap[line]);\n        }\n    }\n\n    // Return the [line, column] (both 1 based) corresponding to a given position in a given script.\n    export function getLineColumnFromPosition(script: TypeScript.Script, position: number): ILineCol {\n        var result = { line: -1, col: -1 };\n        getSourceLineColFromMap(result, position, script.locationInfo.lineMap);\n        if (result.col >= 0) {\n            result.col++;   // Make it 1-based\n        }\n        return result;\n    }\n\n    //\n    // Return the position (offset) corresponding to a given [line, column] (both 1-based) in a given script.\n    //\n    export function getPositionFromLineColumn(script: TypeScript.Script, line: number, column: number): number {\n        return script.locationInfo.lineMap[line] + (column - 1);\n    }\n    \n    // Return true if the token is a primitive type\n    export function isPrimitiveTypeToken(token: Token) {\n        switch (token.tokenId) {\n            case TokenID.Any:\n            case TokenID.Bool:\n            case TokenID.Number:\n            case TokenID.String:\n                return true;\n        }\n        return false;\n    }\n\n    // Return true if the token is a primitive type\n    export function isModifier(token: Token) {\n        switch (token.tokenId) {\n            case TokenID.Public:\n            case TokenID.Private:\n            case TokenID.Static:\n                return true;\n        }\n        return false;\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export class AssignScopeContext {\n        constructor (public scopeChain: ScopeChain,\n                     public typeFlow: TypeFlow,\n                     public modDeclChain: ModuleDeclaration[]) {\n        }\n    }\n\n    export function pushAssignScope(scope: SymbolScope,\n        context: AssignScopeContext,\n        type: Type,\n        classType: Type,\n        fnc: FuncDecl) {\n\n        var chain = new ScopeChain(null, context.scopeChain, scope);\n        chain.thisType = type;\n        chain.classType = classType;\n        chain.fnc = fnc;\n        context.scopeChain = chain;\n    }\n\n    export function popAssignScope(context: AssignScopeContext) {\n        context.scopeChain = context.scopeChain.previous;\n    }\n\n    export function instanceCompare(a: Symbol, b: Symbol) {\n        if (((a == null) || (!a.isInstanceProperty()))) {\n            return b;\n        }\n        else {\n            return a;\n        }\n    }\n\n    export function instanceFilterStop(s: Symbol) {\n        return s.isInstanceProperty();\n    }\n\n    export class ScopeSearchFilter {\n\n        constructor (public select: (a: Symbol, b: Symbol) =>Symbol,\n                            public stop: (s: Symbol) =>bool) { }\n\n        public result: Symbol = null;\n\n        public reset() {\n            this.result = null;\n        }\n\n        public update(b: Symbol): bool {\n            this.result = this.select(this.result, b);\n            if (this.result) {\n                return this.stop(this.result);\n            }\n            else {\n                return false;\n            }\n        }\n    }\n\n    export var instanceFilter = new ScopeSearchFilter(instanceCompare, instanceFilterStop);\n\n    export function preAssignModuleScopes(ast: AST, context: AssignScopeContext) {\n        var moduleDecl = <ModuleDeclaration>ast;\n        var memberScope: SymbolTableScope = null;\n        var aggScope: SymbolAggregateScope = null;\n\n        if (moduleDecl.name && moduleDecl.mod) {\n            moduleDecl.name.sym = moduleDecl.mod.symbol;\n        }\n\n        var mod = moduleDecl.mod;\n\n        // We're likely here because of error recovery\n        if (!mod) {\n            return;\n        }\n\n        memberScope = new SymbolTableScope(mod.members, mod.ambientMembers, mod.enclosedTypes, mod.ambientEnclosedTypes, mod.symbol);\n        mod.memberScope = memberScope;\n        context.modDeclChain.push(moduleDecl);\n        context.typeFlow.checker.currentModDecl = moduleDecl;\n        aggScope = new SymbolAggregateScope(mod.symbol);\n        aggScope.addParentScope(memberScope);\n        aggScope.addParentScope(context.scopeChain.scope);\n        pushAssignScope(aggScope, context, null, null, null);\n        mod.containedScope = aggScope;\n        if (mod.symbol) {\n            context.typeFlow.addLocalsFromScope(mod.containedScope, mod.symbol, moduleDecl.vars, mod.members.privateMembers, true);\n        }\n    }\n\n    export function preAssignClassScopes(ast: AST, context: AssignScopeContext) {\n        var classDecl = <InterfaceDeclaration>ast;\n        var memberScope: SymbolTableScope = null;\n        var aggScope: SymbolAggregateScope = null;\n\n        if (classDecl.name && classDecl.type) {\n            classDecl.name.sym = classDecl.type.symbol;\n        }\n\n        var classType = ast.type;\n\n        if (classType) {\n            var classSym = classType.symbol;\n            memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(classType);\n\n            aggScope = new SymbolAggregateScope(classType.symbol);\n            aggScope.addParentScope(memberScope);\n            aggScope.addParentScope(context.scopeChain.scope);\n\n            classType.containedScope = aggScope;\n            classType.memberScope = memberScope;\n\n            var instanceType = classType.instanceType;\n            memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(instanceType);\n            instanceType.memberScope = memberScope;\n\n            aggScope = new SymbolAggregateScope(instanceType.symbol);\n            aggScope.addParentScope(context.scopeChain.scope);\n\n            pushAssignScope(aggScope, context, instanceType, classType, null);\n            instanceType.containedScope = aggScope;\n        }\n        else {\n            ast.type = context.typeFlow.anyType;\n        }\n    }\n\n    export function preAssignInterfaceScopes(ast: AST, context: AssignScopeContext) {\n        var interfaceDecl = <InterfaceDeclaration>ast;\n        var memberScope: SymbolTableScope = null;\n        var aggScope: SymbolAggregateScope = null;\n\n        if (interfaceDecl.name && interfaceDecl.type) {\n            interfaceDecl.name.sym = interfaceDecl.type.symbol;\n        }\n\n        var interfaceType = ast.type;\n        memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(interfaceType);\n        interfaceType.memberScope = memberScope;\n        aggScope = new SymbolAggregateScope(interfaceType.symbol);\n        aggScope.addParentScope(memberScope);\n        aggScope.addParentScope(context.scopeChain.scope);\n        pushAssignScope(aggScope, context, null, null, null);\n        interfaceType.containedScope = aggScope;\n    }\n\n    export function preAssignWithScopes(ast: AST, context: AssignScopeContext) {\n        var withStmt = <WithStatement>ast;\n        var withType = withStmt.type;\n\n        var members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n        var ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n\n        var withType = new Type();\n        var withSymbol = new WithSymbol(withStmt.minChar, context.typeFlow.checker.locationInfo.unitIndex, withType);\n        withType.members = members;\n        withType.ambientMembers = ambientMembers;\n        withType.symbol = withSymbol;\n        withType.setHasImplementation();\n        withStmt.type = withType;\n\n        var withScope = new TypeScript.SymbolScopeBuilder(withType.members, withType.ambientMembers, null, null, context.scopeChain.scope, withType.symbol);\n\n        pushAssignScope(withScope, context, null, null, null);\n        withType.containedScope = withScope;\n    }\n\n    export function preAssignFuncDeclScopes(ast: AST, context: AssignScopeContext) {\n        var funcDecl = <FuncDecl>ast;\n\n        var container: Symbol = null;\n        var localContainer: Symbol = null;\n        if (funcDecl.type) {\n            localContainer = ast.type.symbol;\n        }\n\n        var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);\n        var isInnerStatic = isStatic && context.scopeChain.fnc != null;\n        // for inner static functions, use the parent's member scope, so local vars cannot be captured\n        var parentScope = isInnerStatic ? context.scopeChain.fnc.type.memberScope : context.scopeChain.scope;\n\n        // if this is not a method, but enclosed by class, use constructor as\n        // the enclosing scope\n        // REVIEW: Some twisted logic here - this needs to be cleaned up once old classes are removed\n        //  - if it's a new class, always use the contained scope, since we initialize the constructor scope below\n        if (context.scopeChain.thisType &&\n            (!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod))) {\n            var instType = context.scopeChain.thisType;\n\n            if (!(instType.typeFlags & TypeFlags.IsClass) && !hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n                if (!funcDecl.isMethod() || isStatic) {\n                    parentScope = instType.constructorScope;\n                }\n                else {\n                    // use constructor scope if a method as well\n                    parentScope = instType.containedScope;\n                }\n            }\n            else {\n                if (context.scopeChain.previous.scope.container &&\n                    context.scopeChain.previous.scope.container.declAST &&\n                    context.scopeChain.previous.scope.container.declAST.nodeType == NodeType.FuncDecl &&\n                    (<FuncDecl>context.scopeChain.previous.scope.container.declAST).isConstructor) {\n\n                        // if the parent is the class constructor, use the constructor scope\n                    parentScope = instType.constructorScope;\n                }\n                else if (isStatic && context.scopeChain.classType) {\n                    parentScope = context.scopeChain.classType.containedScope;\n                }\n                else {\n                    // else, use the contained scope\n                    parentScope = instType.containedScope;\n                }\n            }\n            container = instType.symbol;\n        }\n        else if (funcDecl.isConstructor && context.scopeChain.thisType) {\n            // sets the container to the class type's symbol (which is shared by the instance type)\n            container = context.scopeChain.thisType.symbol;\n        }\n\n        if (funcDecl.type == null || hasFlag(funcDecl.type.symbol.flags, SymbolFlags.TypeSetDuringScopeAssignment)) {\n            if (context.scopeChain.fnc && context.scopeChain.fnc.type) {\n                container = context.scopeChain.fnc.type.symbol;\n            }\n\n            var funcScope = null;\n            var outerFnc: FuncDecl = context.scopeChain.fnc;\n            var nameText = funcDecl.name ? funcDecl.name.actualText : null;\n            var fgSym: TypeSymbol = null;\n\n            if (isStatic) {\n                // In the case of function-nested statics, no member list will have bee initialized for the function, so we need\n                // to copy it over.  We don't set this by default because having a non-null member list will throw off assignment\n                // compatibility tests\n                if (outerFnc.type.members == null && container.getType().memberScope) {\n                    outerFnc.type.members = (<SymbolScopeBuilder>(<TypeSymbol>container).type.memberScope).valueMembers;\n                }\n                funcScope = context.scopeChain.fnc.type.memberScope;\n                outerFnc.innerStaticFuncs[outerFnc.innerStaticFuncs.length] = funcDecl;\n            }\n            else {\n                funcScope = context.scopeChain.scope;\n            }\n\n            // REVIEW: We don't search for another sym for accessors to prevent us from\n            // accidentally coalescing function signatures with the same name (E.g., a function\n            // 'f' the outer scope and a setter 'f' in an object literal within that scope)\n            if (nameText && nameText != \"__missing\" && !funcDecl.isAccessor()) {\n                if (isStatic) {\n                    fgSym = funcScope.findLocal(nameText, false, false);\n                }\n                else {\n                    // REVIEW: This logic should be symmetric with preCollectClassTypes\n                    fgSym = funcScope.findLocal(nameText, false, false);\n                }\n            }\n\n            context.typeFlow.checker.createFunctionSignature(funcDecl, container,\n                                                            funcScope, fgSym, fgSym == null);\n\n            // it's a getter or setter for a class property                     \n            if (!funcDecl.accessorSymbol && \n                (funcDecl.fncFlags & FncFlags.ClassMethod) &&\n                container && \n                ((!fgSym || fgSym.declAST.nodeType != NodeType.FuncDecl) && funcDecl.isAccessor()) || \n                    (fgSym && fgSym.isAccessor())) \n            {\n                funcDecl.accessorSymbol = context.typeFlow.checker.createAccessorSymbol(funcDecl, fgSym, container.getType(), (funcDecl.isMethod() && isStatic), true, funcScope, container);\n            }\n\n            funcDecl.type.symbol.flags |= SymbolFlags.TypeSetDuringScopeAssignment;\n        }\n\n        // Set the symbol for functions and their overloads\n        if (funcDecl.name && funcDecl.type) {\n            funcDecl.name.sym = funcDecl.type.symbol;\n        }\n\n        // Keep track of the original scope type, because target typing might override\n        // the \"type\" member. We need the original \"Scope type\" for completion list, etc.\n        funcDecl.scopeType = funcDecl.type;\n\n        // Overloads have no scope, so bail here\n        if (funcDecl.isOverload) {\n            return;\n        }\n\n        var funcTable = new StringHashTable();\n        var funcMembers = new ScopedMembers(new DualStringHashTable(funcTable, new StringHashTable()));\n        var ambientFuncTable = new StringHashTable();\n        var ambientFuncMembers = new ScopedMembers(new DualStringHashTable(ambientFuncTable, new StringHashTable()));\n        var funcStaticTable = new StringHashTable();\n        var funcStaticMembers = new ScopedMembers(new DualStringHashTable(funcStaticTable, new StringHashTable()));\n        var ambientFuncStaticTable = new StringHashTable();\n        var ambientFuncStaticMembers = new ScopedMembers(new DualStringHashTable(ambientFuncStaticTable, new StringHashTable()));\n\n        // REVIEW: Is it a problem that this is being set twice for properties and constructors?\n        funcDecl.unitIndex = context.typeFlow.checker.locationInfo.unitIndex;\n\n        var locals = new SymbolScopeBuilder(funcMembers, ambientFuncMembers, null, null, parentScope, localContainer);\n        var statics = new SymbolScopeBuilder(funcStaticMembers, ambientFuncStaticMembers, null, null, parentScope, null);\n\n        if (funcDecl.isConstructor && context.scopeChain.thisType) {\n            context.scopeChain.thisType.constructorScope = locals;\n        }\n\n        // basically, there are two problems\n        // - Above, for new classes, we were overwriting the constructor scope with the containing scope.  This caused constructor params to be\n        // in scope everywhere\n        // - Below, we're setting the contained scope table to the same table we were overwriting the constructor scope with, which we need to\n        // fish lambda params, etc, out (see funcTable below)\n        //\n        // A good first approach to solving this would be to change addLocalsFromScope to take a scope instead of a table, and add to the\n        // constructor scope as appropriate\n\n        funcDecl.symbols = funcTable;\n\n        if (!funcDecl.isSpecialFn()) {\n            var group = funcDecl.type;\n            var signature = funcDecl.signature;\n\n            if (!funcDecl.isConstructor) {\n                group.containedScope = locals;\n                locals.container = group.symbol;\n\n                group.memberScope = statics;\n                statics.container = group.symbol;\n            }\n            funcDecl.enclosingFnc = context.scopeChain.fnc;\n            group.enclosingType = isStatic ? context.scopeChain.classType : context.scopeChain.thisType;\n            // for mapping when type checking\n            var fgSym = <TypeSymbol>ast.type.symbol;\n            if (((funcDecl.fncFlags & FncFlags.Signature) == FncFlags.None) && funcDecl.vars) {\n                context.typeFlow.addLocalsFromScope(locals, fgSym, funcDecl.vars,\n                                                    funcTable, false);\n                context.typeFlow.addLocalsFromScope(statics, fgSym, funcDecl.statics,\n                                                    funcStaticTable, false);\n            }\n            if (signature.parameters) {\n                var len = signature.parameters.length;\n                for (var i = 0; i < len; i++) {\n                    var paramSym: ParameterSymbol = signature.parameters[i];\n                    context.typeFlow.checker.resolveTypeLink(locals,\n                                                                paramSym.parameter.typeLink, true);\n                }\n            }\n            context.typeFlow.checker.resolveTypeLink(locals, signature.returnType,\n                                                        funcDecl.isSignature());\n        }\n\n        if (!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n            var thisType = (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) ? context.scopeChain.thisType : null;\n            pushAssignScope(locals, context, thisType, null, funcDecl);\n        }\n\n        if (funcDecl.name && hasFlag(funcDecl.fncFlags, FncFlags.IsFunctionExpression)) {\n            // If the function is an expression, the name will not be visible in the enclosing scope.\n            // Add the function symbol under its name to the local scope to allow for recursive calls.\n            if (funcDecl.name.sym) {\n                funcTable.add(funcDecl.name.actualText, funcDecl.name.sym);\n            }\n        }\n    }\n\n    export function preAssignCatchScopes(ast: AST, context: AssignScopeContext) {\n        var catchBlock = <Catch>ast;\n        if (catchBlock.param) {\n            var catchTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable())); // REVIEW: Should we be allocating a public table instead of a private one?\n            var catchLocals = new SymbolScopeBuilder(catchTable, null, null, null, context.scopeChain.scope,\n                                                   context.scopeChain.scope.container);\n            catchBlock.containedScope = catchLocals;\n            pushAssignScope(catchLocals, context, context.scopeChain.thisType, context.scopeChain.classType, context.scopeChain.fnc);\n        }\n    }\n\n    export function preAssignScopes(ast: AST, parent: AST, walker: IAstWalker) {\n        var context:AssignScopeContext = walker.state;\n        var go = true;\n\n        if (ast) {\n            if (ast.nodeType == NodeType.List) {\n                var list = <ASTList>ast;\n                list.enclosingScope = context.scopeChain.scope;\n            }\n            else if (ast.nodeType == NodeType.ModuleDeclaration) {\n                preAssignModuleScopes(ast, context);\n            }\n            else if (ast.nodeType == NodeType.ClassDeclaration) {\n                preAssignClassScopes(ast, context);\n            }\n            else if (ast.nodeType == NodeType.InterfaceDeclaration) {\n                preAssignInterfaceScopes(ast, context);\n            }\n            else if (ast.nodeType == NodeType.With) {\n                preAssignWithScopes(ast, context);\n            }\n            else if (ast.nodeType == NodeType.FuncDecl) {\n                preAssignFuncDeclScopes(ast, context);\n            }\n            else if (ast.nodeType == NodeType.Catch) {\n                preAssignCatchScopes(ast, context);\n            }\n            else if (ast.nodeType == NodeType.TypeRef) {\n                go = false;\n            }\n        }\n        walker.options.goChildren = go;\n        return ast;\n    }\n\n    export function postAssignScopes(ast: AST, parent: AST, walker: IAstWalker) {\n        var context:AssignScopeContext = walker.state;\n        var go = true;\n        if (ast) {\n            if (ast.nodeType == NodeType.ModuleDeclaration) {\n                var prevModDecl = <ModuleDeclaration>ast;\n\n                popAssignScope(context);\n\n                context.modDeclChain.pop();\n                if (context.modDeclChain.length >= 1) {\n                    context.typeFlow.checker.currentModDecl = context.modDeclChain[context.modDeclChain.length - 1];\n                }\n            }\n            else if (ast.nodeType == NodeType.ClassDeclaration) {\n                popAssignScope(context);\n            }\n            else if (ast.nodeType == NodeType.InterfaceDeclaration) {\n                popAssignScope(context);\n            }\n            else if (ast.nodeType == NodeType.With) {\n                popAssignScope(context);\n            }\n            else if (ast.nodeType == NodeType.FuncDecl) {\n                var funcDecl = <FuncDecl>ast;\n                if ((!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) && !funcDecl.isOverload) {\n                    popAssignScope(context);\n                }\n            }\n            else if (ast.nodeType == NodeType.Catch) {\n                var catchBlock = <Catch>ast;\n                if (catchBlock.param) {\n                    popAssignScope(context);\n                }\n            }\n            else {\n                go = false;\n            }\n        }\n        walker.options.goChildren = go;\n        return ast;\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export class TypeCollectionContext {\n        public script: Script = null;\n\n        constructor (public scopeChain: ScopeChain, public checker: TypeChecker) {\n        }\n    }\n\n    export class MemberScopeContext {\n        public type: Type = null;\n        public ast: AST = null;\n        public scope: SymbolScope;\n        public options = new AstWalkOptions();\n\n        constructor (public flow: TypeFlow, public pos: number, public matchFlag: ASTFlags) {\n        }\n    }\n\n    export class EnclosingScopeContext {\n\n        public scopeGetter: () => SymbolScope = null;\n        public objectLiteralScopeGetter: () => SymbolScope = null;\n        public scopeStartAST: AST = null;\n        public skipNextFuncDeclForClass = false;\n        public deepestModuleDecl: ModuleDeclaration = null;\n        public enclosingClassDecl: TypeDeclaration = null;\n        public enclosingObjectLit: UnaryExpression = null;\n        public publicsOnly = true;\n        public useFullAst = false;\n        private scriptFragment: Script;\n\n        constructor (public logger: ILogger,\n                    public script: Script,\n                    public text: ISourceText,\n                    public pos: number,\n                    public isMemberCompletion: bool) {\n        }\n\n        public getScope(): SymbolScope {\n            return this.scopeGetter();\n        }\n\n        public getObjectLiteralScope(): SymbolScope {\n            return this.objectLiteralScopeGetter();\n        }\n\n        public getScopeAST() {\n            return this.scopeStartAST;\n        }\n\n        public getScopePosition() {\n            return this.scopeStartAST.minChar;\n        }\n\n        public getScriptFragmentStartAST(): AST {\n            return this.scopeStartAST;\n        }\n\n        public getScriptFragmentPosition(): number {\n            return this.getScriptFragmentStartAST().minChar;\n        }\n\n        public getScriptFragment(): Script {\n            if (this.scriptFragment == null) {\n                var ast = this.getScriptFragmentStartAST();\n                var minChar = ast.minChar;\n                var limChar = (this.isMemberCompletion ? this.pos : this.pos + 1);\n                this.scriptFragment = TypeScript.quickParse(this.logger, ast, this.text, minChar, limChar, null/*errorCapture*/).Script;\n            }\n            return this.scriptFragment;\n        }\n    }\n\n    export function preFindMemberScope(ast: AST, parent: AST, walker: IAstWalker) {\n        var memScope: MemberScopeContext = walker.state;\n        if (hasFlag(ast.flags, memScope.matchFlag) && ((memScope.pos < 0) || (memScope.pos == ast.limChar))) {\n            memScope.ast = ast;\n            if ((ast.type == null) && (memScope.pos >= 0)) {\n                memScope.flow.inScopeTypeCheck(ast, memScope.scope);\n            }\n            memScope.type = ast.type;\n            memScope.options.stopWalk();\n        }\n        return ast;\n    }\n\n    export function pushTypeCollectionScope(container: Symbol,\n        valueMembers: ScopedMembers,\n        ambientValueMembers: ScopedMembers,\n        enclosedTypes: ScopedMembers,\n        ambientEnclosedTypes: ScopedMembers,\n        context: TypeCollectionContext,\n        thisType: Type,\n        classType: Type,\n        moduleDecl: ModuleDeclaration) {\n        var builder = new SymbolScopeBuilder(valueMembers, ambientValueMembers, enclosedTypes, ambientEnclosedTypes, null, container);\n        var chain: ScopeChain = new ScopeChain(container, context.scopeChain, builder);\n        chain.thisType = thisType;\n        chain.classType = classType;\n        chain.moduleDecl = moduleDecl;\n        context.scopeChain = chain;\n    }\n\n    export function popTypeCollectionScope(context: TypeCollectionContext) {\n        context.scopeChain = context.scopeChain.previous;\n    }\n\n    export function preFindEnclosingScope(ast: AST, parent: AST, walker: IAstWalker) {\n        var context: EnclosingScopeContext = walker.state;\n        var minChar = ast.minChar;\n        var limChar = ast.limChar;\n\n        // Account for the fact completion list may be called at the end of a file which\n        // is has not been fully re-parsed yet.\n        if (ast.nodeType == NodeType.Script && context.pos > limChar)\n            limChar = context.pos;\n\n        if ((minChar <= context.pos) &&\n            (limChar >= context.pos)) {\n            switch (ast.nodeType) {\n                case NodeType.Script:\n                    var script = <Script>ast;\n                    context.scopeGetter = function () {\n                        return script.bod === null ? null : script.bod.enclosingScope;\n                    };\n                    context.scopeStartAST = script;\n                    break;\n\n                case NodeType.ClassDeclaration:\n                    context.scopeGetter = function () {\n                        return (ast.type === null || ast.type.instanceType.containedScope === null) ? null : ast.type.instanceType.containedScope;\n                    };\n                    context.scopeStartAST = ast;\n                    context.enclosingClassDecl = <TypeDeclaration>ast;\n                    break;\n\n                case NodeType.ObjectLit:\n                    var objectLit = <UnaryExpression>ast;\n                    // Only consider target-typed object literals\n                    if (objectLit.targetType) {\n                        context.scopeGetter = function () {\n                            return objectLit.targetType.containedScope;\n                        };\n                        context.objectLiteralScopeGetter = function () {\n                            return objectLit.targetType.memberScope;\n                        }\n                        context.enclosingObjectLit = objectLit;\n                    }\n                    break;\n\n                case NodeType.ModuleDeclaration:\n                    context.deepestModuleDecl = <ModuleDeclaration>ast;\n                    context.scopeGetter = function () {\n                        return ast.type === null ? null : ast.type.containedScope;\n                    };\n                    context.scopeStartAST = ast;\n                    break;\n\n                case NodeType.InterfaceDeclaration:\n                    context.scopeGetter = function () {\n                        return (ast.type === null) ? null : ast.type.containedScope;\n                    };\n                    context.scopeStartAST = ast;\n                    break;\n\n                case NodeType.FuncDecl: {\n                    var funcDecl = <FuncDecl>ast;\n                    if (context.skipNextFuncDeclForClass) {\n                        context.skipNextFuncDeclForClass = false;\n                    }\n                    else {\n                        context.scopeGetter = function () {\n                            // The scope of a class constructor is hidden somewhere we don't expect :-S\n                            if (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n                                if (ast.type && ast.type.enclosingType) {\n                                    return ast.type.enclosingType.constructorScope;\n                                }\n                            }\n\n                            if (funcDecl.scopeType) {\n                                return funcDecl.scopeType.containedScope;\n                            }\n\n                            if (funcDecl.type) {\n                                return funcDecl.type.containedScope;\n                            }\n                            return null;\n                        };\n                        context.scopeStartAST = ast;\n                    }\n                }\n                    break;\n            }\n            walker.options.goChildren = true;\n        }\n        else {\n            walker.options.goChildren = false;\n        }\n        return ast;\n    }\n\n    //\n    // Find the enclosing scope context from a position inside a script AST.\n    // The \"scopeStartAST\" of the returned scope is always valid.\n    // Return \"null\" if the enclosing scope can't be found.\n    //\n    export function findEnclosingScopeAt(logger: ILogger, script: Script, text: ISourceText, pos: number, isMemberCompletion: bool): EnclosingScopeContext {\n        var context = new EnclosingScopeContext(logger, script, text, pos, isMemberCompletion);\n\n        TypeScript.getAstWalkerFactory().walk(script, preFindEnclosingScope, null, null, context);\n\n        if (context.scopeStartAST === null)\n            return null;\n        return context;\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export class Signature {\n        public hasVariableArgList = false;\n        public returnType: TypeLink;\n        public parameters: ParameterSymbol[] = null;\n        public declAST: FuncDecl = null;\n        public typeCheckStatus = TypeCheckStatus.NotStarted;\n        public nonOptionalParameterCount = 0;\n\n        public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Signature {\n            var result = new Signature();\n            if (this.hasVariableArgList) {\n                result.hasVariableArgList = true;\n            }\n            result.returnType = new TypeLink();\n            if (this.returnType.type) {\n                result.returnType.type =\n                    this.returnType.type.specializeType(pattern, replacement, checker, false);\n            }\n            else {\n                result.returnType.type = checker.anyType;\n            }\n\n            if (this.parameters) {\n                result.parameters = [];\n                for (var i = 0, len = this.parameters.length; i < len; i++) {\n                    var oldSym:ParameterSymbol = this.parameters[i];\n                    var paramDef = new ValueLocation();\n                    var paramSym = new ParameterSymbol(oldSym.name, oldSym.location,\n                                                     checker.locationInfo.unitIndex,\n                                                     paramDef);\n\n                    paramSym.declAST = this.declAST;\n                    paramDef.symbol = paramSym;\n                    paramDef.typeLink = new TypeLink();\n                    result.parameters[i] = paramSym;\n                    var oldType = oldSym.getType();\n                    if (oldType) {\n                        paramDef.typeLink.type = oldType.specializeType(pattern, replacement, checker, false);\n                        paramSym.declAST.type = paramDef.typeLink.type;\n                    }\n                    else {\n                        paramDef.typeLink.type = checker.anyType;\n                    }\n                }\n            }\n            result.nonOptionalParameterCount = this.nonOptionalParameterCount;\n            result.declAST = this.declAST;\n\n            return result;\n        }\n\n        public toString() {\n            return this.toStringHelper(false, false, null);\n        }\n\n        public toStringHelper(shortform: bool, brackets: bool, scope: SymbolScope) {\n            return this.toStringHelperEx(shortform, brackets, scope).toString();\n        }\n\n        public toStringHelperEx(shortform: bool, brackets: bool, scope: SymbolScope, prefix? : string = \"\") : MemberName {\n            var builder = new MemberNameArray();\n            if (brackets) {\n                builder.prefix =  prefix + \"[\";\n            }\n            else {\n                builder.prefix = prefix + \"(\";\n            }\n\n            var paramLen = this.parameters.length;\n            var len = this.hasVariableArgList ? paramLen - 1 : paramLen;\n            for (var i = 0; i < len; i++) {\n                builder.add(MemberName.create(this.parameters[i].name + (this.parameters[i].isOptional() ? \"?\" : \"\") + \": \"));\n                builder.add(this.parameters[i].getType().getScopedTypeNameEx(scope));\n                if (i < paramLen - 1) {\n                    builder.add(MemberName.create(\", \"));\n                }\n            }\n\n            if (this.hasVariableArgList) {\n                builder.add(MemberName.create(\"...\" + this.parameters[i].name + \": \"));\n                builder.add(this.parameters[i].getType().getScopedTypeNameEx(scope));\n            }\n\n            if (shortform) {\n                if (brackets) {\n                    builder.add(MemberName.create(\"] => \"));\n                }\n                else {\n                    builder.add(MemberName.create(\") => \"));\n                }\n            }\n            else {\n                if (brackets) {\n                    builder.add(MemberName.create(\"]: \"));\n                }\n                else {\n                    builder.add(MemberName.create(\"): \"));\n                }\n            }\n\n            if (this.returnType.type) {\n                 builder.add(this.returnType.type.getScopedTypeNameEx(scope));\n            }\n            else {\n                builder.add(MemberName.create(\"any\"));\n            }\n            return builder;\n        }\n    }\n\n    export class SignatureGroup {\n        public signatures: Signature[] = [];\n        public hasImplementation = true;\n        public definitionSignature: Signature = null;\n        public hasBeenTypechecked = false;\n        public flags: SignatureFlags = SignatureFlags.None;\n        public addSignature(signature: Signature) {\n            if (this.signatures == null) {\n                this.signatures = new Signature[];\n            }\n            this.signatures[this.signatures.length] = signature;\n            \n            // REVIEW: duplicates should be found within createFunctionSignature,\n            // so we won't check for them here\n            if (signature.declAST &&\n                !signature.declAST.isOverload &&\n                !signature.declAST.isSignature() && \n                !hasFlag(signature.declAST.fncFlags, FncFlags.Ambient) &&\n                hasFlag(signature.declAST.fncFlags, FncFlags.Definition)) {\n                this.definitionSignature = signature;\n            }\n        }\n\n        public toString() { return this.signatures.toString(); }\n        public toStrings(prefix: string, shortform: bool, scope: SymbolScope) {\n            var result : MemberName[] = [];  \n            var len = this.signatures.length;\n            if (len > 1) {\n                shortform = false;\n            }\n            for (var i = 0; i < len; i++) {\n                // the definition signature shouldn't be printed if there are overloads\n                if (len > 1 && this.signatures[i] == this.definitionSignature) {\n                    continue;\n                }\n                if (this.flags & SignatureFlags.IsIndexer) {\n                    result.push(this.signatures[i].toStringHelperEx(shortform, true, scope));\n                }\n                else {\n                    result.push(this.signatures[i].toStringHelperEx(shortform, false, scope, prefix));\n                }\n            }\n            \n            return result;\n        }\n\n        public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): SignatureGroup {\n            var result = new SignatureGroup();\n            if (this.signatures) {\n                for (var i = 0, len = this.signatures.length; i < len; i++) {\n                    result.addSignature(this.signatures[i].specializeType(pattern, replacement, checker));\n                }\n            }\n            return result;\n        }\n\n        // verifies that signatures are\n        //  - unique within a given group\n        //  - compatible with the declaration signature\n        public verifySignatures(checker: TypeChecker) {\n\n            var len = 0;\n            \n            // TODO: verify no signature pair with identical parameters\n            if (this.signatures && ((len = this.signatures.length) > 0)) {\n                \n                for (var i = 0; i < len; i++) {\n                    \n                    for (var j = i + 1; j < len; j++) {\n                        // next check for equivalence between overloads - no two can be exactly the same                     \n                        if (this.signatures[i].declAST && this.signatures[j].declAST &&\n                            (!hasFlag(this.signatures[i].declAST.fncFlags, FncFlags.Definition) && !hasFlag(this.signatures[j].declAST.fncFlags, FncFlags.Definition)) &&\n                            checker.signaturesAreIdentical(this.signatures[i], this.signatures[j])) {\n                            checker.errorReporter.simpleError(this.signatures[i].declAST, (this.signatures[i].declAST && this.signatures[i].declAST.name) ? \"Signature for '\" + this.signatures[i].declAST.name.actualText + \"' is duplicated\" :\"Signature is duplicated\");\n                        }\n                    }\n                    \n                    // finally, ensure that the definition is assignable to each signature\n                    if (this.definitionSignature) {\n                        if (!checker.signatureIsAssignableToTarget(this.definitionSignature, this.signatures[i])) {\n                            checker.errorReporter.simpleError(this.signatures[i].declAST, \"Overload signature is not compatible with function definition\");\n                        }\n                    }\n                }\n            }\n        }\n\n        public typeCheck(checker: TypeChecker, ast: AST, hasConstruct:bool) {\n            \n            if (this.hasBeenTypechecked) {\n                return;\n            }\n            \n            // set here to prevent us from recursively invoking typeCheck again\n            this.hasBeenTypechecked = true;\n            \n            var len = 0;\n            \n            if (this.signatures && ((len = this.signatures.length) > 0)) {\n                \n                // first, typecheck each signature\n                for (var i = 0; i < len; i++) {\n\n                    if (!hasConstruct && !this.definitionSignature && this.signatures[i].declAST && this.signatures[i].declAST.isOverload && !hasFlag(this.signatures[i].declAST.fncFlags, FncFlags.Ambient)) {\n                        checker.errorReporter.simpleError(this.signatures[i].declAST, \"Overload declaration lacks definition\");\n                    }\n\n                    // If we're typechecking a constructor via one of its overloads, ensure that the outer class is typechecked, since we need to validate its inheritance properties\n                    // to properly check that 'super' is being used correctly\n                    if (this.signatures[i].declAST && this.signatures[i].declAST.isConstructor && this.signatures[i].declAST.classDecl && this.signatures[i].declAST.classDecl.type.symbol.typeCheckStatus == TypeCheckStatus.NotStarted) {\n                        checker.typeFlow.typeCheck(this.signatures[i].declAST.classDecl);\n                    }\n\n                    checker.typeFlow.typeCheck(this.signatures[i].declAST);\n                }\n\n                this.verifySignatures(checker);\n            }\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n///<reference path='..\\harness\\external\\json2.ts' />\n\nmodule TypeScript {\n    export class SourceMapPosition {\n        public sourceLine: number;\n        public sourceColumn: number;\n        public emittedLine: number;\n        public emittedColumn: number;\n    }\n\n    export class SourceMapping {\n        public start = new SourceMapPosition();\n        public end = new SourceMapPosition();\n        public nameIndex: number = -1;\n        public childMappings: SourceMapping[] = [];\n    }\n\n    export class SourceMapper {\n        static MapFileExtension = \".map\";\n        \n        public sourceMappings: SourceMapping[] = [];\n        public currentMappings: SourceMapping[][] = [];\n\n        public names: string[] = [];\n        public currentNameIndex: number[] = [];\n\n        public jsFileName: string;\n        public tsFileName: string;\n\n        constructor(tsFileName: string, jsFileName: string, public jsFile: ITextWriter, public sourceMapOut: ITextWriter, public errorReporter: ErrorReporter) {\n            this.currentMappings.push(this.sourceMappings);\n\n            jsFileName = switchToForwardSlashes(jsFileName);\n            this.jsFileName = TypeScript.getPrettyName(jsFileName, false, true);\n\n            var removalIndex = jsFileName.lastIndexOf(this.jsFileName);\n            var fixedPath = jsFileName.substring(0, removalIndex);\n\n            this.tsFileName = TypeScript.getRelativePathToFixedPath(fixedPath, tsFileName);\n        }\n        \n        // Generate source mapping\n        static EmitSourceMapping(allSourceMappers: SourceMapper[]) {\n            // At this point we know that there is at least one source mapper present.\n            // If there are multiple source mappers, all will correspond to same map file but different sources\n\n            // Output map file name into the js file\n            var sourceMapper = allSourceMappers[0];\n            sourceMapper.jsFile.WriteLine(\"//@ sourceMappingURL=\" + sourceMapper.jsFileName + SourceMapper.MapFileExtension);\n\n            // Now output map file\n            var sourceMapOut = sourceMapper.sourceMapOut;\n            var mappingsString = \"\";\n            var tsFiles: string[] = [];\n\n            var prevEmittedColumn = 0;\n            var prevEmittedLine = 0;\n            var prevSourceColumn = 0;\n            var prevSourceLine = 0;\n            var prevSourceIndex = 0;\n            var prevNameIndex = 0;\n            var namesList: string[] = [];\n            var namesCount = 0;\n            var emitComma = false;\n\n            var recordedPosition: SourceMapPosition = null;\n            for (var sourceMapperIndex = 0; sourceMapperIndex < allSourceMappers.length; sourceMapperIndex++) {\n                sourceMapper = allSourceMappers[sourceMapperIndex];\n\n                // If there are any mappings generated\n                var currentSourceIndex = tsFiles.length;\n                tsFiles.push(sourceMapper.tsFileName);\n\n                // Join namelist\n                if (sourceMapper.names.length > 0) {\n                    namesList.push.apply(namesList, sourceMapper.names);\n                }\n\n                var recordSourceMapping = (mappedPosition: SourceMapPosition, nameIndex: number) => {\n                    if (recordedPosition != null &&\n                        recordedPosition.emittedColumn == mappedPosition.emittedColumn &&\n                        recordedPosition.emittedLine == mappedPosition.emittedLine) {\n                        // This position is already recorded\n                        return;\n                    }\n\n                    // Record this position\n                    if (prevEmittedLine !== mappedPosition.emittedLine) {\n                        while (prevEmittedLine < mappedPosition.emittedLine) {\n                            prevEmittedColumn = 0;\n                            mappingsString = mappingsString + \";\";\n                            prevEmittedLine++;\n                        }\n                        emitComma = false;\n                    }\n                    else if (emitComma) {\n                        mappingsString = mappingsString + \",\";\n                    }\n\n                    // 1. Relative Column\n                    mappingsString = mappingsString + Base64VLQFormat.encode(mappedPosition.emittedColumn - prevEmittedColumn);\n                    prevEmittedColumn = mappedPosition.emittedColumn;\n\n                    // 2. Relative sourceIndex \n                    mappingsString = mappingsString + Base64VLQFormat.encode(currentSourceIndex - prevSourceIndex);\n                    prevSourceIndex = currentSourceIndex;\n\n                    // 3. Relative sourceLine 0 based\n                    mappingsString = mappingsString + Base64VLQFormat.encode(mappedPosition.sourceLine - 1 - prevSourceLine);\n                    prevSourceLine = mappedPosition.sourceLine - 1;\n\n                    // 4. Relative sourceColumn 0 based \n                    mappingsString = mappingsString + Base64VLQFormat.encode(mappedPosition.sourceColumn - prevSourceColumn);\n                    prevSourceColumn = mappedPosition.sourceColumn;\n\n                    // 5. Relative namePosition 0 based\n                    if (nameIndex >= 0) {\n                        mappingsString = mappingsString + Base64VLQFormat.encode(namesCount + nameIndex - prevNameIndex);\n                        prevNameIndex = namesCount + nameIndex;\n                    }\n\n                    emitComma = true;\n                    recordedPosition = mappedPosition;\n                }\n\n                // Record starting spans\n                var recordSourceMappingSiblings = (sourceMappings: SourceMapping[]) => {\n                    for (var i = 0; i < sourceMappings.length; i++) {\n                        var sourceMapping = sourceMappings[i];\n                        recordSourceMapping(sourceMapping.start, sourceMapping.nameIndex);\n                        recordSourceMappingSiblings(sourceMapping.childMappings);\n                        recordSourceMapping(sourceMapping.end, sourceMapping.nameIndex);\n                    }\n                }\n\n                recordSourceMappingSiblings(sourceMapper.sourceMappings, -1);\n                namesCount = namesCount + sourceMapper.names.length;\n            }\n\n            // Write the actual map file\n            if (mappingsString != \"\") {\n                sourceMapOut.Write(JSON2.stringify({\n                    version: 3,\n                    file: sourceMapper.jsFileName,\n                    sources: tsFiles,\n                    names: namesList,\n                    mappings: mappingsString\n                }));\n            }\n\n            // Done, close the file\n            try {\n                // Closing files could result in exceptions, report them if they occur\n                sourceMapOut.Close();\n            } catch (ex) {\n                sourceMapper.errorReporter.emitterError(null, ex.message);\n            }\n        }\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    // private members are private to the scope\n    // public members are public to the scope\n    export class ScopedMembers {\n\n        public allMembers: IHashTable;\n        public publicMembers: IHashTable;\n        public privateMembers: IHashTable;\n\n        constructor (public dualMembers: DualStringHashTable) { \n            this.allMembers = this.dualMembers;\n            this.publicMembers = this.dualMembers.primaryTable;\n            this.privateMembers = this.dualMembers.secondaryTable;\n        }\n\n        // add a public member\n        public addPublicMember(key: string, data) { return this.dualMembers.primaryTable.add(key, data); }\n\n        // add a private member \n        public addPrivateMember(key: string, data) { return this.dualMembers.secondaryTable.add(key, data); }\n    }\n\n    export enum SymbolKind {\n        None,\n        Type,\n        Field,\n        Parameter,\n        Variable,\n    }\n\n    export class SymbolScope {\n        constructor (public container: Symbol) { }\n        public printLabel() { return \"base\"; }\n        public getAllSymbolNames(members: bool): string[]{\n            return [\"please\", \"implement\", \"in\", \"derived\", \"classes\"];\n        }\n        public getAllTypeSymbolNames(members: bool): string[]{\n            return [\"please\", \"implement\", \"in\", \"derived\", \"classes\"];\n        }\n        public getAllValueSymbolNames(members: bool): string[]{\n            return [\"please\", \"implement\", \"in\", \"derived\", \"classes\"];\n        }\n        // advanced search using a filter\n        public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n        // find in this immediate scope\n        public findLocal(name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n        // find in value namespace \n        public find(name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n        // find symbol that supplies an implementation\n        public findImplementation(name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n        // restrict the search to ambient values\n        public findAmbient(name: string, publicOnly: bool, typespace: bool): Symbol { return null; }\n        public print(outfile: ITextWriter) {\n            if (this.container) {\n                outfile.WriteLine(this.printLabel() + \" scope with container: \" + this.container.name + \"...\");\n            }\n            else {\n                outfile.WriteLine(this.printLabel() + \" scope...\");\n            }\n        }\n\n        public enter(container: Symbol, ast: AST, symbol: Symbol, errorReporter: ErrorReporter, publicOnly: bool,\n            typespace: bool, ambient: bool): void {\n            throw new Error(\"please implement in derived class\");\n        }\n\n        public getTable(): IHashTable {\n            throw new Error(\"please implement in derived class\");\n        }\n    }\n\n    function symbolCanBeUsed(sym: Symbol, publicOnly) {\n        return publicOnly ? !(hasFlag(sym.flags, SymbolFlags.Private) ||\n                            (sym.declAST && sym.declAST.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>sym.declAST).fncFlags, FncFlags.Private)))\n                          : true;\n    }\n\n    export class SymbolAggregateScope extends SymbolScope {\n        public printLabel() { return \"agg\"; }\n        public valueCache: IHashTable = null;\n        public valueImplCache: IHashTable = null;\n        public valueAmbientCache: IHashTable = null;\n        public typeCache: IHashTable = null;\n        public typeImplCache: IHashTable = null;\n        public typeAmbientCache: IHashTable = null;\n        public parents: SymbolScope[] = null;\n        public container: Symbol;\n\n        constructor (container: Symbol) {\n            super(container);\n            this.container = container;\n        }\n\n        public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool) {\n            if (this.parents) {\n                for (var i = 0; i < this.parents.length; i++) {\n                    var sym = this.parents[i].search(filter, name, publicOnly, typespace);\n                    if (sym) {\n                        if (filter.update(sym)) {\n                            return sym;\n                        }\n                    }\n                }\n            }\n            return filter.result;\n        }\n\n        public getAllSymbolNames(members: bool): string[]{\n            var result: string[] = [];\n            if (this.parents) {\n                for (var i = 0; i < this.parents.length; i++) {\n                    var parentResult = this.parents[i].getAllSymbolNames(members);\n                    if (parentResult) {\n                        result = result.concat(parentResult);\n                    }\n                }\n            }\n            return result;\n        }\n\n        public getAllTypeSymbolNames(members: bool): string[]{\n            var result: string[] = [];\n            if (this.parents) {\n                for (var i = 0; i < this.parents.length; i++) {\n                    var parentResult = this.parents[i].getAllTypeSymbolNames(members);\n                    if (parentResult) {\n                        result = result.concat(parentResult);\n                    }\n                }\n            }\n            return result;\n        }\n\n        public getAllValueSymbolNames(members: bool): string[]{\n            var result: string[] = [];\n            if (this.parents) {\n                for (var i = 0; i < this.parents.length; i++) {\n                    var parentResult = this.parents[i].getAllValueSymbolNames(members);\n                    if (parentResult) {\n                        result = result.concat(parentResult);\n                    }\n                }\n            }\n            return result;\n        }\n\n        public print(outfile: ITextWriter) {\n            super.print(outfile);\n            if (this.parents) {\n                for (var i = 0; i < this.parents.length; i++) {\n                    this.parents[i].print(outfile);\n                }\n            }\n        }\n\n        public findImplementation(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym: Symbol = null;\n            var i = 0;\n            var implCache = this.valueImplCache;\n\n            if (typespace) {\n                implCache = this.typeImplCache;\n            }\n            if (implCache &&\n                ((sym = implCache.lookup(name)) != null) &&\n                (publicOnly ? !(hasFlag(sym.flags, SymbolFlags.Private) ||\n                                        (sym.declAST && sym.declAST.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>sym.declAST).fncFlags, FncFlags.Private)))\n                                        : true)) {\n                return sym;\n            }\n            if (this.parents) {\n                for (i = 0; i < this.parents.length; i++) {\n                    sym = this.parents[i].findImplementation(name, publicOnly, typespace);\n                    if (sym) {\n                        break;\n                    }\n                }\n            }\n            if (implCache) {\n                if (typespace) {\n                    this.typeImplCache = new StringHashTable();\n                    implCache = this.typeImplCache;\n                }\n                else {\n                    this.valueImplCache = new StringHashTable();\n                    implCache = this.valueImplCache;\n                }\n            }\n            implCache.add(name, sym);\n            return sym;\n        }\n\n        public find(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym: Symbol = null;\n            var i = 0;\n            var cache = this.valueCache;\n\n            if (typespace) {\n                cache = this.typeCache;\n            }\n            if (cache &&\n                ((sym = cache.lookup(name)) != null) &&\n                (publicOnly ? !(hasFlag(sym.flags, SymbolFlags.Private) ||\n                                        (sym.declAST && sym.declAST.nodeType == NodeType.FuncDecl && hasFlag((<FuncDecl>sym.declAST).fncFlags, FncFlags.Private)))\n                                        : true)) {\n                return sym;\n            }\n            if (this.parents) {\n                for (i = 0; i < this.parents.length; i++) {\n                    sym = this.parents[i].find(name, publicOnly, typespace);\n                    if (sym) {\n                        break;\n                    }\n                }\n            }\n            if (cache == null) {\n                if (typespace) {\n                    this.typeCache = new StringHashTable();\n                    cache = this.typeCache;\n                }\n                else {\n                    this.valueCache = new StringHashTable();\n                    cache = this.valueCache;\n                }\n            }\n            cache.add(name, sym);\n            return sym;\n        }\n\n        public findAmbient(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym: Symbol = null;\n            var i = 0;\n            var cache = this.valueAmbientCache;\n            if (typespace) {\n                cache = this.typeAmbientCache;\n            }\n            if (cache && ((sym = cache.lookup(name)) != null)) {\n                return sym;\n            }\n            if (this.parents) {\n                for (i = 0; i < this.parents.length; i++) {\n                    sym = this.parents[i].findAmbient(name, publicOnly, typespace);\n                    if (sym) {\n                        break;\n                    }\n                }\n            }\n            if (cache == null) {\n                if (typespace) {\n                    this.typeAmbientCache = new StringHashTable();\n                    cache = this.typeAmbientCache;\n                }\n                else {\n                    this.valueAmbientCache = new StringHashTable();\n                    cache = this.valueAmbientCache;\n                }\n            }\n            cache.add(name, sym);\n            return sym;\n        }\n\n        public addParentScope(parent: SymbolScope): void {\n            if (this.parents == null) {\n                this.parents = new SymbolScope[];\n            }\n            this.parents[this.parents.length] = parent;\n        }\n    }\n\n    export class SymbolTableScope extends SymbolScope {\n        public container: Symbol;\n\n        constructor(public valueMembers: ScopedMembers,\n                            public ambientValueMembers: ScopedMembers,\n                            public enclosedTypes: ScopedMembers,\n                            public ambientEnclosedTypes: ScopedMembers,\n                            container: Symbol)\n        {\n            super(container);\n            this.container = container;\n        }\n\n        public printLabel() { return \"table\"; }\n\n        public getAllSymbolNames(members: bool): string[]{\n            var result = this.getAllTypeSymbolNames(members);\n\n            return result.concat(this.getAllValueSymbolNames(members));\n        }\n\n        public getAllTypeSymbolNames(members: bool): string[]{\n            var result = [];\n            if (this.ambientEnclosedTypes) {\n                result = result.concat(this.ambientEnclosedTypes.allMembers.getAllKeys());\n            }\n            if (this.enclosedTypes) {\n                result = result.concat(this.enclosedTypes.allMembers.getAllKeys());\n            }\n            return result;\n        }\n\n        public getAllValueSymbolNames(members: bool): string[]{\n            var result = [];\n            if (this.ambientValueMembers) {\n                result = result.concat(this.ambientValueMembers.allMembers.getAllKeys());\n            }\n            if (this.valueMembers) {\n                result = result.concat(this.valueMembers.allMembers.getAllKeys());\n            }\n            return result;\n        }\n\n        public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool) {\n            var sym = this.find(name, publicOnly, typespace);\n            filter.update(sym);\n            return filter.result;\n        }\n\n        public find(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var table: IHashTable = null;\n            var ambientTable: IHashTable = null;\n\n            if (typespace) {\n                table = (this.enclosedTypes == null) ? null :\n                            publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;\n                ambientTable = (this.ambientEnclosedTypes == null) ? null :\n                                    publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n            }\n            else {\n                table = (this.valueMembers == null) ? null :\n                                publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;\n                ambientTable = (this.ambientValueMembers == null) ? null :\n                                    publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n            }\n            if (ambientTable) {\n                var s = ambientTable.lookup(name);\n                if (s) { return s; }\n            }\n            if (table) {\n                var s = table.lookup(name);\n                if (s) { return s; }\n            }\n\n            return null;\n        }\n\n        public findAmbient(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var ambientTable = (this.ambientValueMembers == null) ? null :\n                                publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n            if (typespace) {\n                ambientTable = (this.ambientEnclosedTypes == null) ? null :\n                                    publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n            }\n            if (ambientTable) {\n                var s = ambientTable.lookup(name);\n                if (s) { return s; }\n            }\n\n            return null;\n        }\n\n        public print(outfile: ITextWriter) {\n            super.print(outfile);\n            if (this.ambientValueMembers) {\n                this.ambientValueMembers.allMembers.map(function (key, sym, context) {\n                    outfile.WriteLine(\"  \" + key);\n                }, null);\n            }\n            if (this.valueMembers) {\n                this.valueMembers.allMembers.map(function (key, sym, context) {\n                    outfile.WriteLine(\"  \" + key);\n                }, null);\n            }\n            if (this.ambientEnclosedTypes) {\n                this.ambientEnclosedTypes.allMembers.map(function (key, sym, context) {\n                    outfile.WriteLine(\"  \" + key);\n                }, null);\n            }\n            if (this.enclosedTypes) {\n                this.enclosedTypes.allMembers.map(function (key, sym, context) {\n                    outfile.WriteLine(\"  \" + key);\n                }, null);\n            }\n        }\n\n        public findImplementation(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym = this.find(name, publicOnly, typespace);\n            if (sym) {\n                if (sym.kind() == SymbolKind.Type) {\n                    var typeSym = <TypeSymbol>sym;\n                    if (!typeSym.type.hasImplementation()) {\n                        sym = null;\n                    }\n                }\n                else if (sym.container) {\n                    if (sym.container.kind() == SymbolKind.Type) {\n                        var ctypeSym = <TypeSymbol>sym.container;\n                        if (!ctypeSym.type.hasImplementation()) {\n                            sym = null;\n                        }\n                    }\n                }\n            }\n            return sym;\n        }\n\n        public getTable() {\n            return this.valueMembers.publicMembers;\n        }\n    }\n\n    export class SymbolScopeBuilder extends SymbolScope {\n        public container: Symbol;\n        \n        constructor (public valueMembers: ScopedMembers,\n                    public ambientValueMembers: ScopedMembers,\n                    public enclosedTypes: ScopedMembers,\n                    public ambientEnclosedTypes: ScopedMembers,\n                    public parent: SymbolScope,\n                    container: Symbol)\n        {\n            super(container);\n            this.container = container;\n        }\n\n        public printLabel() { return \"builder\"; }\n        public getAllSymbolNames(members: bool): string[]{\n            var result: string[] = this.getAllTypeSymbolNames(members);\n            return result.concat(this.getAllValueSymbolNames(members));\n        }\n\n        public getAllTypeSymbolNames(members: bool): string[]{\n            var result: string[] = [];\n            if (this.ambientEnclosedTypes) {\n                result = result.concat(this.ambientEnclosedTypes.allMembers.getAllKeys());\n            }\n            if (this.enclosedTypes) {\n                result = result.concat(this.enclosedTypes.allMembers.getAllKeys());\n            }\n            if (!members && this.parent) {\n                var parentResult = this.parent.getAllTypeSymbolNames(members);\n                if (parentResult) {\n                    result = result.concat(parentResult);\n                }\n            }\n            return result;\n        }\n\n        public getAllValueSymbolNames(members: bool): string[]{\n            var result: string[] = [];\n            if (this.ambientValueMembers) {\n                result = result.concat(this.ambientValueMembers.allMembers.getAllKeys());\n            }\n            if (this.valueMembers) {\n                result = result.concat(this.valueMembers.allMembers.getAllKeys());\n            }\n            if (!members && this.parent) {\n                var parentResult = this.parent.getAllValueSymbolNames(members);\n                if (parentResult) {\n                    result = result.concat(parentResult);\n                }\n            }\n            return result;\n        }\n\n        public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool) {\n            var sym: Symbol = null;\n            var table = (this.valueMembers == null) ? null :\n                            publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;\n            var ambientTable = (this.ambientValueMembers == null) ? null :\n                                publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n            if (typespace) {\n                table = (this.enclosedTypes == null) ? null :\n                            publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;\n                ambientTable = (this.ambientEnclosedTypes == null) ? null :\n                                    publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n            }\n            if (ambientTable) {\n                if ((sym = ambientTable.lookup(name)) != null) {\n                    if (filter.update(sym)) {\n                        return sym;\n                    }\n                }\n            }\n            if (table) {\n                if ((sym = table.lookup(name)) != null) {\n                    if (filter.update(sym)) {\n                        return sym;\n                    }\n                }\n            }\n            if (this.parent) {\n                sym = this.parent.search(filter, name, publicOnly, typespace);\n                if (sym) {\n                    if (filter.update(sym)) {\n                        return sym;\n                    }\n                }\n            }\n            return filter.result;\n        }\n\n        public print(outfile: ITextWriter) {\n            super.print(outfile);\n            if (this.ambientValueMembers) {\n                this.ambientValueMembers.allMembers.map(function (key, s, context) {\n                    var sym = <Symbol>s;\n                    outfile.WriteLine(\"  \" + key);\n                }, null);\n            }\n            if (this.valueMembers) {\n                this.valueMembers.allMembers.map(function (key, s, context) {\n                    var sym = <Symbol>s;\n                    outfile.WriteLine(\"  \" + key);\n                }, null);\n            }\n            if (this.ambientEnclosedTypes) {\n                this.ambientEnclosedTypes.allMembers.map(function (key, s, context) {\n                    var sym = <Symbol>s;\n                    outfile.WriteLine(\"  \" + key);\n                }, null);\n            }\n            if (this.enclosedTypes) {\n                this.enclosedTypes.allMembers.map(function (key, s, context) {\n                    var sym = <Symbol>s;\n                    outfile.WriteLine(\"  \" + key);\n                }, null);\n            }\n            if (this.parent) {\n                this.parent.print(outfile);\n            }\n        }\n\n        public find(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym: Symbol = null;\n            var table = (this.valueMembers == null) ? null :\n                            publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;\n            var ambientTable = (this.ambientValueMembers == null) ? null :\n                                publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n            if (typespace) {\n                table = (this.enclosedTypes == null) ? null :\n                            publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;\n                ambientTable = (this.ambientEnclosedTypes == null) ? null :\n                                    publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n            }\n            if (ambientTable && ((sym = ambientTable.lookup(name)) != null)) {\n                return sym;\n            }\n            if (table && ((sym = table.lookup(name)) != null)) {\n                return sym;\n            }\n            if (this.parent) {\n                return this.parent.find(name, publicOnly, typespace);\n            }\n            return null;\n        }\n\n        public findAmbient(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym: Symbol = null;\n            var ambientTable = (this.ambientValueMembers == null) ? null :\n                                publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n            if (typespace) {\n                ambientTable = (this.ambientEnclosedTypes == null) ? null :\n                                    publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n            }\n            if (ambientTable && ((sym = ambientTable.lookup(name)) != null)) {\n                return sym;\n            }\n            if (this.parent) {\n                return this.parent.findAmbient(name, publicOnly, typespace);\n            }\n            return null;\n        }\n\n        public findLocal(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym: Symbol = null;\n            var table = (this.valueMembers == null) ? null :\n                            publicOnly ? this.valueMembers.publicMembers : this.valueMembers.allMembers;\n            var ambientTable = (this.ambientValueMembers == null) ? null :\n                                publicOnly ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.allMembers;\n            if (typespace) {\n                table = (this.enclosedTypes == null) ? null :\n                            publicOnly ? this.enclosedTypes.publicMembers : this.enclosedTypes.allMembers;\n                ambientTable = (this.ambientEnclosedTypes == null) ? null :\n                                    publicOnly ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.allMembers;\n            }\n            if (table) {\n                if ((sym = table.lookup(name)) != null) {\n                    if (sym) { return sym; }\n                }\n            }\n            if (ambientTable) {\n                if ((sym = ambientTable.lookup(name)) != null) {\n                    if (sym) { return sym; }\n                }\n            }\n            return null;\n        }\n\n        public enter(container: Symbol, ast: AST, symbol: Symbol, errorReporter: ErrorReporter, insertAsPublic: bool, typespace: bool, ambient: bool): void {\n            var table = null;\n\n            if (ambient) {\n                if (typespace) {\n                    table = (this.ambientEnclosedTypes == null) ? null :\n                                    insertAsPublic ? this.ambientEnclosedTypes.publicMembers : this.ambientEnclosedTypes.privateMembers;\n                }\n                else {\n                    table = (this.ambientValueMembers == null) ? null :\n                                insertAsPublic ? this.ambientValueMembers.publicMembers : this.ambientValueMembers.privateMembers;\n                }\n            }\n            else {\n                if (typespace) {\n                    table = (this.enclosedTypes == null) ? null :\n                                insertAsPublic ? this.enclosedTypes.publicMembers : this.enclosedTypes.privateMembers;\n                }\n                else {\n                    table = (this.valueMembers == null) ? null :\n                                insertAsPublic ? this.valueMembers.publicMembers : this.valueMembers.privateMembers;\n                }\n            }\n\n            if (table) {\n                if (!table.add(symbol.name, symbol)) {\n                    errorReporter.duplicateIdentifier(ast, symbol.name);\n                }\n            }\n            else {\n                CompilerDiagnostics.Alert(\"YYYYY\");  // REVIEW: Surely we can do better than this...\n            }\n            symbol.container = container;\n        }\n\n        public getTable() { return this.valueMembers.allMembers; }\n    }\n\n    export class FilteredSymbolScope extends SymbolScope {\n        constructor (public scope: SymbolScope, container: Symbol, public filter: ScopeSearchFilter) {\n            super(container);\n        }\n        public print(outfile: ITextWriter) {\n            this.scope.print(outfile);\n        }\n\n        public find(name: string, publicOnly: bool, typespace: bool) {\n            this.filter.reset();\n            return this.scope.search(this.filter, name, publicOnly, typespace);\n        }\n        public findLocal(name: string, publicOnly: bool, typespace: bool) { return this.scope.findLocal(name, publicOnly, typespace); }\n    }\n\n    export class FilteredSymbolScopeBuilder extends SymbolScopeBuilder {\n        constructor (valueMembers: ScopedMembers, parent: SymbolScope, container: Symbol, public filter: (sym: Symbol) =>bool) {\n            super(valueMembers, null, null, null, parent, container);\n        }\n        public findLocal(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym = super.findLocal(name, publicOnly, typespace);\n            if (sym) {\n                if (!this.filter(sym)) {\n                    return null;\n                }\n            }\n            return sym;\n        }\n\n        public search(filter: ScopeSearchFilter, name: string, publicOnly: bool, typespace: bool):Symbol {\n            throw new Error(\"please implement\");\n        }\n\n        public find(name: string, publicOnly: bool, typespace: bool): Symbol {\n            var sym = super.findLocal(name, publicOnly, typespace);\n            if (sym) {\n                if (!this.filter(sym)) {\n                    return null;\n                }\n            }\n            return super.find(name, publicOnly, typespace);\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export enum TypeCheckStatus {\n        NotStarted,\n        Started,\n        Finished,\n    }\n\n    // For lexically-scoped constructs\n    export function aLexicallyEnclosesB(a: Symbol, b: Symbol) {\n        if (a.declAST && b && b.declAST && a.declAST.nodeType == NodeType.FuncDecl) {\n            return a.declAST.minChar <= b.declAST.minChar && a.declAST.limChar >= b.declAST.limChar;\n        }\n        else {\n            return false;\n        }\n    }\n\n    export function aEnclosesB(a: Symbol, b: Symbol) {\n        while (a.container) {\n            if (a == b || aLexicallyEnclosesB(a.container, b)) {\n                return true;\n            }\n            a = a.container;\n        }\n        return false;\n    }\n\n    export interface PhasedTypecheckObject {\n        typeCheckStatus: TypeCheckStatus;\n    }\n\n    export class Symbol {\n        public bound = false;\n        public container: Symbol;\n        public instanceScope(): SymbolScope { return null; }\n        public isVariable() { return false; }\n        public isMember() { return false; }\n        public isInferenceSymbol() { return false; }\n        public isWith() { return false; }\n        public writeable() { return false; }\n        public isType(): bool { return false; }\n        public getType(): Type { return null; }\n        public flags: SymbolFlags = SymbolFlags.None;\n        public refs: Identifier[];\n        public isAccessor() { return false; }\n        public isObjectLitField = false;\n\n        public declAST: AST = null;\n        public declModule: ModuleDeclaration = null;  // if child of module, this is the module that declared it\n\n        public passSymbolCreated: number = CompilerDiagnostics.analysisPass;\n\n        constructor(public name: string, public location: number, public length: number,\n                 public unitIndex: number) { }\n\n        public isInstanceProperty() {\n            return hasFlag(this.flags, SymbolFlags.Property) && (!hasFlag(this.flags, SymbolFlags.ModuleMember));\n        }\n\n        public getTypeName(scope: SymbolScope): string {\n            return this.getTypeNameEx(scope).toString();\n        }\n        \n        public getTypeNameEx(scope: SymbolScope): MemberName {\n            return MemberName.create(this.toString());\n        }\n\n        public getOptionalNameString() {\n            return hasFlag(this.flags, SymbolFlags.Optional) ? \"?\" : \"\";\n        }\n\n        public pathToRoot() {\n            var path = new Symbol[];\n            var node = this;\n            while (node && (node.name != globalId)) {\n                path[path.length] = node;\n                node = node.container;\n            }\n            return path;\n        }\n\n        public findCommonAncestorPath(b: Symbol) {\n            if (this.container == null) {\n                return new Symbol[];\n            }\n            var aPath = this.container.pathToRoot();\n            var bPath: Symbol[];\n            if (b) {\n                bPath = b.pathToRoot();\n            }\n            else {\n                bPath = new Symbol[];\n            }\n            var commonNodeIndex = -1;\n            for (var i = 0, aLen = aPath.length; i < aLen; i++) {\n                var aNode = aPath[i];\n                for (var j = 0, bLen = bPath.length; j < bLen; j++) {\n                    var bNode = bPath[j];\n                    if (aNode == bNode) {\n                        commonNodeIndex = i;\n                        break;\n                    }\n                }\n                if (commonNodeIndex >= 0) {\n                    break;\n                }\n            }\n            if (commonNodeIndex >= 0) {\n                return aPath.slice(0, commonNodeIndex);\n            }\n            else {\n                return aPath;\n            }\n        }\n\n        // Gets the pretty Name for the symbol withing the scope\n        public getPrettyName(scopeSymbol: Symbol) {\n            return this.name;\n        }\n\n        public scopeRelativeName(scope: SymbolScope): string {\n            if (scope == null) {\n                return this.getPrettyName(null) + this.getOptionalNameString();\n            }\n            var lca = this.findCommonAncestorPath(scope.container);\n            var builder = \"\";\n            for (var i = 0, len = lca.length; i < len; i++) {\n                var prettyName = lca[i].getPrettyName(i == len - 1 ? scope.container : lca[i + 1]);\n                builder = prettyName + \".\" + builder;\n            }\n            builder += this.getPrettyName(len == 0 ? scope.container : lca[0]) + this.getOptionalNameString();\n            return builder;\n        }\n\n        public fullName(): string {\n            var builder = this.name;\n            var ancestor = this.container;\n            while (ancestor && (ancestor.name != globalId)) {\n                builder = ancestor.name + \".\" + builder;\n                ancestor = ancestor.container;\n            }\n            return builder;\n        }\n\n        public isExternallyVisible(checker: TypeChecker) {\n            // Global module is not hidden\n            if (this == checker.gloMod) {\n                return true;\n            }\n\n            // private symbol\n            if (hasFlag(this.flags, SymbolFlags.Private)) {\n                return false;\n            }\n\n            // If the current container is not exported\n            // If its in global - it is visible, otherwise it isn't\n            if (!hasFlag(this.flags, SymbolFlags.Exported)) {\n                return this.container == checker.gloMod;\n            }\n\n            // It is visible if its container is visible too\n            return this.container.isExternallyVisible(checker);\n        }\n\n        public visible(scope: SymbolScope, checker: TypeChecker) {\n            if (checker == null || this.container == checker.gloMod) {\n                return true;\n            }\n\n            if (hasFlag(this.flags, SymbolFlags.ModuleMember)) {\n\n                if (hasFlag(this.flags, SymbolFlags.Exported)) {\n                    if (!hasFlag(this.flags, SymbolFlags.Private)) {\n                        return true;\n                    }\n                    else {\n                        return aEnclosesB(this, scope.container);\n                    }\n                }\n                else {\n                    // REVIEW:\n                    // Note that in the scope-assignment and binding phases,\n                    // currentModDecl will point to the \"master\" module decl,\n                    // and not necessarily the one that the symbol in question\n                    // was declared in.\n                    // That's ok - there's no harm done in attributing the symbol\n                    // to the master mod decl in either of those phases, so long\n                    // as we reference the actual module fragment of declaration\n                    // during typecheck.  Doing this also prevents us from printing\n                    // multiple error messages if the symbol is not visible.\n                    return checker && (checker.currentModDecl == this.declModule) ||\n                                                (checker.currentModDecl &&\n                                                    checker.currentModDecl.mod &&\n                                                    checker.currentModDecl.mod.symbol &&\n                                                    this.declModule &&\n                                                    this.declModule.mod &&\n                                                    this.declModule.mod.symbol &&\n                                                    aEnclosesB(checker.currentModDecl.mod.symbol, this.declModule.mod.symbol));\n                }\n            }\n            else {\n                // field or method\n                var isFunction = this.declAST && this.declAST.nodeType == NodeType.FuncDecl;\n                var isMethod = isFunction && (<FuncDecl>this.declAST).isMethod();\n                var isStaticFunction = isFunction && hasFlag((<FuncDecl>this.declAST).fncFlags, FncFlags.Static)\n                var isPrivateMethod = isMethod && hasFlag((<FuncDecl>this.declAST).fncFlags, FncFlags.Private);\n                var isAlias = this.isType() && (<TypeSymbol>this).aliasLink;\n\n                if (this.isMember() || isMethod || isStaticFunction || isAlias) {\n                    if (hasFlag(this.flags, SymbolFlags.Private) || isPrivateMethod) {\n                        if (scope.container == null && this.container != scope.container) {\n                            return false; // it's an inner member being accessed by the global scope\n                        }\n                        else {\n                            return this.container == null ? true : aEnclosesB(scope.container, this.container);\n                        }\n                    }\n                    else {\n                        return true;\n                    }\n                }\n                else if (this.container) {\n                    return aEnclosesB(this, scope.container);\n                }\n                else {\n                    return true;\n                }\n            }\n        }\n\n        public addRef(identifier: Identifier) {\n            if (!this.refs) {\n                this.refs = [];\n            }\n            this.refs[this.refs.length] = identifier;\n        }\n\n        public toString() {\n            if (this.name) {\n                return this.name;\n            }\n            else {\n                return \"_anonymous\";\n            }\n        }\n\n        public print(outfile) {\n            outfile.Write(this.toString());\n        }\n\n        public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Symbol {\n            throw new Error(\"please implement in derived class\");\n        }\n\n        public setType(type: Type) {\n            throw new Error(\"please implement in derived class\");\n        }\n\n        public kind(): SymbolKind {\n            throw new Error(\"please implement in derived class\");\n        }\n\n        public getInterfaceDeclFromSymbol(checker: TypeChecker) {\n            if (this.declAST != null) {\n                if (this.declAST.nodeType == NodeType.InterfaceDeclaration) {\n                    return <InterfaceDeclaration>this.declAST;\n                } else if (this.container != null && this.container != checker.gloMod && this.container.declAST.nodeType == NodeType.InterfaceDeclaration) {\n                    return <InterfaceDeclaration>this.container.declAST;\n                }\n            }\n\n            return null;\n        }\n\n        public getVarDeclFromSymbol() {\n            if (this.declAST != null && this.declAST.nodeType == NodeType.VarDecl) {\n                return <VarDecl>this.declAST;\n            }\n\n            return null;\n        }\n\n        public getDocComments() : Comment[] {\n            if (this.declAST != null) {\n                return this.declAST.getDocComments();\n            }\n\n            return [];\n        }\n\n        public isStatic() {\n            return hasFlag(this.flags, SymbolFlags.Static);\n        }\n    }\n\n    export class ValueLocation {\n        public symbol: Symbol;\n        public typeLink: TypeLink;\n    }\n\n    export class InferenceSymbol extends Symbol {\n        constructor (name: string, location: number, length: number, unitIndex: number) {\n            super(name, location, length, unitIndex);\n        }\n\n        public typeCheckStatus = TypeCheckStatus.NotStarted;\n        public isInferenceSymbol() { return true; }\n        public transferVarFlags(varFlags: VarFlags) {\n            if (hasFlag(varFlags, VarFlags.Ambient)) {\n                this.flags |= SymbolFlags.Ambient;\n            }\n            if (hasFlag(varFlags, VarFlags.Constant)) {\n                this.flags |= SymbolFlags.Constant;\n            }\n            if (hasFlag(varFlags, VarFlags.Static)) {\n                this.flags |= SymbolFlags.Static;\n            }\n            if (hasFlag(varFlags, VarFlags.Property)) {\n                this.flags |= SymbolFlags.Property;\n            }\n            if (hasFlag(varFlags, VarFlags.Private)) {\n                this.flags |= SymbolFlags.Private;\n            }\n            if (hasFlag(varFlags, VarFlags.Public)) {\n                this.flags |= SymbolFlags.Public;\n            }\n            if (hasFlag(varFlags, VarFlags.Readonly)) {\n                this.flags |= SymbolFlags.Readonly;\n            }\n            if (hasFlag(varFlags, VarFlags.Exported)) {\n                this.flags |= SymbolFlags.Exported;\n            }\n        }\n    }\n\n    export class TypeSymbol extends InferenceSymbol {\n        public additionalLocations: number[];\n        public expansions: Type[] = []; // For types that may be \"split\", keep track of the subsequent definitions\n        public expansionsDeclAST: AST[] = [];\n        public isDynamic = false;\n\n        constructor (locName: string, location: number, length: number, unitIndex: number, public type: Type) {\n            super(locName, location, length, unitIndex);\n            this.prettyName = this.name;\n        }\n\n        public addLocation(loc: number) {\n            if (this.additionalLocations == null) {\n                this.additionalLocations = [];\n            }\n            this.additionalLocations[this.additionalLocations.length] = loc;\n        }\n        public isMethod = false;\n        public aliasLink:ImportDeclaration = null;\n        public kind() { return SymbolKind.Type; }\n        public isType(): bool { return true; }\n        public getType() { return this.type; }\n        public prettyName: string;\n        public onlyReferencedAsTypeRef = optimizeModuleCodeGen;\n\n        public getTypeNameEx(scope: SymbolScope) {\n            return this.type.getMemberTypeNameEx(this.name ? this.name + this.getOptionalNameString() : \"\", false, false, scope);\n        }\n\n        public instanceScope(): SymbolScope {\n            // Don't use the constructor scope for a class body or methods - use the contained scope\n            if (!(this.type.typeFlags & TypeFlags.IsClass) && this.type.isClass()) {\n                return this.type.instanceType.constructorScope;\n            }\n            else {\n                return this.type.containedScope;\n            }\n        }\n        // corresponding instance type if this is a class\n        public instanceType: Type;\n\n        public toString() {\n            var result = this.type.getTypeName();\n            if (this.name) {\n                result = this.name + \":\" + result;\n            }\n            return result;\n        }\n\n        public isClass() { return this.instanceType != null; }\n        public isFunction() { return this.declAST != null && this.declAST.nodeType == NodeType.FuncDecl; }\n\n        public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Symbol {\n            if (this.type == pattern) {\n                return replacement.symbol;\n            }\n            else {\n                var replType = this.type.specializeType(pattern, replacement, checker, false);\n                if (replType != this.type) {\n                    var result = new TypeSymbol(this.name, -1, 0, -1, replType);\n                    return result;\n                }\n                else {\n                    return this;\n                }\n            }\n        }\n\n        // Gets the pretty name of the symbol with respect to symbol of the scope (scopeSymbol)\n        // searchTillRoot specifies if the name need to searched in the root path of the scope\n        public getPrettyName(scopeSymbol: Symbol) {\n            if (!!scopeSymbol && isQuoted(this.prettyName) && this.type.isModuleType()) {\n                // Its a dynamic module - and need to be specialized with the scope\n                // Check in exported module members in each scope\n                var symbolPath = scopeSymbol.pathToRoot();\n                var prettyName = this.getPrettyNameOfDynamicModule(symbolPath);\n                if (prettyName != null) {\n                    return prettyName.name;\n                }\n            }\n\n            return this.prettyName;\n        }\n\n        public getPrettyNameOfDynamicModule(scopeSymbolPath: Symbol[]) {\n            var scopeSymbolPathLength = scopeSymbolPath.length;\n            var externalSymbol: { name: string; symbol: Symbol; } = null;\n            if (scopeSymbolPath.length > 0 &&\n                scopeSymbolPath[scopeSymbolPathLength - 1].getType().isModuleType() &&\n                (<TypeSymbol>scopeSymbolPath[scopeSymbolPathLength - 1]).isDynamic) {\n\n                // Check if submodule is dynamic\n                if (scopeSymbolPathLength > 1 &&\n                    scopeSymbolPath[scopeSymbolPathLength - 2].getType().isModuleType() &&\n                    (<TypeSymbol>scopeSymbolPath[scopeSymbolPathLength - 2]).isDynamic) {\n                    var moduleType = <ModuleType>scopeSymbolPath[scopeSymbolPathLength - 2].getType();\n                    externalSymbol = moduleType.findDynamicModuleName(this.type);\n\n                }\n\n                if (externalSymbol == null) {\n                    // Check in this module\n                    var moduleType = <ModuleType>scopeSymbolPath[scopeSymbolPathLength - 1].getType();\n                    externalSymbol = moduleType.findDynamicModuleName(this.type);\n                }\n            }\n\n            return externalSymbol;\n        }\n\n        public getDocComments(): Comment[]{\n            var comments : Comment[] = [];\n            if (this.declAST != null) {\n                comments = comments.concat(this.declAST.getDocComments());\n            }\n\n            for (var i = 0; i < this.expansionsDeclAST.length; i++) {\n                comments = comments.concat(this.expansionsDeclAST[i].getDocComments());\n            }\n\n            return comments;\n        }\n    }\n\n    export class WithSymbol extends TypeSymbol {\n        constructor (location: number, unitIndex: number, withType: Type) {\n            super(\"with\", location, 4, unitIndex, withType);\n        }\n        public isWith() { return true; }\n    }\n\n    export class FieldSymbol extends InferenceSymbol {\n        public name: string;\n        public location: number;\n\n        constructor (name: string, location: number, unitIndex: number, public canWrite: bool,\n                      public field: ValueLocation) {\n\n            super(name, location, name.length, unitIndex);\n            this.name = name;\n            this.location = location;\n        }\n        public kind() { return SymbolKind.Field; }\n        public writeable() { return this.isAccessor() ? this.setter != null : this.canWrite; }\n        public getType() { return this.field.typeLink.type; }\n        public getTypeNameEx(scope: SymbolScope) {\n            return MemberName.create(this.field.typeLink.type.getScopedTypeNameEx(scope), this.name + this.getOptionalNameString() + \": \", \"\");\n        }\n\n        public isMember() { return true; }\n        public setType(type: Type) {\n            this.field.typeLink.type = type;\n        }\n\n        public getter: TypeSymbol = null;\n        public setter: TypeSymbol = null;\n        public hasBeenEmitted = false; // since getters and setters are emitted together, need to track if one has been emitted\n\n        public isAccessor() { return this.getter != null || this.setter != null; }\n\n        public isVariable() { return true; }\n        public toString() { return this.getTypeNameEx(null).toString(); }\n        public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Symbol {\n            var rType = this.field.typeLink.type.specializeType(pattern, replacement, checker, false);\n            if (rType != this.field.typeLink.type) {\n                var fieldDef = new ValueLocation();\n                var result = new FieldSymbol(this.name, 0, checker.locationInfo.unitIndex,\n                                           this.canWrite, fieldDef);\n                result.flags = this.flags;\n                fieldDef.symbol = result;\n                fieldDef.typeLink = new TypeLink();\n                result.setType(rType);\n                result.typeCheckStatus = TypeCheckStatus.Finished;\n                return result;\n            }\n            else {\n                return this;\n            }\n        }\n\n        public getDocComments(): Comment[] {\n            if (this.getter != null || this.setter != null) {\n                var comments : Comment[] = [];\n                if (this.getter != null) {\n                    comments = comments.concat(this.getter.getDocComments());\n                }\n                if (this.setter != null) {\n                    comments = comments.concat(this.setter.getDocComments());\n                }\n                return comments;\n            }\n            else if (this.declAST != null) {\n                return this.declAST.getDocComments();\n            }\n\n            return [];\n        }\n\n    }\n\n    export class ParameterSymbol extends InferenceSymbol {\n        public name: string;\n        public location: number;\n        private paramDocComment: string = null;\n        public funcDecl: AST = null;\n        \n        constructor (name: string, location: number, unitIndex: number,\n                          public parameter: ValueLocation) {\n            super(name, location, name.length, unitIndex);\n\n            this.name = name;\n            this.location = location;\n        }\n        public kind() { return SymbolKind.Parameter; }\n        public writeable() { return true; }\n        public getType() { return this.parameter.typeLink.type; }\n        public setType(type: Type) {\n            this.parameter.typeLink.type = type;\n        }\n        public isVariable() { return true; }\n        public argsOffset = (-1);\n        public isOptional() {\n            if (this.parameter && this.parameter.symbol && this.parameter.symbol.declAST) {\n                return (<ArgDecl>this.parameter.symbol.declAST).isOptional;\n            }\n            else {\n                return false;\n            }\n        }\n\n        public getTypeNameEx(scope: SymbolScope) {\n            return MemberName.create(this.getType().getScopedTypeNameEx(scope), this.name + (this.isOptional() ? \"?\" : \"\") + \": \", \"\");\n        }\n\n        public toString() { return this.getTypeNameEx(null).toString(); }\n\n        public specializeType(pattern: Type, replacement: Type, checker: TypeChecker): Symbol {\n            var rType = this.parameter.typeLink.type.specializeType(pattern, replacement, checker, false);\n            if (this.parameter.typeLink.type != rType) {\n                var paramDef = new ValueLocation();\n                var result = new ParameterSymbol(this.name, 0, checker.locationInfo.unitIndex,\n                                               paramDef);\n                paramDef.symbol = result;\n                result.setType(rType);\n                return result;\n            }\n            else {\n                return this;\n            }\n        }\n\n        public getParameterDocComments() {\n            if (!this.paramDocComment) {\n                var parameterComments: string[] = [];\n                if (this.funcDecl) {\n                    var fncDocComments = this.funcDecl.getDocComments();\n                    var paramComment = Comment.getParameterDocCommentText(this.name, fncDocComments);\n                    if (paramComment != \"\") {\n                        parameterComments.push(paramComment);\n                    }\n                }\n                var docComments = TypeScript.Comment.getDocCommentText(this.getDocComments());\n                if (docComments != \"\") {\n                    parameterComments.push(docComments);\n                }\n                \n                this.paramDocComment = parameterComments.join(\"\\n\");\n            }\n\n            return this.paramDocComment;\n        }\n    }\n\n    export class VariableSymbol extends InferenceSymbol {\n\n        constructor (name: string, location: number, unitIndex: number, public variable: ValueLocation) {\n            super(name, location, name.length, unitIndex);\n        }\n        public kind() { return SymbolKind.Variable; }\n        public writeable() { return true; }\n        public getType() { return this.variable.typeLink.type; }\n        public getTypeNameEx(scope: SymbolScope) {\n            return MemberName.create(this.getType().getScopedTypeNameEx(scope), this.name + \": \", \"\");\n        }\n\n        public setType(type: Type) {\n            this.variable.typeLink.type = type;\n        }\n        public isVariable() { return true; }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export enum TokenID {\n        // Keywords\n        Any,\n        Bool,\n        Break,\n        Case,\n        Catch,\n        Class,\n        Const,\n        Continue,\n        Debugger,\n        Default,\n        Delete,\n        Do,\n        Else,\n        Enum,\n        Export,\n        Extends,\n        Declare,\n        False,\n        Finally,\n        For,\n        Function,\n        Constructor,\n        Get,\n        If,\n        Implements,\n        Import,\n        In,\n        InstanceOf,\n        Interface,\n        Let,\n        Module,\n        New,\n        Number,\n        Null,\n        Package,\n        Private,\n        Protected,\n        Public,\n        Return,\n        Set,\n        Static,\n        String,\n        Super,\n        Switch,\n        This,\n        Throw,\n        True,\n        Try,\n        TypeOf,\n        Var,\n        Void,\n        With,\n        While,\n        Yield,\n        // Punctuation\n        Semicolon,\n        OpenParen,\n        CloseParen,\n        OpenBracket,\n        CloseBracket,\n        OpenBrace,\n        CloseBrace,\n        Comma,\n        Equals,\n        PlusEquals,\n        MinusEquals,\n        AsteriskEquals,\n        SlashEquals,\n        PercentEquals,\n        AmpersandEquals,\n        CaretEquals,\n        BarEquals,\n        LessThanLessThanEquals,\n        GreaterThanGreaterThanEquals,\n        GreaterThanGreaterThanGreaterThanEquals,\n        Question,\n        Colon,\n        BarBar,\n        AmpersandAmpersand,\n        Bar,\n        Caret,\n        And,\n        EqualsEquals,\n        ExclamationEquals,\n        EqualsEqualsEquals,\n        ExclamationEqualsEquals,\n        LessThan,\n        LessThanEquals,\n        GreaterThan,\n        GreaterThanEquals,\n        LessThanLessThan,\n        GreaterThanGreaterThan,\n        GreaterThanGreaterThanGreaterThan,\n        Plus,\n        Minus,\n        Asterisk,\n        Slash,\n        Percent,\n        Tilde,\n        Exclamation,\n        PlusPlus,\n        MinusMinus,\n        Dot,\n        DotDotDot,\n        Error,\n        EndOfFile,\n        EqualsGreaterThan,\n        Identifier,\n        StringLiteral,\n        RegularExpressionLiteral,\n        NumberLiteral,\n        Whitespace,\n        Comment,\n        Lim,\n        LimFixed = EqualsGreaterThan,\n        LimKeyword = Yield,\n    }\n\n    export var tokenTable = new TokenInfo[];\n    export var nodeTypeTable = new string[];\n    export var nodeTypeToTokTable = new number[];\n    export var noRegexTable = new bool[];\n\n    noRegexTable[TokenID.Identifier] = true;\n    noRegexTable[TokenID.StringLiteral] = true;\n    noRegexTable[TokenID.NumberLiteral] = true;\n    noRegexTable[TokenID.RegularExpressionLiteral] = true;\n    noRegexTable[TokenID.This] = true;\n    noRegexTable[TokenID.PlusPlus] = true;\n    noRegexTable[TokenID.MinusMinus] = true;\n    noRegexTable[TokenID.CloseParen] = true;\n    noRegexTable[TokenID.CloseBracket] = true;\n    noRegexTable[TokenID.CloseBrace] = true;\n    noRegexTable[TokenID.True] = true;\n    noRegexTable[TokenID.False] = true;\n\n    export enum OperatorPrecedence {\n        None,\n        Comma,\n        Assignment,\n        Conditional,\n        LogicalOr,\n        LogicalAnd,\n        BitwiseOr,\n        BitwiseExclusiveOr,\n        BitwiseAnd,\n        Equality,\n        Relational,\n        Shift,\n        Additive,\n        Multiplicative,\n        Unary,\n        Lim\n    }\n\n    export enum Reservation {\n        None = 0,\n        Javascript = 1,\n        JavascriptFuture = 2,\n        TypeScript = 4,\n        JavascriptFutureStrict = 8,\n        TypeScriptAndJS = Javascript | TypeScript,\n        TypeScriptAndJSFuture = JavascriptFuture | TypeScript,\n        TypeScriptAndJSFutureStrict = JavascriptFutureStrict | TypeScript,\n    }\n\n    export class TokenInfo {\n        constructor (public tokenId: TokenID, public reservation: Reservation,\n                    public binopPrecedence: number, public binopNodeType: number,\n                    public unopPrecedence: number, public unopNodeType: number,\n                    public text: string, public ers: ErrorRecoverySet) { }\n    }\n\n    function setTokenInfo(tokenId: TokenID, reservation: number, binopPrecedence: number,\n        binopNodeType: number, unopPrecedence: number, unopNodeType: number,\n        text: string, ers: ErrorRecoverySet) {\n        if (tokenId !== undefined) {\n            tokenTable[tokenId] = new TokenInfo(tokenId, reservation, binopPrecedence,\n                                              binopNodeType, unopPrecedence, unopNodeType, text, ers);\n            if (binopNodeType != NodeType.None) {\n                nodeTypeTable[binopNodeType] = text;\n                nodeTypeToTokTable[binopNodeType] = tokenId;\n            }\n            if (unopNodeType != NodeType.None) {\n                nodeTypeTable[unopNodeType] = text;\n            }\n        }\n    }\n\n    setTokenInfo(TokenID.Any, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"any\", ErrorRecoverySet.PrimType);\n    setTokenInfo(TokenID.Bool, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"bool\", ErrorRecoverySet.PrimType);\n    setTokenInfo(TokenID.Break, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"break\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.Case, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"case\", ErrorRecoverySet.SCase);\n    setTokenInfo(TokenID.Catch, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"catch\", ErrorRecoverySet.Catch);\n    setTokenInfo(TokenID.Class, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"class\", ErrorRecoverySet.TypeScriptS);\n    setTokenInfo(TokenID.Const, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"const\", ErrorRecoverySet.Var);\n    setTokenInfo(TokenID.Continue, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"continue\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.Debugger, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.Debugger, \"debugger\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.Default, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"default\", ErrorRecoverySet.SCase);\n    setTokenInfo(TokenID.Delete, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.Delete, \"delete\", ErrorRecoverySet.Prefix);\n    setTokenInfo(TokenID.Do, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"do\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.Else, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"else\", ErrorRecoverySet.Else);\n    setTokenInfo(TokenID.Enum, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"enum\", ErrorRecoverySet.TypeScriptS);\n    setTokenInfo(TokenID.Export, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"export\", ErrorRecoverySet.TypeScriptS);\n    setTokenInfo(TokenID.Extends, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"extends\", ErrorRecoverySet.None);\n    setTokenInfo(TokenID.Declare, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"declare\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.False, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"false\", ErrorRecoverySet.RLit);\n    setTokenInfo(TokenID.Finally, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"finally\", ErrorRecoverySet.Catch);\n    setTokenInfo(TokenID.For, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"for\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.Function, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"function\", ErrorRecoverySet.Func);\n    setTokenInfo(TokenID.Constructor, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"constructor\", ErrorRecoverySet.Func);\n    setTokenInfo(TokenID.Get, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"get\", ErrorRecoverySet.Func);\n    setTokenInfo(TokenID.Set, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"set\", ErrorRecoverySet.Func);\n    setTokenInfo(TokenID.If, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"if\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.Implements, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"implements\", ErrorRecoverySet.None);\n    setTokenInfo(TokenID.Import, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"import\", ErrorRecoverySet.TypeScriptS);\n    setTokenInfo(TokenID.In, Reservation.TypeScriptAndJS, OperatorPrecedence.Relational, NodeType.In, OperatorPrecedence.None, NodeType.None, \"in\", ErrorRecoverySet.None);\n    setTokenInfo(TokenID.InstanceOf, Reservation.TypeScriptAndJS, OperatorPrecedence.Relational, NodeType.InstOf, OperatorPrecedence.None, NodeType.None, \"instanceof\", ErrorRecoverySet.BinOp);\n    setTokenInfo(TokenID.Interface, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"interface\", ErrorRecoverySet.TypeScriptS);\n    setTokenInfo(TokenID.Let, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"let\", ErrorRecoverySet.None);\n    setTokenInfo(TokenID.Module, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"module\", ErrorRecoverySet.TypeScriptS);\n    setTokenInfo(TokenID.New, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"new\", ErrorRecoverySet.PreOp);\n    setTokenInfo(TokenID.Number, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"number\", ErrorRecoverySet.PrimType);\n    setTokenInfo(TokenID.Null, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"null\", ErrorRecoverySet.RLit);\n    setTokenInfo(TokenID.Package, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"package\", ErrorRecoverySet.None);\n    setTokenInfo(TokenID.Private, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"private\", ErrorRecoverySet.TypeScriptS);\n    setTokenInfo(TokenID.Protected, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"protected\", ErrorRecoverySet.None);\n    setTokenInfo(TokenID.Public, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"public\", ErrorRecoverySet.TypeScriptS);\n    setTokenInfo(TokenID.Return, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"return\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.Static, Reservation.TypeScriptAndJSFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"static\", ErrorRecoverySet.None);\n    setTokenInfo(TokenID.String, Reservation.TypeScript, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"string\", ErrorRecoverySet.PrimType);\n    setTokenInfo(TokenID.Super, Reservation.TypeScriptAndJSFuture, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"super\", ErrorRecoverySet.RLit);\n    setTokenInfo(TokenID.Switch, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"switch\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.This, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"this\", ErrorRecoverySet.RLit);\n    setTokenInfo(TokenID.Throw, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"throw\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.True, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"true\", ErrorRecoverySet.RLit);\n    setTokenInfo(TokenID.Try, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"try\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.TypeOf, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.Typeof, \"typeof\", ErrorRecoverySet.Prefix);\n    setTokenInfo(TokenID.Var, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"var\", ErrorRecoverySet.Var);\n    setTokenInfo(TokenID.Void, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.Void, \"void\", ErrorRecoverySet.Prefix);\n    setTokenInfo(TokenID.With, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.With, \"with\", ErrorRecoverySet.Stmt);\n    setTokenInfo(TokenID.While, Reservation.TypeScriptAndJS, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"while\", ErrorRecoverySet.While);\n    setTokenInfo(TokenID.Yield, Reservation.JavascriptFutureStrict, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"yield\", ErrorRecoverySet.None);\n\n    setTokenInfo(TokenID.Identifier, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"identifier\", ErrorRecoverySet.ID);\n    setTokenInfo(TokenID.NumberLiteral, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"numberLiteral\", ErrorRecoverySet.Literal);\n    setTokenInfo(TokenID.RegularExpressionLiteral, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"regex\", ErrorRecoverySet.RegExp);\n    setTokenInfo(TokenID.StringLiteral, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"qstring\", ErrorRecoverySet.Literal);\n\n    // Non-operator non-identifier tokens\n    setTokenInfo(TokenID.Semicolon, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \";\", ErrorRecoverySet.SColon); // ;\n    setTokenInfo(TokenID.CloseParen, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \")\", ErrorRecoverySet.RParen); // )\n    setTokenInfo(TokenID.CloseBracket, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"]\", ErrorRecoverySet.RBrack); // ]\n    setTokenInfo(TokenID.OpenBrace, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"{\", ErrorRecoverySet.LCurly); // {\n    setTokenInfo(TokenID.CloseBrace, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"}\", ErrorRecoverySet.RCurly); // }\n    setTokenInfo(TokenID.DotDotDot, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"...\", ErrorRecoverySet.None); // ...\n\n    // Operator non-identifier tokens\n    setTokenInfo(TokenID.Comma, Reservation.None, OperatorPrecedence.Comma, NodeType.Comma, OperatorPrecedence.None, NodeType.None, \",\", ErrorRecoverySet.Comma); // ,\n    setTokenInfo(TokenID.Equals, Reservation.None, OperatorPrecedence.Assignment, NodeType.Asg, OperatorPrecedence.None, NodeType.None, \"=\", ErrorRecoverySet.Asg); // =\n    setTokenInfo(TokenID.PlusEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgAdd, OperatorPrecedence.None, NodeType.None, \"+=\", ErrorRecoverySet.BinOp); // +=\n    setTokenInfo(TokenID.MinusEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgSub, OperatorPrecedence.None, NodeType.None, \"-=\", ErrorRecoverySet.BinOp); // -=\n    setTokenInfo(TokenID.AsteriskEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgMul, OperatorPrecedence.None, NodeType.None, \"*=\", ErrorRecoverySet.BinOp); // *=\n\n    setTokenInfo(TokenID.SlashEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgDiv, OperatorPrecedence.None, NodeType.None, \"/=\", ErrorRecoverySet.BinOp); // /=\n    setTokenInfo(TokenID.PercentEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgMod, OperatorPrecedence.None, NodeType.None, \"%=\", ErrorRecoverySet.BinOp); // %=\n    setTokenInfo(TokenID.AmpersandEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgAnd, OperatorPrecedence.None, NodeType.None, \"&=\", ErrorRecoverySet.BinOp); // &=\n    setTokenInfo(TokenID.CaretEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgXor, OperatorPrecedence.None, NodeType.None, \"^=\", ErrorRecoverySet.BinOp); // ^=\n    setTokenInfo(TokenID.BarEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgOr, OperatorPrecedence.None, NodeType.None, \"|=\", ErrorRecoverySet.BinOp); // |=\n    setTokenInfo(TokenID.LessThanLessThanEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgLsh, OperatorPrecedence.None, NodeType.None, \"<<=\", ErrorRecoverySet.BinOp); // <<=\n    setTokenInfo(TokenID.GreaterThanGreaterThanEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgRsh, OperatorPrecedence.None, NodeType.None, \">>=\", ErrorRecoverySet.BinOp); // >>=\n    setTokenInfo(TokenID.GreaterThanGreaterThanGreaterThanEquals, Reservation.None, OperatorPrecedence.Assignment, NodeType.AsgRs2, OperatorPrecedence.None, NodeType.None, \">>>=\", ErrorRecoverySet.BinOp); // >>>=\n    setTokenInfo(TokenID.Question, Reservation.None, OperatorPrecedence.Conditional, NodeType.ConditionalExpression, OperatorPrecedence.None, NodeType.None, \"?\", ErrorRecoverySet.BinOp); // ?\n    setTokenInfo(TokenID.Colon, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \":\", ErrorRecoverySet.Colon); // :\n    setTokenInfo(TokenID.BarBar, Reservation.None, OperatorPrecedence.LogicalOr, NodeType.LogOr, OperatorPrecedence.None, NodeType.None, \"||\", ErrorRecoverySet.BinOp); // ||\n    setTokenInfo(TokenID.AmpersandAmpersand, Reservation.None, OperatorPrecedence.LogicalAnd, NodeType.LogAnd, OperatorPrecedence.None, NodeType.None, \"&&\", ErrorRecoverySet.BinOp); // &&\n    setTokenInfo(TokenID.Bar, Reservation.None, OperatorPrecedence.BitwiseOr, NodeType.Or, OperatorPrecedence.None, NodeType.None, \"|\", ErrorRecoverySet.BinOp); // |\n    setTokenInfo(TokenID.Caret, Reservation.None, OperatorPrecedence.BitwiseExclusiveOr, NodeType.Xor, OperatorPrecedence.None, NodeType.None, \"^\", ErrorRecoverySet.BinOp); // ^\n    setTokenInfo(TokenID.And, Reservation.None, OperatorPrecedence.BitwiseAnd, NodeType.And, OperatorPrecedence.None, NodeType.None, \"&\", ErrorRecoverySet.BinOp); // &\n    setTokenInfo(TokenID.EqualsEquals, Reservation.None, OperatorPrecedence.Equality, NodeType.Eq, OperatorPrecedence.None, NodeType.None, \"==\", ErrorRecoverySet.BinOp); // ==\n    setTokenInfo(TokenID.ExclamationEquals, Reservation.None, OperatorPrecedence.Equality, NodeType.Ne, OperatorPrecedence.None, NodeType.None, \"!=\", ErrorRecoverySet.BinOp); // !=\n    setTokenInfo(TokenID.EqualsEqualsEquals, Reservation.None, OperatorPrecedence.Equality, NodeType.Eqv, OperatorPrecedence.None, NodeType.None, \"===\", ErrorRecoverySet.BinOp); // ===\n    setTokenInfo(TokenID.ExclamationEqualsEquals, Reservation.None, OperatorPrecedence.Equality, NodeType.NEqv, OperatorPrecedence.None, NodeType.None, \"!==\", ErrorRecoverySet.BinOp); // !==\n    setTokenInfo(TokenID.LessThan, Reservation.None, OperatorPrecedence.Relational, NodeType.Lt, OperatorPrecedence.None, NodeType.None, \"<\", ErrorRecoverySet.BinOp); // <\n    setTokenInfo(TokenID.LessThanEquals, Reservation.None, OperatorPrecedence.Relational, NodeType.Le, OperatorPrecedence.None, NodeType.None, \"<=\", ErrorRecoverySet.BinOp); // <=\n    setTokenInfo(TokenID.GreaterThan, Reservation.None, OperatorPrecedence.Relational, NodeType.Gt, OperatorPrecedence.None, NodeType.None, \">\", ErrorRecoverySet.BinOp); // >\n    setTokenInfo(TokenID.GreaterThanEquals, Reservation.None, OperatorPrecedence.Relational, NodeType.Ge, OperatorPrecedence.None, NodeType.None, \">=\", ErrorRecoverySet.BinOp); // >=\n    setTokenInfo(TokenID.LessThanLessThan, Reservation.None, OperatorPrecedence.Shift, NodeType.Lsh, OperatorPrecedence.None, NodeType.None, \"<<\", ErrorRecoverySet.BinOp); // <<\n    setTokenInfo(TokenID.GreaterThanGreaterThan, Reservation.None, OperatorPrecedence.Shift, NodeType.Rsh, OperatorPrecedence.None, NodeType.None, \">>\", ErrorRecoverySet.BinOp); // >>\n    setTokenInfo(TokenID.GreaterThanGreaterThanGreaterThan, Reservation.None, OperatorPrecedence.Shift, NodeType.Rs2, OperatorPrecedence.None, NodeType.None, \">>>\", ErrorRecoverySet.BinOp); // >>>\n    setTokenInfo(TokenID.Plus, Reservation.None, OperatorPrecedence.Additive, NodeType.Add, OperatorPrecedence.Unary, NodeType.Pos, \"+\", ErrorRecoverySet.AddOp); // +\n    setTokenInfo(TokenID.Minus, Reservation.None, OperatorPrecedence.Additive, NodeType.Sub, OperatorPrecedence.Unary, NodeType.Neg, \"-\", ErrorRecoverySet.AddOp); // -\n    setTokenInfo(TokenID.Asterisk, Reservation.None, OperatorPrecedence.Multiplicative, NodeType.Mul, OperatorPrecedence.None, NodeType.None, \"*\", ErrorRecoverySet.BinOp); // *\n    setTokenInfo(TokenID.Slash, Reservation.None, OperatorPrecedence.Multiplicative, NodeType.Div, OperatorPrecedence.None, NodeType.None, \"/\", ErrorRecoverySet.BinOp); // /\n    setTokenInfo(TokenID.Percent, Reservation.None, OperatorPrecedence.Multiplicative, NodeType.Mod, OperatorPrecedence.None, NodeType.None, \"%\", ErrorRecoverySet.BinOp); // %\n    setTokenInfo(TokenID.Tilde, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.Not, \"~\", ErrorRecoverySet.PreOp); // ~\n    setTokenInfo(TokenID.Exclamation, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.LogNot, \"!\", ErrorRecoverySet.PreOp); // !\n    setTokenInfo(TokenID.PlusPlus, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.IncPre, \"++\", ErrorRecoverySet.PreOp); // ++\n    setTokenInfo(TokenID.MinusMinus, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.Unary, NodeType.DecPre, \"--\", ErrorRecoverySet.PreOp); // --\n    setTokenInfo(TokenID.OpenParen, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"(\", ErrorRecoverySet.LParen); // (\n    setTokenInfo(TokenID.OpenBracket, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"[\", ErrorRecoverySet.LBrack); // [\n    setTokenInfo(TokenID.Dot, Reservation.None, OperatorPrecedence.Unary, NodeType.None, OperatorPrecedence.None, NodeType.None, \".\", ErrorRecoverySet.Dot); // .\n    setTokenInfo(TokenID.EndOfFile, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"<EOF>\", ErrorRecoverySet.EOF); // EOF\n    setTokenInfo(TokenID.EqualsGreaterThan, Reservation.None, OperatorPrecedence.None, NodeType.None, OperatorPrecedence.None, NodeType.None, \"=>\", ErrorRecoverySet.None); // =>\n\n    export function lookupToken(tokenId: TokenID): TokenInfo {\n        return tokenTable[tokenId];\n    }\n\n    export enum TokenClass {\n        Punctuation,\n        Keyword,\n        Operator,\n        Comment,\n        Whitespace,\n        Identifier,\n        NumberLiteral,\n        StringLiteral,\n        RegExpLiteral,\n    }\n\n    export class SavedToken {\n        constructor (public tok: Token, public minChar: number, public limChar: number) { }\n    }\n\n    export class Token {\n        constructor (public tokenId: TokenID) {\n        }\n\n        public toString() {\n            return \"token: \" + this.tokenId + \" \" + this.getText() + \" (\" + (<any>TokenID)._map[this.tokenId] + \")\";\n        }\n\n        public print(line: number, outfile) {\n            outfile.WriteLine(this.toString() + \",on line\" + line);\n        }\n\n        public getText(): string {\n            return tokenTable[this.tokenId].text;\n        }\n\n        public classification(): TokenClass {\n            if (this.tokenId <= TokenID.LimKeyword) {\n                return TokenClass.Keyword;\n            }\n            else {\n                var tokenInfo = lookupToken(this.tokenId);\n                if (tokenInfo != undefined) {\n                    if ((tokenInfo.unopNodeType != NodeType.None) ||\n                        (tokenInfo.binopNodeType != NodeType.None)) {\n                        return TokenClass.Operator;\n                    }\n                }\n            }\n\n            return TokenClass.Punctuation;\n        }\n    }\n\n    export class NumberLiteralToken extends Token {\n        constructor (public value: number, public hasEmptyFraction?: bool) {\n            super(TokenID.NumberLiteral);\n        }\n\n        public getText(): string {\n            return this.hasEmptyFraction ? this.value.toString() + \".0\" : this.value.toString();\n        }\n\n        public classification(): TokenClass {\n            return TokenClass.NumberLiteral;\n        }\n    }\n\n    export class StringLiteralToken extends Token {\n        constructor (public value: string) {\n            super(TokenID.StringLiteral);\n        }\n\n        public getText(): string {\n            return this.value;\n        }\n\n        public classification(): TokenClass {\n            return TokenClass.StringLiteral;\n        }\n    }\n\n    export class IdentifierToken extends Token {\n        constructor (public value: string, public hasEscapeSequence : bool) {\n            super(TokenID.Identifier);\n        }\n        public getText(): string {\n            return this.value;\n        }\n        public classification(): TokenClass {\n            return TokenClass.Identifier;\n        }\n    }\n\n    export class WhitespaceToken extends Token {\n        constructor (tokenId: TokenID, public value: string) {\n            super(tokenId);\n        }\n\n        public getText(): string {\n            return this.value;\n        }\n\n        public classification(): TokenClass {\n            return TokenClass.Whitespace;\n        }\n    }\n\n    export class CommentToken extends Token {\n        constructor (tokenID: TokenID, public value: string, public isBlock: bool, public startPos: number, public line: number, public endsLine: bool) {\n            super(tokenID);\n        }\n\n        public getText(): string {\n            return this.value;\n        }\n\n        public classification(): TokenClass {\n            return TokenClass.Comment;\n        }\n    }\n\n    export class RegularExpressionLiteralToken extends Token {\n        constructor(public regex) {\n            super(TokenID.RegularExpressionLiteral);\n        }\n\n        public getText(): string {\n            return this.regex.toString();\n        }\n\n        public classification(): TokenClass {\n            return TokenClass.RegExpLiteral;\n        }\n    }\n\n    // TODO: new with length TokenID.LimFixed\n    export var staticTokens = new Token[];\n    export function initializeStaticTokens() {\n        for (var i = 0; i <= TokenID.LimFixed; i++) {\n            staticTokens[i] = new Token(i);\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts'/>\n///<reference path='io.ts'/>\n///<reference path='optionsParser.ts'/>\n\nclass CommandLineHost implements TypeScript.IResolverHost {\n\n    public pathMap: any = {};\n    public resolvedPaths: any = {};\n\n    constructor(public compilationSettings: TypeScript.CompilationSettings) { \n    }\n\n    public getPathIdentifier(path: string) { \n        return this.compilationSettings.useCaseSensitiveFileResolution ? path : path.toLocaleUpperCase();\n    }\n\n    public isResolved(path: string) {\n        return this.resolvedPaths[this.getPathIdentifier(this.pathMap[path])] != undefined;\n    }\n\n    public resolveCompilationEnvironment(preEnv: TypeScript.CompilationEnvironment,\n        resolver: TypeScript.ICodeResolver,\n        traceDependencies: bool): TypeScript.CompilationEnvironment {\n        var resolvedEnv = new TypeScript.CompilationEnvironment(preEnv.compilationSettings, preEnv.ioHost);\n\n        var nCode = preEnv.code.length;\n        var path = \"\";\n\n        var postResolutionError = \n            (errorFile: string, errorMessage: string) => {\n                TypeScript.CompilerDiagnostics.debugPrint(\"Could not resolve file '\" + errorFile + \"'\" + (errorMessage == \"\" ? \"\" : \": \" + errorMessage));\n            }\n\n        var resolutionDispatcher: TypeScript.IResolutionDispatcher = {\n            postResolutionError: postResolutionError,\n            postResolution: (path: string, code: TypeScript.ISourceText) => {\n                var pathId = this.getPathIdentifier(path);\n                if (!this.resolvedPaths[pathId]) {\n                    resolvedEnv.code.push(<TypeScript.SourceUnit>code);\n                    this.resolvedPaths[pathId] = true;\n                }\n            }\n        };\n\n        for (var i = 0; i < nCode; i++) {\n            path = TypeScript.switchToForwardSlashes(preEnv.ioHost.resolvePath(preEnv.code[i].path));\n            this.pathMap[preEnv.code[i].path] = path;\n            resolver.resolveCode(path, \"\", false, resolutionDispatcher);\n        }\n\n        return resolvedEnv;\n    }\n}\nclass BatchCompiler {\n    public compilationSettings: TypeScript.CompilationSettings;\n    public compilationEnvironment: TypeScript.CompilationEnvironment;\n    public resolvedEnvironment: TypeScript.CompilationEnvironment = null;\n    public hasResolveErrors: bool = false;\n    public compilerVersion = \"0.8.2.0\";\n    public printedVersion = false;\n\n    constructor (public ioHost: IIO) { \n        this.compilationSettings = new TypeScript.CompilationSettings();\n        this.compilationEnvironment = new TypeScript.CompilationEnvironment(this.compilationSettings, this.ioHost);\n    }\n\n    public resolve() {\n        var resolver = new TypeScript.CodeResolver(this.compilationEnvironment);\n        var commandLineHost = new CommandLineHost(this.compilationSettings);\n        var ret = commandLineHost.resolveCompilationEnvironment(this.compilationEnvironment, resolver, true);\n\n        // Reset resolve error status\n        this.hasResolveErrors = false;\n\n        for (var i = 0; i < this.compilationEnvironment.code.length; i++) {\n            if (!commandLineHost.isResolved(this.compilationEnvironment.code[i].path)) {\n                this.hasResolveErrors = true;\n                var path = this.compilationEnvironment.code[i].path;\n                if (!TypeScript.isSTRFile(path) && !TypeScript.isDSTRFile(path) && !TypeScript.isTSFile(path) && !TypeScript.isDTSFile(path)) {\n                    this.ioHost.stderr.WriteLine(\"Unknown extension for file: \\\"\"+path+\"\\\". Only .ts and .d.ts extensions are allowed.\");\n                }\n                else {\n                    this.ioHost.stderr.WriteLine(\"Error reading file \\\"\" + path + \"\\\": File not found\");\n                }\n            }\n        }\n\n        return ret;\n    }\n    \n    /// Do the actual compilation reading from input files and\n    /// writing to output file(s).\n    public compile(): bool {\n        var compiler: TypeScript.TypeScriptCompiler;\n\n        compiler = new TypeScript.TypeScriptCompiler(this.ioHost.stderr, new TypeScript.NullLogger(), this.compilationSettings);\n        compiler.setErrorOutput(this.ioHost.stderr);\n        compiler.setErrorCallback(\n            (minChar, charLen, message, unitIndex) => {\n                compiler.errorReporter.hasErrors = true;\n                var fname = this.resolvedEnvironment.code[unitIndex].path;\n                var lineCol = { line: -1, col: -1 };\n                compiler.parser.getSourceLineCol(lineCol, minChar);\n                // line is 1-base, col, however, is 0-base. add 1 to the col before printing the message\n                var msg = fname + \" (\" + lineCol.line + \",\" + (lineCol.col + 1) + \"): \" + message;\n                if (this.compilationSettings.errorRecovery) {\n                    this.ioHost.stderr.WriteLine(msg);\n                } else {\n                    throw new SyntaxError(msg);\n                }\n            });\n\n        if (this.compilationSettings.emitComments) {\n            compiler.emitCommentsToOutput();\n        }\n\n        var consumeUnit = (code: TypeScript.SourceUnit, addAsResident: bool) => {\n            try {\n                // if file resolving is disabled, the file's content will not yet be loaded\n\n                if (!this.compilationSettings.resolve) {\n                    code.content = this.ioHost.readFile(code.path);\n                    // If declaration files are going to be emitted, \n                    // preprocess the file contents and add in referenced files as well\n                    if (this.compilationSettings.generateDeclarationFiles) {\n                        TypeScript.CompilerDiagnostics.assert(code.referencedFiles == null, \"With no resolve option, referenced files need to null\");\n                        code.referencedFiles = TypeScript.getReferencedFiles(code);\n                    }\n                }\n\n                if (code.content != null) {\n                    if (this.compilationSettings.parseOnly) {\n                        compiler.parseUnit(code.content, code.path);\n                    }\n                    else {\n                        if (this.compilationSettings.errorRecovery) {\n                            compiler.parser.setErrorRecovery(this.ioHost.stderr);\n                        }\n                        compiler.addUnit(code.content, code.path, addAsResident, code.referencedFiles);\n                    }\n                }\n            }\n            catch (err) {\n                compiler.errorReporter.hasErrors = true;\n                // This includes syntax errors thrown from error callback if not in recovery mode\n                this.ioHost.stderr.WriteLine(err.message);\n            }\n\n        }\n\n        for (var iCode = 0 ; iCode < this.resolvedEnvironment.code.length; iCode++) {\n            if (!this.compilationSettings.parseOnly || (iCode > 0)) {\n                consumeUnit(this.resolvedEnvironment.code[iCode], false);\n            }\n        }\n\n        var emitterIOHost = {\n            createFile: (fileName: string, useUTF8?: bool) => IOUtils.createFileAndFolderStructure(this.ioHost, fileName, useUTF8),\n            directoryExists: this.ioHost.directoryExists,\n            fileExists: this.ioHost.fileExists,\n            resolvePath: this.ioHost.resolvePath\n        };\n\n        try {\n            if (!this.compilationSettings.parseOnly) {\n                compiler.typeCheck();\n                compiler.emit(emitterIOHost);\n                compiler.emitDeclarations();\n            }\n            else {\n                compiler.emitAST(emitterIOHost);\n            }\n        } catch (err) {\n            compiler.errorReporter.hasErrors = true;\n            // Catch emitter exceptions\n            if (err.message != \"EmitError\") {\n                throw err;\n            }\n        }\n\n        return compiler.errorReporter.hasErrors;\n    }\n\n    // Execute the provided inputs\n    public run() {\n        for (var i = 0; i < this.compilationEnvironment.code.length; i++) {\n            var unit = this.compilationEnvironment.code[i];\n            \n            var outputFileName: string = unit.path;\n            if (TypeScript.isTSFile(outputFileName)) {\n                outputFileName = outputFileName.replace(/\\.ts$/, \".js\");\n            } else if (TypeScript.isSTRFile(outputFileName)) {\n                outputFileName = outputFileName.replace(/\\.str$/, \".js\");\n            }\n            if (this.ioHost.fileExists(outputFileName)) {\n                var unitRes = this.ioHost.readFile(outputFileName)\n                this.ioHost.run(unitRes, outputFileName);\n            }\n        }\n    }\n\n    /// Begin batch compilation\n    public batchCompile() {\n        TypeScript.CompilerDiagnostics.diagnosticWriter = { Alert: (s: string) => { this.ioHost.printLine(s); } }\n\n        var code: TypeScript.SourceUnit;\n\n        var opts = new OptionsParser(this.ioHost);\n\n        opts.option('out', {\n            usage: 'Concatenate and emit output to single file | Redirect output structure to the directory',\n            type: 'file|directory',\n            set: (str) => {\n                this.compilationSettings.outputOption = str;\n            }\n        });\n\n        opts.option('style', {\n            usage: 'Select style checking options (examples --style requireSemi:off or --style \"eqeqeq;bitwise:off\")',\n            experimental: true,\n            set: (str) => {\n                this.compilationSettings.setStyleOptions(str);\n            }\n        });\n\n        opts.flag('sourcemap', {\n            usage: 'Generates corresponding .map file',\n            set: () => {\n                this.compilationSettings.mapSourceFiles = true;\n            }\n        });\n\n        opts.flag('declaration', {\n            usage: 'Generates corresponding .d.ts file',\n            set: () => {\n                this.compilationSettings.generateDeclarationFiles = true;\n            }\n        });\n\n        if (this.ioHost.watchFile) {\n            opts.flag('watch', {\n                usage: 'Watch output files',\n                set: () => {\n                    this.compilationSettings.watch = true;\n                }\n            }, 'w');\n        }\n\n        opts.flag('exec', {\n            usage: 'Execute the script after compilation',\n            set: () => {\n                this.compilationSettings.exec = true;\n            }\n        }, 'e');\n\n        opts.flag('parse', {\n            usage: 'Parse only',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.parseOnly = true;\n            }\n        });\n\n        opts.flag('minw', {\n            usage: 'Minimize whitespace',\n            experimental: true,\n            set: () => { this.compilationSettings.minWhitespace = true; }\n        }, 'mw');\n\n        opts.flag('const', {\n            usage: 'Propagate constants to emitted code',\n            experimental: true,\n            set: () => { this.compilationSettings.propagateConstants = true; }\n        });\n\n        opts.flag('errorrecovery', {\n            usage: 'Enable error recovery',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.errorRecovery = true;\n            }\n        }, 'er');\n\n        opts.flag('comments', {\n            usage: 'Emit comments to output',\n            set: () => {\n                this.compilationSettings.emitComments = true;\n            }\n        }, 'c');\n\n        opts.flag('cflow', {\n            usage: 'Control flow',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.controlFlow = true;\n            }\n        });\n\n        opts.flag('cflowp', {\n            usage: 'Print control flow',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.controlFlow = true;\n                this.compilationSettings.printControlFlow = true;\n            }\n        });\n\n        opts.flag('cflowu', {\n            usage: 'Print Use Def control flow',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.controlFlow = true;\n                this.compilationSettings.controlFlowUseDef = true;\n            }\n        });\n\n        opts.flag('noerroronwith', {\n            usage: 'Allow with statements',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.errorOnWith = false;\n            }\n        });\n\n        opts.flag('noresolve', {\n            usage: 'Skip resolution and preprocessing',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.resolve = false;\n                this.compilationSettings.preprocess = false;\n            }\n        });\n\n        opts.flag('debug', {\n            usage: 'Print debug output',\n            experimental: true,\n            set: () => {\n                TypeScript.CompilerDiagnostics.debug = true;\n            }\n        });\n\n        opts.flag('canCallDefinitionSignature', {\n            usage: 'Allows you to call the definition signature of an overload group',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.canCallDefinitionSignature = true;\n            }\n        });\n\n        opts.flag('nooptimizemodules', {\n            usage: 'Do not optimize module codegen',\n            experimental: true,\n            set: () => {\n                TypeScript.optimizeModuleCodeGen = false;\n            }\n        });\n\n        opts.flag('nolib', {\n            usage: 'Do not include a default lib.d.ts with global declarations',\n            set: () => {\n                this.compilationSettings.useDefaultLib = false;\n            }\n        });\n\n\n        opts.flag('inferProperties', {\n            usage: 'Infer class properties from top-level assignments to \\'this\\'',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.inferPropertiesFromThisAssignment = true;\n            }\n        });\n\n        opts.option('target', {\n            usage: 'Specify ECMAScript target version: \"ES3\" (default), or \"ES5\"',\n            type: 'VER',\n            set: (type) => {\n                type = type.toLowerCase();\n\n                if (type === 'es3') {\n                    this.compilationSettings.codeGenTarget = TypeScript.CodeGenTarget.ES3;\n                } else if (type === 'es5') {\n                    this.compilationSettings.codeGenTarget = TypeScript.CodeGenTarget.ES5;\n                }\n                else {\n                    this.ioHost.printLine(\"ECMAScript target version '\" + type + \"' not supported.  Using default 'ES3' code generation\");\n                }\n            }\n        });\n\n        opts.option('module', {\n            usage: 'Specify module code generation: \"commonjs\" (default) or \"amd\"',\n            type: 'kind',\n            set: (type) => {\n                type = type.toLowerCase();\n\n                if (type === 'commonjs' || type === 'node') {\n                    TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Synchronous;\n                } else if (type === 'amd') {\n                    TypeScript.moduleGenTarget = TypeScript.ModuleGenTarget.Asynchronous;\n                } else {\n                    this.ioHost.printLine(\"Module code generation '\" + type + \"' not supported.  Using default 'commonjs' code generation\");\n                }\n            }\n        });\n\n        var printedUsage = false;\n\n        opts.flag('help', {\n            usage: 'Print this message',\n            set: () => {\n                this.printVersion();\n                opts.printUsage();\n                printedUsage = true;\n            }\n        }, 'h');\n\n        opts.flag('useCaseSensitiveFileResolution', {\n            usage: 'Force file resolution to be case sensitive',\n            experimental: true,\n            set: () => {\n                this.compilationSettings.useCaseSensitiveFileResolution = true;\n            }\n        });\n\n        opts.flag('version', {\n            usage: 'Print the compiler\\'s version: ' + this.compilerVersion,\n            set: () => {\n                this.printVersion();\n            }\n        }, 'v');\n\n        opts.parse(this.ioHost.arguments);\n        \n        if (this.compilationSettings.useDefaultLib) {\n            var compilerFilePath = this.ioHost.getExecutingFilePath()\n            var binDirPath = this.ioHost.dirName(compilerFilePath);\n            var libStrPath = this.ioHost.resolvePath(binDirPath + \"/lib.d.ts\");\n            code = new TypeScript.SourceUnit(libStrPath, null);\n            this.compilationEnvironment.code.push(code);\n        }\n\n        for (var i = 0; i < opts.unnamed.length; i++) {\n            code = new TypeScript.SourceUnit(opts.unnamed[i], null);\n            this.compilationEnvironment.code.push(code);\n        }\n\n        // If no source files provided to compiler - print usage information\n        if (this.compilationEnvironment.code.length == (this.compilationSettings.useDefaultLib ? 1 : 0)) {\n            if (!printedUsage && !this.printedVersion) {\n                this.printVersion();\n                opts.printUsage();\n                this.ioHost.quit(1);\n            }\n            return;\n        }\n\n        var sourceFiles: TypeScript.SourceUnit[] = [];\n        if (this.compilationSettings.watch) {\n            // Capture the state before calling resolve\n            sourceFiles = this.compilationEnvironment.code.slice(0);\n        }\n\n        // Resolve file dependencies, if requested\n        this.resolvedEnvironment = this.compilationSettings.resolve ? this.resolve() : this.compilationEnvironment;\n\n        var hasCompileErrors = this.compile();\n\n        var hasErrors = hasCompileErrors || this.hasResolveErrors;\n        if (!hasErrors) {\n            if (this.compilationSettings.exec) {\n                this.run();\n            }\n        }\n\n        if (this.compilationSettings.watch) {\n            // Watch will cause the program to stick around as long as the files exist\n            this.watchFiles(sourceFiles);\n        }\n        else {  \n            // Exit with the appropriate error code\n            this.ioHost.quit(hasErrors ? 1 : 0);\n        }\n    }\n\n    public printVersion() {\n        if (!this.printedVersion) {\n            this.ioHost.printLine(\"Version \" + this.compilerVersion);\n            this.printedVersion = true;\n        }\n    }\n\n    public watchFiles(soruceFiles: TypeScript.SourceUnit[]) {\n        if (!this.ioHost.watchFile) {\n            this.ioHost.printLine(\"Error: Current host does not support -w[atch] option\");\n            return;\n        }\n\n        var resolvedFiles: string[] = []\n        var watchers: { [x: string]: IFileWatcher; } = {};\n\n        var addWatcher = (filename: string) => {\n            if (!watchers[filename]) {\n                var watcher = this.ioHost.watchFile(filename, onWatchedFileChange);\n                watchers[filename] = watcher;\n            }\n            else {\n                throw new Error(\"Cannot watch file, it is already watched.\");\n            }\n        };\n\n        var removeWatcher = (filename: string) => {\n            if (watchers[filename]) {\n                watchers[filename].close();\n                delete watchers[filename];\n            }\n            else {\n                throw new Error(\"Cannot stop watching file, it is not being watched.\");\n            }\n        };\n\n        var onWatchedFileChange = () => {\n            // Reset the state\n            this.compilationEnvironment.code = soruceFiles;\n\n            // Resolve file dependencies, if requested\n            this.resolvedEnvironment = this.compilationSettings.resolve ? this.resolve() : this.compilationEnvironment;\n\n            // Check if any new files were added to the environment as a result of the file change\n            var oldFiles = resolvedFiles;\n            var newFiles: string[] = [];\n            this.resolvedEnvironment.code.forEach((sf) => newFiles.push(sf.path));\n            newFiles = newFiles.sort();\n\n            var i = 0, j = 0;\n            while (i < oldFiles.length && j < newFiles.length) {\n\n                var compareResult = oldFiles[i].localeCompare(newFiles[j]);\n                if (compareResult == 0) {\n                    // No change here\n                    i++;\n                    j++;\n                }\n                else if (compareResult < 0) {\n                    // Entry in old list does not exist in the new one, it was removed\n                    removeWatcher(oldFiles[i]);\n                    i++;\n                }\n                else {\n                    // Entry in new list does exist in the new one, it was added\n                    addWatcher(newFiles[j]);\n                    j++;\n                }\n            }\n\n            // All remaining unmatched items in the old list have been removed\n            for (var k = i; k < oldFiles.length; k++) {\n                removeWatcher(oldFiles[k]);\n            }\n\n            // All remaing unmatched items in the new list have been added\n            for (var k = j; k < newFiles.length; k++) {\n                addWatcher(newFiles[k]);\n            }\n\n            // Update the state\n            resolvedFiles = newFiles;;\n\n            // Print header\n            this.ioHost.printLine(\"\");\n            this.ioHost.printLine(\"Recompiling (\" + new Date() + \"): \");\n            resolvedFiles.forEach((f) => this.ioHost.printLine(\"    \" + f));\n\n            // Trigger a new compilation\n            var hasCompileErrors = this.compile();\n\n            var hasErrors = hasCompileErrors || this.hasResolveErrors;\n            if (!hasErrors) {\n                if (this.compilationSettings.exec) {\n                    this.run();\n                }\n            }\n        };\n\n        // Switch to using stdout for all error messages\n        this.ioHost.stderr = this.ioHost.stdout;\n\n        // Initialize the initial list of resolved files, and add watches to them\n        this.resolvedEnvironment.code.forEach((sf) => {\n            resolvedFiles.push(sf.path);\n            addWatcher(sf.path);\n        });\n        resolvedFiles.sort();\n    }\n}\n\n// Start the batch compilation using the current hosts IO\nvar batch = new BatchCompiler(IO);\nbatch.batchCompile();\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export class ArrayCache {\n        public arrayType: Type;\n        public arrayBase: Type = null;\n\n        public specialize(arrInstType: Type, checker: TypeChecker): Type {\n            if (this.arrayBase == null) {\n                this.arrayBase = arrInstType.specializeType(checker.wildElm.type, this.arrayType.elementType,\n                                                   checker, true);\n            }\n            return this.arrayBase;\n        }\n    }\n\n    export class TypeComparisonInfo {\n        public onlyCaptureFirstError = false;\n        public flags: TypeRelationshipFlags = TypeRelationshipFlags.SuccessfulComparison;\n        public message = \"\";\n\n        public addMessageToFront(message) {\n            if (!this.onlyCaptureFirstError) {\n                this.message = this.message ? message + \":\\n\\t\" + this.message : message;\n            }\n            else {\n                this.setMessage(message);\n            }\n        }\n\n        public setMessage(message) {\n            this.message = message;\n        }\n    }\n\n    export interface SignatureData {\n        parameters: ParameterSymbol[];\n        nonOptionalParameterCount: number;\n    }\n\n    export interface ApplicableSignature {\n        signature: Signature;\n        hadProvisionalErrors: bool;\n    }\n\n    export enum TypeCheckCollectionMode {\n        Resident,\n        Transient\n    }\n\n    export class PersistentGlobalTypeState {\n        public importedGlobalsTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n        public importedGlobalsTypeTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n\n        public importedGlobals: SymbolScopeBuilder;\n\n        // transient state\n        public globals: IHashTable = null;\n        public globalTypes: IHashTable = null;\n        public ambientGlobals: IHashTable = null;\n        public ambientGlobalTypes: IHashTable = null;\n\n        // resident state\n        public residentGlobalValues = new StringHashTable();\n        public residentGlobalTypes = new StringHashTable();\n        public residentGlobalAmbientValues = new StringHashTable();\n        public residentGlobalAmbientTypes = new StringHashTable();\n\n        // dual resident/transient state\n\n        // REVIEW: We shouldn't need to allocate private hash tables for these, since there's no private global scope\n        // REVIEW: In general, we should audit each instance of DualStringHashTable to ensure that both the primary\n        // and secondary tables are necessary.  If it's not necessary, we should sub in a constant sentinel value.\n        public dualGlobalValues: DualStringHashTable;\n        public dualGlobalTypes: DualStringHashTable;\n        public dualAmbientGlobalValues: DualStringHashTable;\n        public dualAmbientGlobalTypes: DualStringHashTable;\n\n        public globalScope: SymbolScope;\n\n        public voidType: Type;\n        public booleanType: Type;\n        public doubleType: Type;\n\n        public stringType: Type;\n        public anyType: Type;\n        public nullType: Type;\n        public undefinedType: Type;\n\n        // Use this flag to turn resident checking on and off\n        public residentTypeCheck: bool = true;\n\n        public mod: ModuleType = null;\n        public gloMod: TypeSymbol = null;\n\n        public wildElm: TypeSymbol = null;\n\n        constructor (public errorReporter: ErrorReporter) {\n            this.importedGlobals = new SymbolScopeBuilder(null, this.importedGlobalsTable, null, this.importedGlobalsTypeTable, null, null);\n\n            this.dualGlobalValues = new DualStringHashTable(this.residentGlobalValues, new StringHashTable());\n            this.dualGlobalTypes = new DualStringHashTable(this.residentGlobalTypes, new StringHashTable());\n            this.dualAmbientGlobalValues = new DualStringHashTable(this.residentGlobalAmbientValues, new StringHashTable());\n            this.dualAmbientGlobalTypes = new DualStringHashTable(this.residentGlobalAmbientTypes, new StringHashTable());\n\n            var dualGlobalScopedMembers = new ScopedMembers(new DualStringHashTable(this.dualGlobalValues, new StringHashTable()));\n            var dualGlobalScopedAmbientMembers = new ScopedMembers(new DualStringHashTable(this.dualAmbientGlobalValues, new StringHashTable()));\n            var dualGlobalScopedEnclosedTypes = new ScopedMembers(new DualStringHashTable(this.dualGlobalTypes, new StringHashTable()));\n            var dualGlobalScopedAmbientEnclosedTypes = new ScopedMembers(new DualStringHashTable(this.dualAmbientGlobalTypes, new StringHashTable()));\n\n            this.globalScope = new SymbolScopeBuilder(dualGlobalScopedMembers, dualGlobalScopedAmbientMembers, dualGlobalScopedEnclosedTypes, dualGlobalScopedAmbientEnclosedTypes, this.importedGlobals, null);\n\n            this.voidType = this.enterPrimitive(Primitive.Void, \"void\");\n            this.booleanType = this.enterPrimitive(Primitive.Boolean, \"bool\");\n            this.doubleType = this.enterPrimitive(Primitive.Double, \"number\");\n            this.importedGlobals.ambientEnclosedTypes.addPublicMember(\"number\", this.doubleType.symbol);\n\n            this.stringType = this.enterPrimitive(Primitive.String, \"string\");\n            this.anyType = this.enterPrimitive(Primitive.Any, \"any\");\n            this.nullType = this.enterPrimitive(Primitive.Null, \"null\");\n            this.undefinedType = this.enterPrimitive(Primitive.Undefined, \"undefined\");\n\n            // shared global state is resident\n            this.setCollectionMode(TypeCheckCollectionMode.Resident);\n\n            this.wildElm = new TypeSymbol(\"_element\", -1, 0, -1, new Type());\n            this.importedGlobalsTypeTable.addPublicMember(this.wildElm.name, this.wildElm);\n\n            this.mod = new ModuleType(dualGlobalScopedEnclosedTypes, dualGlobalScopedAmbientEnclosedTypes);\n            this.mod.members = dualGlobalScopedMembers;\n            this.mod.ambientMembers = dualGlobalScopedAmbientMembers;\n            this.mod.containedScope = this.globalScope;\n\n            this.gloMod = new TypeSymbol(globalId, -1, 0, -1, this.mod);\n            this.mod.members.addPublicMember(this.gloMod.name, this.gloMod);\n\n            this.defineGlobalValue(\"undefined\", this.undefinedType);\n        }\n\n\n        public enterPrimitive(flags: number, name: string) {\n            var primitive = new Type();\n            primitive.primitiveTypeClass = flags;\n            var symbol = new TypeSymbol(name, -1, name.length, -1, primitive);\n            symbol.typeCheckStatus = TypeCheckStatus.Finished;\n            primitive.symbol = symbol;\n            this.importedGlobals.enter(null, null, symbol, this.errorReporter, true, true, true);\n            return primitive;\n        }\n\n        public setCollectionMode(mode: TypeCheckCollectionMode) {\n            this.residentTypeCheck =\n                this.dualGlobalValues.insertPrimary =\n                    this.dualGlobalTypes.insertPrimary =\n                        this.dualAmbientGlobalValues.insertPrimary =\n                            this.dualAmbientGlobalTypes.insertPrimary = mode == TypeCheckCollectionMode.Resident;\n        }\n\n        public refreshPersistentState() {\n            this.globals = new StringHashTable();\n            this.globalTypes = new StringHashTable();\n            this.ambientGlobals = new StringHashTable();\n            this.ambientGlobalTypes = new StringHashTable();\n\n            // add global types to the global scope\n            this.globalTypes.add(this.voidType.symbol.name, this.voidType.symbol);\n            this.globalTypes.add(this.booleanType.symbol.name, this.booleanType.symbol);\n            this.globalTypes.add(this.doubleType.symbol.name, this.doubleType.symbol);\n            this.globalTypes.add(\"number\", this.doubleType.symbol);\n            this.globalTypes.add(this.stringType.symbol.name, this.stringType.symbol);\n            this.globalTypes.add(this.anyType.symbol.name, this.anyType.symbol);\n            this.globalTypes.add(this.nullType.symbol.name, this.nullType.symbol);\n            this.globalTypes.add(this.undefinedType.symbol.name, this.undefinedType.symbol);\n\n            this.dualGlobalValues.secondaryTable = this.globals;\n            this.dualGlobalTypes.secondaryTable = this.globalTypes;\n            this.dualAmbientGlobalValues.secondaryTable = this.ambientGlobals;\n            this.dualAmbientGlobalTypes.secondaryTable = this.ambientGlobalTypes;\n        }\n\n        public defineGlobalValue(name: string, type: Type) {\n            var valueLocation = new ValueLocation();\n            valueLocation.typeLink = new TypeLink();\n            var sym = new VariableSymbol(name, 0, -1, valueLocation);\n            sym.setType(type);\n            sym.typeCheckStatus = TypeCheckStatus.Finished;\n            sym.container = this.gloMod;\n            this.importedGlobalsTable.addPublicMember(name, sym);\n        }\n    }\n\n    export class ContextualTypeContext {\n        public targetSig: Signature = null;\n        public targetThis: Type = null;\n        public targetAccessorType: Type = null;\n\n        constructor (public contextualType: Type,\n            public provisional: bool, public contextID: number) { }\n    }\n\n    export class ContextualTypingContextStack {\n        private contextStack: ContextualTypeContext[] = [];\n        static contextID = TypeCheckStatus.Finished + 1;\n        public pushContextualType(type: Type, provisional: bool) { this.contextStack.push(new ContextualTypeContext(type, provisional, ContextualTypingContextStack.contextID++)); this.checker.errorReporter.pushToErrorSink = provisional; }\n        public hadProvisionalErrors = false; // somewhere in the chain a provisional typecheck error was thrown\n        public popContextualType() {\n            var tc = this.contextStack.pop();\n            this.checker.errorReporter.pushToErrorSink = this.isProvisional();\n            this.hadProvisionalErrors = this.hadProvisionalErrors || (tc.provisional && (this.checker.errorReporter.getCapturedErrors().length));\n            this.checker.errorReporter.freeCapturedErrors();\n            return tc;\n        }\n        public getContextualType(): ContextualTypeContext { return (!this.contextStack.length ? null : this.contextStack[this.contextStack.length - 1]); }\n        public getContextID() { return (!this.contextStack.length ? TypeCheckStatus.Finished : this.contextStack[this.contextStack.length - 1].contextID); }\n        public isProvisional() { return (!this.contextStack.length ? false : this.contextStack[this.contextStack.length - 1].provisional); }\n\n        constructor (public checker: TypeChecker) { }\n    }\n\n    export class TypeChecker {\n        public errorReporter: ErrorReporter = null;\n        public globalScope: SymbolScope;\n\n        public checkControlFlow = false;\n        public printControlFlowGraph = false;\n        public checkControlFlowUseDef = false;\n        public styleSettings: StyleSettings = null;\n\n        public units: LocationInfo[] = null;\n\n        public voidType: Type;\n        public booleanType: Type;\n        public numberType: Type;\n        public stringType: Type;\n        public anyType: Type;\n        public nullType: Type;\n        public undefinedType: Type;\n\n        public anon = \"_anonymous\";\n\n        public globals: DualStringHashTable;\n        public globalTypes: DualStringHashTable;\n        public ambientGlobals: DualStringHashTable;\n        public ambientGlobalTypes: DualStringHashTable;\n        public gloModType: ModuleType;\n        public gloMod: TypeSymbol;\n        public wildElm: TypeSymbol;\n\n        public locationInfo: LocationInfo = null;\n        public typeFlow: TypeFlow = null;\n\n        public currentCompareA: Symbol = null;\n        public currentCompareB: Symbol = null;\n\n        public currentModDecl: ModuleDeclaration = null;\n\n        public inBind = false;\n        public inWith = false;\n        public errorsOnWith = true;\n\n        public typingContextStack: ContextualTypingContextStack;\n        public currentContextualTypeContext: ContextualTypeContext = null;\n\n        public resolvingBases = false;\n\n        public canCallDefinitionSignature = false;\n\n        public assignableCache: any[] = <any>{};\n        public subtypeCache: any[] = <any>{};\n        public identicalCache: any[] = <any>{};\n\n        public provisionalStartedTypecheckObjects: PhasedTypecheckObject[] = [];\n\n        public mustCaptureGlobalThis = false;\n\n        constructor (public persistentState: PersistentGlobalTypeState) {\n            this.voidType = this.persistentState.voidType;\n            this.booleanType = this.persistentState.booleanType;\n            this.numberType = this.persistentState.doubleType;\n            this.stringType = this.persistentState.stringType;\n            this.anyType = this.persistentState.anyType;\n            this.nullType = this.persistentState.nullType;\n            this.undefinedType = this.persistentState.undefinedType;\n\n            this.globals = this.persistentState.dualGlobalValues;\n            this.globalTypes = this.persistentState.dualGlobalTypes;\n            this.ambientGlobals = this.persistentState.dualAmbientGlobalValues;\n            this.ambientGlobalTypes = this.persistentState.dualAmbientGlobalTypes;\n            this.gloModType = this.persistentState.mod;\n            this.gloMod = this.persistentState.gloMod;\n            this.wildElm = this.persistentState.wildElm;\n\n            this.globalScope = this.persistentState.globalScope;\n\n            this.typingContextStack = new ContextualTypingContextStack(this);\n        }\n\n        public setStyleOptions(style: StyleSettings) {\n            this.styleSettings = style;\n        }\n\n        // Contextual typing\n        public setContextualType(type: Type, provisional: bool) {\n            this.typingContextStack.pushContextualType(type, provisional);\n            this.currentContextualTypeContext = this.typingContextStack.getContextualType();\n        }\n\n        public unsetContextualType() {\n            var lastTC = this.typingContextStack.popContextualType();\n            this.currentContextualTypeContext = this.typingContextStack.getContextualType();\n            return lastTC;\n        }\n\n        public hadProvisionalErrors() {\n            return this.typingContextStack.hadProvisionalErrors;\n        }\n        public resetProvisionalErrors() {\n            if (!this.typingContextStack.getContextualType()) {\n                this.typingContextStack.hadProvisionalErrors = false;\n            }\n        }\n\n        public typeCheckWithContextualType(contextType: Type, provisional: bool, condition: bool, ast: AST) {\n            if (condition) {\n                this.setContextualType(contextType, this.typingContextStack.isProvisional() || provisional);\n            }\n            this.typeFlow.typeCheck(ast);\n            if (condition) {\n                this.unsetContextualType();\n            }\n        }\n\n        public resetTargetType() {\n            this.currentContextualTypeContext = this.typingContextStack.getContextualType();\n        }\n\n        // Unset the current contextual type without disturbing the stack, effectively \"killing\" the contextual typing process\n        public killCurrentContextualType() { this.currentContextualTypeContext = null; this.errorReporter.pushToErrorSink = false; }\n        public hasTargetType() { return this.currentContextualTypeContext && this.currentContextualTypeContext.contextualType; }\n        public getTargetTypeContext() { return this.currentContextualTypeContext; }\n\n        public inProvisionalTypecheckMode() {\n            return this.typingContextStack.isProvisional();\n        }\n\n        public getTypeCheckFinishedStatus() {\n            if (this.inProvisionalTypecheckMode()) {\n                return this.typingContextStack.getContextID();\n            }\n            return TypeCheckStatus.Finished;\n        }\n\n        public typeStatusIsFinished(status: TypeCheckStatus) {\n\n            return status == TypeCheckStatus.Finished ||\n                   (this.inProvisionalTypecheckMode() && status == this.typingContextStack.getContextID());\n        }\n\n        public addStartedPTO(pto: PhasedTypecheckObject) {\n            if (this.inProvisionalTypecheckMode()) {\n                this.provisionalStartedTypecheckObjects[this.provisionalStartedTypecheckObjects.length] = pto;\n            }\n        }\n\n        public cleanStartedPTO() {\n            for (var i = 0; i < this.provisionalStartedTypecheckObjects.length; i++) {\n                if (this.provisionalStartedTypecheckObjects[i].typeCheckStatus >= this.typingContextStack.getContextID()) {\n                    this.provisionalStartedTypecheckObjects[i].typeCheckStatus = TypeCheckStatus.NotStarted;\n                }\n            }\n            this.provisionalStartedTypecheckObjects = [];\n        }\n\n        // type collection      \n        public collectTypes(ast: AST): void {\n            if (ast.nodeType == NodeType.Script) {\n                var script = <Script>ast;\n                this.locationInfo = script.locationInfo;\n            }\n            var globalChain = new ScopeChain(this.gloMod, null, this.globalScope);\n            var context = new TypeCollectionContext(globalChain, this);\n            getAstWalkerFactory().walk(ast, preCollectTypes, postCollectTypes, null, context);\n        }\n\n        public makeArrayType(type: Type): Type {\n            if (type.arrayCache == null) {\n                type.arrayCache = new ArrayCache();\n                type.arrayCache.arrayType = new Type();\n                type.arrayCache.arrayType.elementType = type;\n                type.arrayCache.arrayType.symbol = type.symbol;\n            }\n            return type.arrayCache.arrayType;\n        }\n\n        public getParameterList(funcDecl: FuncDecl, container: Symbol): SignatureData {\n            var args = funcDecl.arguments;\n            var parameterTable = null;\n            var parameterBuilder = null;\n            var len = args.members.length;\n            var nonOptionalParams = 0;\n            var result: ParameterSymbol[] = [];\n\n            if (len > 0) {\n                parameterTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n                parameterBuilder = new SymbolScopeBuilder(parameterTable, null, null, null, null, container);\n\n                for (var i = 0; i < len; i++) {\n                    var parameter = <ArgDecl>args.members[i];\n                    var paramDef = new ValueLocation();\n                    var parameterSymbol = new ParameterSymbol(parameter.id.text, parameter.minChar,\n                                                            this.locationInfo.unitIndex, paramDef);\n                    parameterSymbol.declAST = parameter;\n                    parameterSymbol.funcDecl = funcDecl;\n                    parameter.id.sym = parameterSymbol;\n                    parameter.sym = parameterSymbol;\n                    paramDef.symbol = parameterSymbol;\n                    paramDef.typeLink = getTypeLink(parameter.typeExpr, this, false);\n                    parameterBuilder.enter(null, parameter, parameterSymbol, this.errorReporter, true, false, false); // REVIEW: Should this be entered into the private scope?\n                    result[result.length] = parameterSymbol;\n                    if (!parameter.isOptionalArg()) {\n                        nonOptionalParams++;\n                    }\n                }\n            }\n            return { parameters: result, nonOptionalParameterCount: nonOptionalParams };\n        }\n\n        // Create a signature for a function definition\n        //  (E.g., has a function body - function declarations, property declarations, lambdas)\n        public createFunctionSignature(funcDecl: FuncDecl, container: Symbol, scope: SymbolScope, overloadGroupSym: Symbol, addToScope: bool): Signature {\n\n            var isExported = hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported) || container == this.gloMod;\n            var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);\n            var isPrivate = hasFlag(funcDecl.fncFlags, FncFlags.Private);\n            var isDefinition = hasFlag(funcDecl.fncFlags, FncFlags.Definition);\n            var isAmbient = hasFlag(funcDecl.fncFlags, FncFlags.Ambient);\n            var isConstructor = funcDecl.isConstructMember() || funcDecl.isConstructor;\n            var isGlobal = container == this.gloMod;\n\n            var signature: Signature = new Signature();\n            var isLambda = funcDecl.fncFlags & FncFlags.IsFunctionExpression;\n\n            // If a return type has been declared for the signature, set the type link.\n            // Otherwise:\n            //  if it's a signature, its type will be 'any'\n            //  if it's a definition, the return type will be inferred  \n            if (funcDecl.returnTypeAnnotation || isDefinition) {\n                signature.returnType = getTypeLink(funcDecl.returnTypeAnnotation, this, false);\n            }\n            else {\n                signature.returnType = new TypeLink();\n                signature.returnType.type = this.anyType;\n            }\n\n            signature.hasVariableArgList = funcDecl.variableArgList;\n\n            var sigData = this.getParameterList(funcDecl, container);\n\n            signature.parameters = sigData.parameters;\n            signature.nonOptionalParameterCount = sigData.nonOptionalParameterCount;\n\n            funcDecl.signature = signature;\n            signature.declAST = funcDecl;\n\n            var useOverloadGroupSym =\n                overloadGroupSym &&\n                overloadGroupSym.getType() &&\n                !overloadGroupSym.isAccessor() &&\n                (funcDecl.isSignature() || (isAmbient == hasFlag(overloadGroupSym.flags, SymbolFlags.Ambient)));\n\n            if (useOverloadGroupSym && isPrivate != hasFlag(overloadGroupSym.flags, SymbolFlags.Private)) {\n                this.errorReporter.simpleError(funcDecl, \"Public/Private visibility of overloads does not agree\");\n            }\n\n            var groupType = useOverloadGroupSym ? overloadGroupSym.getType() : new Type();\n\n            if (isConstructor) {\n                if (groupType.construct == null) {\n                    groupType.construct = new SignatureGroup();\n                }\n                groupType.construct.addSignature(signature);\n                groupType.construct.hasImplementation = !(funcDecl.isSignature());\n                if (groupType.construct.hasImplementation) {\n                    groupType.setHasImplementation();\n                }\n            }\n            else if (funcDecl.isIndexerMember()) {\n                if (groupType.index == null) {\n                    groupType.index = new SignatureGroup();\n                    groupType.index.flags |= SignatureFlags.IsIndexer;\n                }\n\n                groupType.index.addSignature(signature);\n                groupType.index.hasImplementation = !(funcDecl.isSignature());\n                if (groupType.index.hasImplementation) {\n                    groupType.setHasImplementation();\n                }\n            }\n            else {\n                if (groupType.call == null) {\n                    groupType.call = new SignatureGroup();\n                }\n                groupType.call.addSignature(signature);\n\n                groupType.call.hasImplementation = !(funcDecl.isSignature());\n                if (groupType.call.hasImplementation) {\n                    groupType.setHasImplementation();\n                }\n            }\n\n            var instanceType = groupType.instanceType;\n\n            // Ensure that the function's symbol is properly configured\n            // (If there were overloads, we'll already have a symbol, otherwise we need to create one)\n            var funcName: string = null;\n\n            // Set the function's name:\n            //  In the case of anonymous or functions resulting from error\n            //  correction in the parser (isMissing() == true), we do not\n            //  want to set a function name, since they shouldn't be inserted\n            //  into the enclosing scope\n\n            // usedHint prevents functions bound to object literal fields from being added to the\n            // enclosing scope\n            var usedHint = false;\n            if (funcDecl.name && !funcDecl.name.isMissing()) {\n                funcName = funcDecl.name.text;\n            }\n            else if (funcDecl.hint) {\n                funcName = funcDecl.hint;\n                usedHint = true;\n            }\n\n            if (groupType.symbol == null) {\n                groupType.symbol =\n                    new TypeSymbol(funcName ? funcName : this.anon,\n                                    funcDecl.minChar, funcDecl.limChar - funcDecl.minChar,\n                                    this.locationInfo.unitIndex,\n                                    groupType);\n                if (!useOverloadGroupSym) {\n                    groupType.symbol.declAST = funcDecl;\n                }\n            }\n\n            // REVIEW: Are we missing any other flags?\n            if (isStatic) {\n                groupType.symbol.flags |= SymbolFlags.Static;\n            }\n\n            if (isAmbient) {\n                groupType.symbol.flags |= SymbolFlags.Ambient;\n            }\n\n            if (isPrivate) {\n                groupType.symbol.flags |= SymbolFlags.Private;\n            }\n\n            groupType.symbol.isMethod = funcDecl.isMethod();\n            if (groupType.symbol.isMethod) {\n                groupType.symbol.flags |= SymbolFlags.Property;\n            }\n\n            funcDecl.type = groupType;\n\n            // Add the function symbol to the appropriate scope\n            // if the funcDecl is a constructor, it will be added to the enclosing scope as a class\n            if (!isConstructor) {\n                // Add the function's symbol to its enclosing scope\n                if (funcName && !isLambda && !funcDecl.isAccessor() && !usedHint) {\n\n                    // REVIEW: We're not setting the isDecl flags for fuctions bound to object literal properties\n                    // so removing the isDefiniton clause would break object literals\n                    if (addToScope) {  // REVIEW: If we combine this with createFunctionDeclarationSignature, we'll need to broaden this for both decls and defs                      \n                        // if it's a static method, enter directly into the container's scope\n                        if (funcDecl.isMethod() && isStatic) {\n\n                            // REVIEW: What about private statics?\n                            if (!(<TypeSymbol>container).type.members.publicMembers.add(funcName, groupType.symbol)) {\n                                this.errorReporter.duplicateIdentifier(funcDecl, funcName);\n                            }\n\n                            groupType.symbol.container = container;\n                        } // REVIEW: Another check for overloads...\n                        else if (overloadGroupSym == null || (overloadGroupSym.declAST && !(<FuncDecl>overloadGroupSym.declAST).isOverload && (container.isType()))) {\n                            scope.enter(container, funcDecl, groupType.symbol, this.errorReporter, !isPrivate && (isExported || isStatic || isGlobal), false, isAmbient);\n                        }\n                    }\n                    else if (!funcDecl.isSpecialFn()) {\n                        groupType.symbol.container = container; // REVIEW: Set container for overloads or anonymous?\n                    }\n                }\n                else if (!funcDecl.isSpecialFn()) {\n                    groupType.symbol.container = container; // REVIEW: Set container for lambdas and accessors?\n                }\n            }\n\n            // If, say, a call signature overload was declared before the class type was, we want to reuse\n            // the type that's already been instantiated for the class type, rather than allocate a new one\n            if (useOverloadGroupSym) {\n                var overloadGroupType = overloadGroupSym ? overloadGroupSym.getType() : null;\n                var classType = groupType;\n\n                if (classType != overloadGroupType) {\n                    if (classType.construct == null) {\n                        if (overloadGroupType && overloadGroupType.construct) {\n                            classType.construct = overloadGroupType.construct;\n                        }\n                        else {\n                            classType.construct = new SignatureGroup();\n                        }\n                    }\n                    else if (overloadGroupType) {\n                        if (overloadGroupType.construct) {\n                            classType.construct.signatures.concat(overloadGroupType.construct.signatures);\n                        }\n                    }\n\n                    // sync call and index signatures as well, but don't allocate should they not\n                    // already exist\n                    if (overloadGroupType) {\n                        if (classType.call == null) {\n                            classType.call = overloadGroupType.call;\n                        }\n                        else if (overloadGroupType.call) {\n                            classType.call.signatures.concat(overloadGroupType.call.signatures);\n                        }\n\n                        // if the function is not static, we need to add any call overloads onto the\n                        // instance type's call signature list\n                        if (!isStatic) {\n\n                            if (classType.instanceType == null) {\n                                classType.instanceType = overloadGroupType.instanceType;\n                            }\n\n                            var instanceType = classType.instanceType;\n\n                            if (instanceType) {\n                                if (instanceType.call == null) {\n                                    instanceType.call = overloadGroupType.call;\n                                }\n                                else if (overloadGroupType.call) {\n                                    instanceType.call.signatures.concat(overloadGroupType.call.signatures);\n                                }\n                            }\n                        }\n\n                        if (classType.index == null) {\n                            classType.index = overloadGroupType.index;\n                        }\n                        else if (overloadGroupType.index) {\n                            classType.index.signatures.concat(overloadGroupType.index.signatures);\n                        }\n                    }\n                }\n            }\n\n            return signature;\n        }\n\n        // Creates a new symbol for an accessor property\n        // Note that funcDecl.type.symbol and fgSym may not be the same (E.g., in the case of type collection)\n        public createAccessorSymbol(funcDecl: FuncDecl, fgSym: Symbol, enclosingClass: Type, addToMembers: bool, isClassProperty: bool, scope: SymbolScope, container: Symbol) {\n            var accessorSym: FieldSymbol = null\n            var sig = funcDecl.signature;\n            var nameText = funcDecl.name.text;\n            var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);\n            var isPrivate = hasFlag(funcDecl.fncFlags, FncFlags.Private);\n\n            if (fgSym == null) {\n                var field = new ValueLocation();\n                accessorSym = new FieldSymbol(nameText, funcDecl.minChar, this.locationInfo.unitIndex, false, field);\n                field.symbol = accessorSym;\n                accessorSym.declAST = funcDecl; // REVIEW: need to reset for getters and setters\n\n                if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n                    if (accessorSym.getter) {\n                        this.errorReporter.simpleError(funcDecl, \"Redeclaration of property getter\");\n                    }\n                    accessorSym.getter = <TypeSymbol>sig.declAST.type.symbol;\n                }\n                else {\n                    if (accessorSym.setter) {\n                        this.errorReporter.simpleError(funcDecl, \"Redeclaration of property setter\");\n                    }\n                    accessorSym.setter = <TypeSymbol>sig.declAST.type.symbol;\n                }\n\n                field.typeLink = getTypeLink(null, this, false);\n\n                // if it's static, enter it into the class's member list directly\n                if (addToMembers) {\n                    if (enclosingClass) {\n                        if (!enclosingClass.members.publicMembers.add(nameText, accessorSym)) {\n                            this.errorReporter.duplicateIdentifier(funcDecl, accessorSym.name);\n                        }\n                        accessorSym.container = enclosingClass.symbol;\n                    }\n                    else {\n                        this.errorReporter.simpleError(funcDecl, \"Accessor property may not be added in this context\");\n                    }\n                }\n                else {\n                    scope.enter(container, funcDecl, accessorSym, this.errorReporter, !isPrivate || isStatic, false, false);\n                }\n\n                // We set the flags here, instead of below, because the accessor symbol does not yet have a type\n                if (isClassProperty) {\n                    accessorSym.flags |= SymbolFlags.Property;\n                }\n                if (isStatic) {\n                    accessorSym.flags |= SymbolFlags.Static;\n                }\n\n                if (isPrivate) {\n                    accessorSym.flags |= SymbolFlags.Private;\n                }\n                else {\n                    accessorSym.flags |= SymbolFlags.Public;\n                }\n            }\n            else {\n                accessorSym = <FieldSymbol>(<any>fgSym);\n\n                if (isPrivate != hasFlag(accessorSym.flags, SymbolFlags.Private)) {\n                    this.errorReporter.simpleError(funcDecl, \"Getter and setter accessors do not agree in visibility\");\n                }\n\n                if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n                    if (accessorSym.getter) {\n                        this.errorReporter.simpleError(funcDecl, \"Redeclaration of property getter\");\n                    }\n                    accessorSym.getter = <TypeSymbol>funcDecl.type.symbol;\n                }\n                else {\n                    if (accessorSym.setter) {\n                        this.errorReporter.simpleError(funcDecl, \"Redeclaration of property setter\");\n                    }\n                    accessorSym.setter = <TypeSymbol>funcDecl.type.symbol;\n                }\n            }\n\n            return accessorSym;\n        }\n\n        public addBases(resultScope: SymbolAggregateScope, type: Type, baseContext: { base: string; baseId: number; }): void {\n            resultScope.addParentScope(new SymbolTableScope(type.members, type.ambientMembers, type.getAllEnclosedTypes(), type.getAllAmbientEnclosedTypes(), type.symbol));\n            var i = 0;\n            var parent: Type;\n            if (type.extendsList) {\n                for (var len = type.extendsList.length; i < len; i++) {\n                    parent = type.extendsList[i];\n                    if (baseContext.baseId == parent.typeID) {\n                        this.errorReporter.reportErrorFromSym(parent.symbol, \"Type '\" + baseContext.base + \"' is recursively referenced as a base class of itself\");\n                        parent.symbol.flags |= SymbolFlags.RecursivelyReferenced;\n                        break;\n                    }\n                    this.addBases(resultScope, parent, baseContext);\n                }\n            }\n        }\n\n        public scopeOf(type: Type): SymbolScope {\n            var resultScope = new SymbolAggregateScope(type.symbol);\n            var baseContext = { base: type.symbol && type.symbol.name ? type.symbol.name : \"{}\", baseId: type.typeID };\n            this.addBases(resultScope, type, baseContext);\n            return resultScope;\n        }\n\n        public lookupMemberTypeSymbol(containingType: Type, name: string): Symbol {\n            var symbol: Symbol = null;\n            if (containingType.containedScope) {\n                symbol = containingType.containedScope.find(name, false, true);\n            }\n            else if (containingType.members) {\n                symbol = containingType.members.allMembers.lookup(name);\n\n                if (symbol == null && containingType.ambientMembers) {\n                    symbol = containingType.ambientMembers.allMembers.lookup(name);\n                }\n            }\n            if (symbol == null) {\n                var typeMembers = containingType.getAllEnclosedTypes();\n                var ambientTypeMembers = containingType.getAllAmbientEnclosedTypes();\n                if (typeMembers) {\n                    symbol = typeMembers.allMembers.lookup(name);\n\n                    if (symbol == null && ambientTypeMembers) {\n                        symbol = ambientTypeMembers.allMembers.lookup(name);\n                    }\n\n                }\n            }\n            if (symbol && symbol.isType()) {\n                return symbol;\n            }\n            else {\n                return null;\n            }\n        }\n\n        public findSymbolForDynamicModule(idText: string, currentFileName: string, search: (id: string) =>Symbol): Symbol {\n            var originalIdText = idText;\n            var symbol = search(idText);\n           \n            if (symbol == null) {\n                // perhaps it's a dynamic module?\n                if (!symbol) {\n                    idText = swapQuotes(originalIdText);\n                    symbol = search(idText);\n                }\n\n                // Check the literal path first\n                if (!symbol) {\n                    idText = stripQuotes(originalIdText) + \".ts\";\n                    symbol = search(idText);\n                }\n\n                if (!symbol) {\n                    idText = stripQuotes(originalIdText) + \".str\";\n                    symbol = search(idText);\n                }\n\n                // Check check for .d.str\n                if (!symbol) {\n                    idText = stripQuotes(originalIdText) + \".d.ts\";\n                    symbol = search(idText);\n                }\n\n                if (!symbol) {\n                    idText = stripQuotes(originalIdText) + \".d.str\";\n                    symbol = search(idText);\n                }\n\n                // If the literal path doesn't work, begin the search\n                if (!symbol && !isRelative(originalIdText)) {\n                    // check the full path first, as this is the most likely scenario\n                    idText = originalIdText;\n\n                    var strippedIdText = stripQuotes(idText);\n\n                    // REVIEW: Technically, we shouldn't have to normalize here - we should normalize in addUnit.\n                    // Still, normalizing here alows any language services to be free of assumptions\n                    var path = getRootFilePath(switchToForwardSlashes(currentFileName));\n\n                    while (symbol == null && path != \"\") {\n                        idText = normalizePath(path + strippedIdText + \".ts\");\n                        symbol = search(idText);\n\n                        // check for .str\n                        if (symbol == null) {\n                            idText = changePathToSTR(idText);\n                            symbol = search(idText);\n                        }\n\n                        // check for .d.ts\n                        if (symbol == null) {\n                            idText = changePathToDTS(idText);\n                            symbol = search(idText);\n                        }\n\n                        // check for .d.str\n                        if (symbol == null) {\n                            idText = changePathToDSTR(idText);\n                            symbol = search(idText);\n                        }\n\n                        if (symbol == null) {\n							if(path === '/') {\n								path = '';\n						    } else {\n								path = normalizePath(path + \"..\");\n								path = path && path != '/' ? path + '/' : path;\n						    }\n                        }\n                    }\n                }\n            }\n\n            return symbol;\n        }\n\n        public resolveTypeMember(scope: SymbolScope, dotNode: BinaryExpression): Type {\n            var lhs = dotNode.operand1;\n            var rhs = dotNode.operand2;\n            var resultType = this.anyType;\n            var lhsType = this.anyType;\n\n            if (lhs && rhs && (rhs.nodeType == NodeType.Name)) {\n                if (lhs.nodeType == NodeType.Dot) {\n                    lhsType = this.resolveTypeMember(scope, <BinaryExpression>lhs);\n                }\n                else if (lhs.nodeType == NodeType.Name) {\n                    var identifier = <Identifier>lhs;\n                    var symbol = scope.find(identifier.text, false, true);\n                    if (symbol == null) {\n                        this.errorReporter.unresolvedSymbol(identifier, identifier.actualText);\n                    }\n                    else if (symbol.isType()) {\n\n                        var typeSymbol = <TypeSymbol> symbol;\n\n                        if (typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == NodeType.Name) {\n                            var modPath = (<Identifier>typeSymbol.aliasLink.alias).text;\n                            var modSym = this.findSymbolForDynamicModule(modPath, this.locationInfo.filename, (id) => scope.find(id, false, true));\n                            if (modSym) {\n                                typeSymbol.type = modSym.getType();\n                            }\n                        }\n\n                        if (optimizeModuleCodeGen && symbol) {\n                            var symType = symbol.getType();\n                            // Once the type has been referenced outside of a type ref position, there's\n                            // no going back                        \n                            if (symType && typeSymbol.aliasLink && typeSymbol.onlyReferencedAsTypeRef) {\n\n                                var modDecl = <ModuleDeclaration>symType.symbol.declAST;\n                                if (modDecl && hasFlag(modDecl.modFlags, ModuleFlags.IsDynamic)) {\n                                    typeSymbol.onlyReferencedAsTypeRef = !this.resolvingBases;\n                                }\n                            }\n                        }\n                        if (!symbol.visible(scope, this)) {\n                            this.errorReporter.simpleError(lhs, \"The symbol '\" + identifier.actualText + \"' is not visible at this point\");\n                        }\n                        lhsType = symbol.getType();\n\n                        identifier.sym = symbol;\n                    }\n                    else {\n                        this.errorReporter.simpleError(lhs, \"Expected type\");\n                    }\n\n                }\n\n                // if the LHS type is a module alias, we won't be able to resolve it until\n                // typecheck type.  If this is called during binding, lhsType will be null\n                if (!lhsType) {\n                    lhsType = this.anyType;\n                }\n\n                if (lhsType != this.anyType) {\n                    var rhsIdentifier = <Identifier>rhs;\n                    var resultSymbol = this.lookupMemberTypeSymbol(lhsType, rhsIdentifier.text);\n                    if (resultSymbol == null) {\n                        resultType = this.anyType;\n                        this.errorReporter.simpleError(dotNode, \"Expected type\");\n                    }\n                    else {\n                        resultType = resultSymbol.getType();\n                        if (!resultSymbol.visible(scope, this)) {\n                            this.errorReporter.simpleError(lhs, \"The symbol '\" + (<Identifier>rhs).actualText + \"' is not visible at this point\");\n                        }\n                    }\n                    rhsIdentifier.sym = resultType.symbol;\n                }\n            }\n            if (resultType.isClass()) {\n                resultType = resultType.instanceType;\n            }\n            return resultType;\n        }\n\n        public resolveFuncDecl(funcDecl: FuncDecl, scope: SymbolScope,\n            fgSym: TypeSymbol): Symbol {\n            var functionGroupSymbol = this.createFunctionSignature(funcDecl, scope.container, scope, fgSym, false).declAST.type.symbol;\n            var signatures: Signature[];\n            if (funcDecl.isConstructMember()) {\n                signatures = functionGroupSymbol.type.construct.signatures;\n            }\n            else if (funcDecl.isIndexerMember()) {\n                signatures = functionGroupSymbol.type.getInstanceType().index.signatures;\n            }\n            else {\n                signatures = functionGroupSymbol.type.call.signatures;\n            }\n\n            var signature = signatures[signatures.length - 1];\n            var len = signature.parameters.length;\n            for (var i = 0; i < len; i++) {\n                var paramSym: ParameterSymbol = signature.parameters[i];\n                this.resolveTypeLink(scope, paramSym.parameter.typeLink, true);\n            }\n\n            // If a vararg list is present, check that the type is an array type\n            if (len && funcDecl.variableArgList) {\n                if (!signature.parameters[len - 1].parameter.typeLink.type.elementType) {\n                    this.errorReporter.simpleErrorFromSym(signature.parameters[len - 1].parameter.symbol, \"... parameter must have array type\");\n                    signature.parameters[len - 1].parameter.typeLink.type = this.makeArrayType(signature.parameters[len - 1].parameter.typeLink.type);\n                }\n            }\n            this.resolveTypeLink(scope, signature.returnType,\n                            funcDecl.isSignature());\n            return functionGroupSymbol;\n        }\n\n        public resolveVarDecl(varDecl: VarDecl, scope: SymbolScope): Symbol {\n            var field = new ValueLocation();\n            var fieldSymbol =\n                new FieldSymbol(varDecl.id.text, varDecl.minChar, this.locationInfo.unitIndex,\n                                (varDecl.varFlags & VarFlags.Readonly) == VarFlags.None,\n                                field);\n            fieldSymbol.transferVarFlags(varDecl.varFlags);\n            field.symbol = fieldSymbol;\n            fieldSymbol.declAST = varDecl;\n            field.typeLink = getTypeLink(varDecl.typeExpr, this, varDecl.init == null);\n            this.resolveTypeLink(scope, field.typeLink, true);\n            varDecl.sym = fieldSymbol;\n            varDecl.type = field.typeLink.type;\n            return fieldSymbol;\n        }\n\n        public resolveTypeLink(scope: SymbolScope, typeLink: TypeLink, supplyVar: bool): void {\n            var arrayCount = 0;\n            if (typeLink.type == null) {\n                var ast: AST = typeLink.ast;\n                if (ast) {\n                    while (typeLink.type == null) {\n                        switch (ast.nodeType) {\n                            case NodeType.Name:\n                                var identifier = <Identifier>ast;\n                                var symbol = scope.find(identifier.text, false, true);\n                                if (symbol == null) {\n                                    typeLink.type = this.anyType;\n                                    this.errorReporter.unresolvedSymbol(identifier, identifier.actualText);\n                                }\n                                else if (symbol.isType()) {\n                                    if (!symbol.visible(scope, this)) {\n                                        this.errorReporter.simpleError(ast, \"The symbol '\" + identifier.actualText + \"' is not visible at this point\");\n                                    }\n                                    identifier.sym = symbol;\n                                    typeLink.type = symbol.getType();\n                                    if (typeLink.type) {\n                                        if (typeLink.type.isClass()) {\n                                            typeLink.type = typeLink.type.instanceType;\n                                        }\n                                    }\n                                    else {\n                                        typeLink.type = this.anyType;\n                                    }\n                                }\n                                else {\n                                    typeLink.type = this.anyType;\n                                    this.errorReporter.simpleError(ast, \"Expected type\");\n                                }\n                                break;\n                            case NodeType.Dot:\n                                typeLink.type = this.resolveTypeMember(scope, <BinaryExpression>ast);\n                                break;\n                            case NodeType.TypeRef:\n                                var typeRef = <TypeReference>ast;\n                                arrayCount = typeRef.arrayCount;\n                                ast = typeRef.term;\n                                if (ast == null) {\n                                    typeLink.type = this.anyType;\n                                }\n                                break;\n                            case NodeType.InterfaceDeclaration:\n                                var interfaceDecl = <InterfaceDeclaration>ast;\n                                var interfaceType = new Type();\n                                var interfaceSymbol = new TypeSymbol((<Identifier>interfaceDecl.name).text,\n                                                                   ast.minChar,\n                                                                   ast.limChar - ast.minChar,\n                                                                   this.locationInfo.unitIndex,\n                                                                   interfaceType);\n                                interfaceType.symbol = interfaceSymbol;\n                                interfaceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n\n                                interfaceType.containedScope =\n                                    new SymbolTableScope(interfaceType.members, null, null, null,\n                                                         interfaceSymbol);\n\n                                interfaceType.containedScope.container = interfaceSymbol;\n                                interfaceType.memberScope = interfaceType.containedScope;\n\n                                var memberList = <ASTList>interfaceDecl.members;\n                                var props: AST[] = memberList.members;\n                                var propsLen = props.length;\n\n                                for (var j = 0; j < propsLen; j++) {\n                                    var propDecl = props[j];\n                                    var propSym: Symbol = null;\n                                    var addMember = true;\n                                    var id: Identifier = null;\n                                    if (propDecl.nodeType == NodeType.FuncDecl) {\n                                        var funcDecl = <FuncDecl>propDecl;\n                                        id = funcDecl.name;\n                                        propSym = interfaceType.members.allMembers.lookup(funcDecl.getNameText());\n                                        addMember = (propSym == null);\n                                        if (funcDecl.isSpecialFn()) {\n                                            addMember = false;\n                                            propSym = this.resolveFuncDecl(funcDecl, scope, interfaceSymbol);\n                                        }\n                                        else {\n                                            propSym = this.resolveFuncDecl(funcDecl, scope, <TypeSymbol>propSym);\n                                        }\n                                        funcDecl.type = (<TypeSymbol>propSym).type;\n                                    }\n                                    else {\n                                        id = (<VarDecl>propDecl).id;\n                                        propSym = this.resolveVarDecl(<VarDecl>propDecl, scope);\n\n                                        // Don't add the member if it was missing a name.  This \n                                        // generally just leads to cascading errors that make things\n                                        // more confusing for the user.\n                                        addMember = !id.isMissing();\n                                    }\n\n                                    if (addMember) {\n                                        if (id && hasFlag(id.flags, ASTFlags.OptionalName)) {\n                                            propSym.flags |= SymbolFlags.Optional;\n                                        }\n                                        if (!interfaceType.members.allMembers.add(propSym.name, propSym)) {\n                                            this.errorReporter.duplicateIdentifier(ast, propSym.name);\n                                        }\n                                    }\n                                }\n\n                                ast.type = interfaceType;\n                                typeLink.type = interfaceType;\n\n                                break;\n                            case NodeType.FuncDecl:\n                                var tsym = <TypeSymbol>this.resolveFuncDecl(<FuncDecl>ast, scope, null);\n                                typeLink.type = tsym.type;\n                                break;\n                            default:\n                                typeLink.type = this.anyType;\n                                this.errorReporter.simpleError(ast, \"Expected type\");\n                                break;\n                        }\n                    }\n                }\n                for (var count = arrayCount; count > 0; count--) {\n                    typeLink.type = this.makeArrayType(typeLink.type);\n                }\n                if (supplyVar && (typeLink.type == null)) {\n                    typeLink.type = this.anyType;\n                }\n                if (typeLink.ast) {\n                    typeLink.ast.type = typeLink.type;\n                }\n            }\n            // else wait for type inference\n        }\n\n        public resolveBaseTypeLink(typeLink: TypeLink, scope: SymbolScope) {\n            this.resolvingBases = true;\n            this.resolveTypeLink(scope, typeLink, true);\n            this.resolvingBases = false;\n            var extendsType: Type = null;\n            if (typeLink.type.isClass()) {\n                extendsType = typeLink.type.instanceType;\n            }\n            else {\n                extendsType = typeLink.type;\n            }\n\n            return extendsType;\n        }\n\n        public findMostApplicableSignature(signatures: ApplicableSignature[], args: ASTList): { sig: Signature; ambiguous: bool; } {\n\n            if (signatures.length == 1) {\n                return { sig: signatures[0].signature, ambiguous: false };\n            }\n\n            var best: ApplicableSignature = signatures[0];\n            var Q: ApplicableSignature = null;\n            var AType: Type = null;\n            var PType: Type = null;\n            var QType: Type = null;\n            var ambiguous = false;\n\n            for (var qSig = 1; qSig < signatures.length; qSig++) {\n                Q = signatures[qSig];\n                var i = 0;\n                // find the better conversion\n                for (i = 0; args && i < args.members.length; i++) {\n                    AType = args.members[i].type;\n                    PType = i < best.signature.parameters.length ? best.signature.parameters[i].getType() : best.signature.parameters[best.signature.parameters.length - 1].getType().elementType;\n                    QType = i < Q.signature.parameters.length ? Q.signature.parameters[i].getType() : Q.signature.parameters[Q.signature.parameters.length - 1].getType().elementType;\n\n                    if (this.typesAreIdentical(PType, QType)) {\n                        continue;\n                    }\n                    else if (this.typesAreIdentical(AType, PType)) {\n                        break;\n                    }\n                    else if (this.typesAreIdentical(AType, QType)) {\n                        best = Q;\n                        break;\n                    }\n                    else if (this.sourceIsSubtypeOfTarget(PType, QType)) {\n                        break;\n                    }\n                    else if (this.sourceIsSubtypeOfTarget(QType, PType)) {\n                        best = Q;\n                        break;\n                    }\n                    else if (Q.hadProvisionalErrors) {\n                        break;\n                    }\n                    else if (best.hadProvisionalErrors) {\n                        best = Q;\n                        break;\n                    }\n                }\n\n                if (!args || i == args.members.length) {\n                    var collection: ITypeCollection = {\n                        getLength: () => { return 2; },\n                        setTypeAtIndex: (index: number, type: Type) => { }, // no contextual typing here, so no need to do anything\n                        getTypeAtIndex: (index: number) => { return index ? Q.signature.returnType.type : best.signature.returnType.type; } // we only want the \"second\" type - the \"first\" is skipped\n                    }\n                    var bct = this.findBestCommonType(best.signature.returnType.type, null, collection, true);\n                    ambiguous = !bct;\n                }\n                else {\n                    ambiguous = false;\n                }\n            }\n\n            return { sig: best.signature, ambiguous: ambiguous };\n        }\n\n        public getApplicableSignatures(signatures: Signature[], args: ASTList, comparisonInfo: TypeComparisonInfo): ApplicableSignature[] {\n\n            var applicableSigs: ApplicableSignature[] = [];\n            var memberType: Type = null;\n            var miss = false;\n            var cxt: ContextualTypeContext = null;\n            var hadProvisionalErrors = false;\n\n            for (var i = 0; i < signatures.length; i++) {\n                miss = false;\n\n                for (var j = 0; j < args.members.length; j++) {\n\n                    if (j >= signatures[i].parameters.length) {\n                        continue;\n                    }\n                    memberType = signatures[i].parameters[j].getType();\n\n                    // account for varargs\n                    if (signatures[i].declAST.variableArgList && (j >= signatures[i].nonOptionalParameterCount - 1) && memberType.isArray()) {\n                        memberType = memberType.elementType;\n                    }\n\n                    if (memberType == this.anyType) {\n                        continue;\n                    }\n                    else if (args.members[j].nodeType == NodeType.FuncDecl) {\n                        if (this.typeFlow.functionInterfaceType && memberType == this.typeFlow.functionInterfaceType) {\n                            continue;\n                        }\n                        if (!this.canContextuallyTypeFunction(memberType, <FuncDecl>args.members[j], true)) {\n                            // if it's just annotations that are blocking us, typecheck the function and add it to the list\n                            if (this.canContextuallyTypeFunction(memberType, <FuncDecl>args.members[j], false)) {\n                                this.typeFlow.typeCheck(args.members[j]);\n                                if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {\n                                    break;\n                                }\n                            }\n                            else {\n                                break;\n                            }\n                        }\n                        else { // if it can be contextually typed, try it out...\n\n                            this.typeCheckWithContextualType(memberType, true, true, args.members[j]);\n                            this.cleanStartedPTO();\n                            hadProvisionalErrors = this.hadProvisionalErrors();\n\n                            if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {\n                                if (comparisonInfo) {\n                                    comparisonInfo.setMessage(\"Could not apply type '\" + memberType.getTypeName() + \"' to argument \" + (j + 1) + \", which is of type '\" + args.members[j].type.getTypeName() + \"'\");\n                                }\n                                miss = true;\n                            }\n\n                            // clean the type\n                            //if (hadProvisionalErrors) {\n                            //    cxt = this.currentContextualTypeContext;\n                            //    this.typeCheckWithContextualType(null, true, true, args.members[j]);\n                            //    if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType)) {\n                            //        miss = true;\n                            //    }\n                            //    this.cleanStartedPTO();\n                            //}\n\n                            this.resetProvisionalErrors();\n                            if (miss) {\n                                break;\n                            }\n                        }\n                    }\n                    else if (args.members[j].nodeType == NodeType.ObjectLit) {\n                        // now actually attempt to typecheck as the contextual type\n                        if (this.typeFlow.objectInterfaceType && memberType == this.typeFlow.objectInterfaceType) {\n                            continue;\n                        }\n\n                        this.typeCheckWithContextualType(memberType, true, true, args.members[j]);\n                        this.cleanStartedPTO();\n                        hadProvisionalErrors = this.hadProvisionalErrors(); \n\n                        if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {\n                            if (comparisonInfo) {\n                                comparisonInfo.setMessage(\"Could not apply type '\" + memberType.getTypeName() + \"' to argument \" + (j + 1) + \", which is of type '\" + args.members[j].type.getTypeName() + \"'\");\n                            }\n                            miss = true;\n                        }\n\n                        // clean the type\n                        //if (hadProvisionalErrors) {\n                        //    this.typeCheckWithContextualType(null, true, true, args.members[j]);\n\n                        //    // is the \"cleaned\" type even assignable?\n                        //    if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType)) {\n                        //        miss = true;\n                        //    }\n\n                        //    this.cleanStartedPTO();\n                        //}\n\n                        this.resetProvisionalErrors();\n                        if (miss) {\n                            break;\n                        }\n                    }\n                    else if (args.members[j].nodeType == NodeType.ArrayLit) {\n                        // attempt to contextually type the array literal\n                        if (this.typeFlow.arrayInterfaceType && memberType == this.typeFlow.arrayInterfaceType) {\n                            continue;\n                        }\n\n                        this.typeCheckWithContextualType(memberType, true, true, args.members[j]);\n                        this.cleanStartedPTO();\n                        hadProvisionalErrors = this.hadProvisionalErrors(); \n\n                        if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType, comparisonInfo)) {\n                            if (comparisonInfo) {\n                                comparisonInfo.setMessage(\"Could not apply type '\" + memberType.getTypeName() + \"' to argument \" + (j + 1) + \", which is of type '\" + args.members[j].type.getTypeName() + \"'\");\n                            }\n                            break;\n                        }\n\n                        // clean the type\n                        //if (hadProvisionalErrors) {\n                        //    this.typeCheckWithContextualType(null, true, true, args.members[j]);\n                        //    if (!this.sourceIsAssignableToTarget(args.members[j].type, memberType)) {\n                        //        miss = true;\n                        //    }\n\n                        //    this.cleanStartedPTO();\n                        //}\n\n                        this.resetProvisionalErrors();\n                        if (miss) {\n                            break;\n                        }\n                    }\n                }\n\n                if (j == args.members.length) {\n                    applicableSigs[applicableSigs.length] = { signature: signatures[i], hadProvisionalErrors: hadProvisionalErrors };\n                }\n                hadProvisionalErrors = false;\n            }\n\n            return applicableSigs;\n        }\n\n        public canContextuallyTypeFunction(candidateType: Type, funcDecl: FuncDecl, beStringent: bool): bool {\n\n            // in these cases, we do not attempt to apply a contextual type\n            //  RE: isInlineCallLiteral - if the call target is a function literal, we don't want to apply the target type\n            //  to its body - instead, it should be applied to its return type\n            if (funcDecl.isParenthesized ||\n                funcDecl.isMethod() ||\n                beStringent && funcDecl.returnTypeAnnotation ||\n                funcDecl.isInlineCallLiteral) {\n                return false;\n            }\n\n            beStringent = beStringent || (this.typeFlow.functionInterfaceType == candidateType);\n\n            // At this point, if we're not being stringent, there's no need to check for multiple call sigs\n            // or count parameters - we just want to unblock typecheck\n            if (!beStringent) {\n                return true;\n            }\n\n            // If we're coming from an in-scope typecheck, lambdas may not have had function signatures created for them\n            // REVIEW: Should we search out the overload group here?\n            if (!funcDecl.signature) {\n                this.createFunctionSignature(funcDecl, this.typeFlow.scope.container, this.typeFlow.scope, null, null);\n                this.typeFlow.typeCheck(funcDecl);\n            }\n\n            var signature = funcDecl.signature;\n            var paramLen = signature.parameters.length;\n\n            // Check that the argument declarations have no type annotations\n            for (var i = 0; i < paramLen; i++) {\n                var param = signature.parameters[i];\n                var symbol = <ParameterSymbol>param;\n                var argDecl = <ArgDecl>symbol.declAST;\n\n                // REVIEW: a valid typeExpr is a requirement for varargs,\n                // so we may want to revise our invariant\n                if (beStringent && argDecl.typeExpr) {\n                    return false;\n                }\n            }\n\n            if (candidateType.construct && candidateType.call) {\n                return false;\n            }\n\n            var candidateSigs = candidateType.construct ? candidateType.construct : candidateType.call;\n\n            if (!candidateSigs || candidateSigs.signatures.length > 1) {\n                return false;\n            }\n\n            // if we're here, the contextual type can be applied to the function\n            return true;\n        }\n\n        public canContextuallyTypeObjectLiteral(targetType: Type, objectLit: UnaryExpression): bool {\n\n            if (targetType == this.typeFlow.objectInterfaceType) {\n                return true;\n            }\n\n            var memberDecls = <ASTList>objectLit.operand;\n\n            if (!(memberDecls && targetType.memberScope)) {\n                return false;\n            }\n\n            var id: AST = null;\n            var targetMember: Symbol = null;\n            var text = \"\";\n            var foundSyms = {};\n\n            // Check that each property in the object literal is present in the target\n            // type\n            for (var i = 0; i < memberDecls.members.length; i++) {\n                id = (<BinaryExpression>memberDecls.members[i]).operand1;\n\n                if (id.nodeType == NodeType.Name) {\n                    text = (<Identifier>id).text;\n                }\n                else if (id.nodeType == NodeType.QString) {\n                    // TODO: set text to unescaped string\n                    var idText = (<StringLiteral>id).text;\n                    text = idText.substring(1, idText.length - 1);\n                }\n                else {\n                    return false;\n                }\n\n                targetMember = targetType.memberScope.find(text, true, false);\n\n                if (!targetMember) {\n                    return false;\n                }\n\n                foundSyms[text] = true;\n            }\n\n            // Check that all members in the target type are present in the object literal\n            var targetMembers = targetType.memberScope.getAllValueSymbolNames(true);\n\n            for (var i = 0; i < targetMembers.length; i++) {\n                var memberName = targetMembers[i];\n                var memberSym = targetType.memberScope.find(memberName, true, false);\n\n                if (!foundSyms[targetMembers[i]] &&\n                    !hasFlag(memberSym.flags, SymbolFlags.Optional)) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        public widenType(t: Type) {\n            if (t == this.undefinedType || t == this.nullType) { // REVIEW: not isNullOrUndefinedType for perf reasons\n                return this.anyType;\n            }\n\n            return t;\n        }\n\n        public isNullOrUndefinedType(t: Type) {\n            return t == this.undefinedType || t == this.nullType;\n        }\n\n        public findBestCommonType(initialType: Type, targetType: Type, collection: ITypeCollection, acceptVoid:bool, comparisonInfo?: TypeComparisonInfo) {\n            var i = 0;\n            var len = collection.getLength();\n            var nlastChecked = 0;\n            var bestCommonType = initialType;\n\n            if (targetType) {\n                bestCommonType = bestCommonType ? bestCommonType.mergeOrdered(targetType, this, acceptVoid) : targetType;\n            }\n\n            // it's important that we set the convergence type here, and not in the loop,\n            // since the first element considered may be the contextual type\n            var convergenceType: Type = bestCommonType;\n\n            while (nlastChecked < len) {\n\n                for (i = 0; i < len; i++) {\n\n                    // no use in comparing a type against itself\n                    if (i == nlastChecked) {\n                        continue;\n                    }\n\n                    if (convergenceType && (bestCommonType = convergenceType.mergeOrdered(collection.getTypeAtIndex(i), this, acceptVoid, comparisonInfo))) {\n                        convergenceType = bestCommonType;\n                    }\n\n                    if (bestCommonType == this.anyType || bestCommonType == null) {\n                        break;\n                    }\n                    else if (targetType) { // set the element type to the target type\n                        collection.setTypeAtIndex(i, targetType);\n                    }\n                }\n\n                // use the type if we've agreed upon it\n                if (convergenceType && bestCommonType) {\n                    break;\n                }\n\n                nlastChecked++;\n                if (nlastChecked < len) {\n                    convergenceType = collection.getTypeAtIndex(nlastChecked);\n                }\n            }\n\n            return acceptVoid ? bestCommonType : (bestCommonType == this.voidType ? null : bestCommonType);\n        }\n\n        // Type Identity\n\n        public typesAreIdentical(t1: Type, t2: Type) {\n\n            // This clause will cover both primitive types (since the type objects are shared),\n            // as well as shared brands\n            if (t1 == t2) {\n                return true;\n            }\n\n            if (!t1 || !t2) {\n                return false;\n            }\n\n            if (t1.isClass() || t1.isClassInstance()) {\n                return false;\n            }\n\n            var comboId = (t2.typeID << 16) | t1.typeID;\n\n            if (this.identicalCache[comboId]) {\n                return true;\n            }\n\n            // If one is an enum, and they're not the same type, they're not identical\n            if ((t1.typeFlags & TypeFlags.IsEnum) || (t2.typeFlags & TypeFlags.IsEnum)) {\n                return false;\n            }\n\n            if (t1.isArray() || t2.isArray()) {\n                if (!(t1.isArray() && t2.isArray())) {\n                    return false;\n                }\n                this.identicalCache[comboId] = false;\n                var ret = this.typesAreIdentical(t1.elementType, t2.elementType);\n                if (ret) {\n                    this.subtypeCache[comboId] = true;\n                }\n                else {\n                    this.subtypeCache[comboId] = undefined;\n                }\n\n                return ret;\n            }\n\n            if (t1.primitiveTypeClass != t2.primitiveTypeClass) {\n                return false;\n            }\n\n            this.identicalCache[comboId] = false;\n\n            // properties are identical in name, optionality, and type\n            // REVIEW: TypeChanges - The compiler does not currently check against the members of parent types!\n            // REVIEW: TypeChanges - What about ambientMembers?\n            if (t1.memberScope && t2.memberScope) {\n                var t1MemberKeys = t1.memberScope.getAllValueSymbolNames(true).sort();\n                var t2MemberKeys = t2.memberScope.getAllValueSymbolNames(true).sort();\n\n                if (t1MemberKeys.length != t2MemberKeys.length) {\n                    this.identicalCache[comboId] = undefined;\n                    return false;\n                }\n\n                var t1MemberSymbol: Symbol = null;\n                var t2MemberSymbol: Symbol = null;\n\n                var t1MemberType: Type = null;\n                var t2MemberType: Type = null;\n\n                for (var iMember = 0; iMember < t1MemberKeys.length; iMember++) {\n                    if (t1MemberKeys[iMember] != t2MemberKeys[iMember]) {\n                        this.identicalCache[comboId] = undefined;\n                        return false;\n                    }\n\n                    t1MemberSymbol = <Symbol>t1.memberScope.find(t1MemberKeys[iMember], false, false);\n                    t2MemberSymbol = <Symbol>t2.memberScope.find(t2MemberKeys[iMember], false, false);\n\n                    if ((t1MemberSymbol.flags & SymbolFlags.Optional) != (t2MemberSymbol.flags & SymbolFlags.Optional)) {\n                        this.identicalCache[comboId] = undefined;\n                        return false;\n                    }\n\n                    t1MemberType = t1MemberSymbol.getType();\n                    t2MemberType = t2MemberSymbol.getType();\n\n                    // catch the mutually recursive or cached cases\n                    if (t1MemberType && t2MemberType && (this.identicalCache[(t2MemberType.typeID << 16) | t1MemberType.typeID] != undefined)) {\n                        continue;\n                    }\n\n                    if (!this.typesAreIdentical(t1MemberType, t2MemberType)) {\n                        this.identicalCache[comboId] = undefined;\n                        return false;\n                    }\n                }\n            }\n            else if (t1.memberScope || t2.memberScope) {\n                this.identicalCache[comboId] = undefined;\n                return false;\n            }\n\n            if (!this.signatureGroupsAreIdentical(t1.call, t2.call)) {\n                this.identicalCache[comboId] = undefined;\n                return false;\n            }\n\n            if (!this.signatureGroupsAreIdentical(t1.construct, t2.construct)) {\n                this.identicalCache[comboId] = undefined;\n                return false;\n            }\n\n            if (!this.signatureGroupsAreIdentical(t1.index, t2.index)) {\n                this.identicalCache[comboId] = undefined;\n                return false;\n            }\n\n            this.identicalCache[comboId] = true;\n            return true;\n        }\n\n        public signatureGroupsAreIdentical(sg1: SignatureGroup, sg2: SignatureGroup) {\n\n            // covers the null case\n            if (sg1 == sg2) {\n                return true;\n            }\n\n            // covers the mixed-null case\n            if (!sg1 || !sg2) {\n                return false;\n            }\n\n            if (sg1.signatures.length != sg2.signatures.length) {\n                return false;\n            }\n\n            var sig1: Signature = null;\n            var sig2: Signature = null;\n            var sigsMatch = false;\n\n            // The signatures in the signature group may not be ordered...\n            // REVIEW: Should definition signatures be required to be identical as well?\n            for (var iSig1 = 0; iSig1 < sg1.signatures.length; iSig1++) {\n                sig1 = sg1.signatures[iSig1];\n\n                for (var iSig2 = 0; iSig2 < sg2.signatures.length; iSig2++) {\n                    sig2 = sg2.signatures[iSig2];\n\n                    if (this.signaturesAreIdentical(sig1, sig2)) {\n                        sigsMatch = true;\n                        break;\n                    }\n                }\n\n                if (sigsMatch) {\n                    sigsMatch = false;\n                    continue;\n                }\n\n                // no match found for a specific signature\n                return false;\n            }\n\n            return true;\n        }\n\n        public signaturesAreIdentical(s1: Signature, s2: Signature) {\n\n            if (s1.hasVariableArgList != s2.hasVariableArgList) {\n                return false;\n            }\n\n            if (s1.nonOptionalParameterCount != s2.nonOptionalParameterCount) {\n                return false;\n            }\n\n            if (s1.parameters.length != s2.parameters.length) {\n                return false;\n            }\n\n            if (!this.typesAreIdentical(s1.returnType.type, s2.returnType.type)) {\n                return false;\n            }\n\n            for (var iParam = 0; iParam < s1.parameters.length; iParam++) {\n                if (!this.typesAreIdentical(s1.parameters[iParam].parameter.typeLink.type, s2.parameters[iParam].parameter.typeLink.type)) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        // Subtyping and Assignment compatibility\n\n        public sourceIsSubtypeOfTarget(source: Type, target: Type, comparisonInfo?: TypeComparisonInfo) { return this.sourceIsRelatableToTarget(source, target, false, this.subtypeCache, comparisonInfo); }\n        public signatureGroupIsSubtypeOfTarget(sg1: SignatureGroup, sg2: SignatureGroup, comparisonInfo?: TypeComparisonInfo) { return this.signatureGroupIsRelatableToTarget(sg1, sg2, false, this.subtypeCache, comparisonInfo); }\n        public signatureIsSubtypeOfTarget(s1: Signature, s2: Signature, comparisonInfo?: TypeComparisonInfo) { return this.signatureIsRelatableToTarget(s1, s2, false, this.subtypeCache, comparisonInfo); }\n\n        public sourceIsAssignableToTarget(source: Type, target: Type, comparisonInfo?: TypeComparisonInfo) { return this.sourceIsRelatableToTarget(source, target, true, this.assignableCache, comparisonInfo); }\n        public signatureGroupIsAssignableToTarget(sg1: SignatureGroup, sg2: SignatureGroup, comparisonInfo?: TypeComparisonInfo) { return this.signatureGroupIsRelatableToTarget(sg1, sg2, true, this.assignableCache, comparisonInfo); }\n        public signatureIsAssignableToTarget(s1: Signature, s2: Signature, comparisonInfo?: TypeComparisonInfo) { return this.signatureIsRelatableToTarget(s1, s2, true, this.assignableCache, comparisonInfo); }\n\n        public sourceIsRelatableToTarget(source: Type, target: Type, assignableTo: bool, comparisonCache: any, comparisonInfo: TypeComparisonInfo) {\n\n            // REVIEW: Does this check even matter?\n            //if (this.typesAreIdentical(source, target)) {\n            //    return true;\n            //}\n            if (source == target) {\n                return true;\n            }\n\n            // An error has already been reported in this case\n            if (!(source && target)) {\n                return true;\n            }\n\n            var comboId = (source.typeID << 16) | target.typeID;\n\n            // In the case of a 'false', we want to short-circuit a recursive typecheck\n            if (comparisonCache[comboId] != undefined) {\n                return true;\n            }\n\n            // this is one difference between subtyping and assignment compatibility\n            if (assignableTo) {\n                if (source == this.anyType || target == this.anyType) {\n                    return true;\n                }\n            }\n            else {\n                // This is one difference between assignment compatibility and subtyping\n                if (target == this.anyType) {\n                    return true;\n                }\n            }\n\n            if (source == this.undefinedType) {\n                return true;\n            }\n\n            if ((source == this.nullType) && (target != this.undefinedType && target != this.voidType)) {\n                return true;\n            }\n\n            // REVIEW: enum types aren't explicitly covered in the spec\n            if (target == this.numberType && (source.typeFlags & TypeFlags.IsEnum)) {\n                return true;\n            }\n            if (source == this.numberType && (target.typeFlags & TypeFlags.IsEnum)) {\n                return true;\n            }\n            if ((source.typeFlags & TypeFlags.IsEnum) || (target.typeFlags & TypeFlags.IsEnum)) {\n                return false;\n            }\n\n            if (source.isArray() || target.isArray()) {\n                if (!(source.isArray() && target.isArray())) {\n                    return false;\n                }\n                comparisonCache[comboId] = false;\n                var ret = this.sourceIsRelatableToTarget(source.elementType, target.elementType, assignableTo, comparisonCache, comparisonInfo);\n                if (ret) {\n                    comparisonCache[comboId] = true;\n                }\n                else {\n                    comparisonCache[comboId] = undefined;\n                }\n\n                return ret;\n            }\n\n            // this check ensures that we only operate on object types from this point forward,\n            // since the checks involving primitives occurred above\n            if (source.primitiveTypeClass != target.primitiveTypeClass) {\n\n                if (target.primitiveTypeClass == Primitive.None) {\n                    if (source == this.numberType && this.typeFlow.numberInterfaceType) {\n                        source = this.typeFlow.numberInterfaceType;\n                    }\n                    else if (source == this.stringType && this.typeFlow.stringInterfaceType) {\n                        source = this.typeFlow.stringInterfaceType;\n                    }\n                    else if (source == this.booleanType && this.typeFlow.booleanInterfaceType) {\n                        source = this.typeFlow.booleanInterfaceType;\n                    }\n                    else {\n                        return false;\n                    }\n                }\n                else {\n                    return false;\n                }\n            }\n\n            comparisonCache[comboId] = false;\n\n            if (source.hasBase(target)) {\n                comparisonCache[comboId] = true;\n                return true;\n            }\n\n            if (this.typeFlow.objectInterfaceType && target == this.typeFlow.objectInterfaceType) {\n                return true;\n            }\n\n            if (this.typeFlow.functionInterfaceType && (source.call || source.construct) && target == this.typeFlow.functionInterfaceType) {\n                return true;\n            }\n\n            // REVIEW: We should perhaps do this, though it wouldn't be quite right without generics support\n            //if (this.typeFlow.arrayInterfaceType && (source.index) && target == this.typeFlow.arrayInterfaceType) {\n            //    return true;\n            //}\n\n            // At this point, if the target is a class, but not the source or a parent of the source, bail\n            if (target.isClass() || target.isClassInstance()) {\n                comparisonCache[comboId] = undefined;\n                return false;\n            }\n\n            if (target.memberScope && source.memberScope) {\n                var mPropKeys = target.memberScope.getAllValueSymbolNames(true);\n                var mProp: Symbol = null;\n                var nProp: Symbol = null;\n                var mPropType: Type = null;\n                var nPropType: Type = null;\n                var inferenceSymbol: InferenceSymbol = null;\n\n                for (var iMProp = 0; iMProp < mPropKeys.length; iMProp++) {\n                    mProp = target.memberScope.find(mPropKeys[iMProp], false, false);\n                    nProp = source.memberScope.find(mPropKeys[iMProp], false, false);\n\n                    // methods do not have the \"arguments\" field\n                    if (mProp.name == \"arguments\" &&\n                        this.typeFlow.iargumentsInterfaceType &&\n                        (this.typeFlow.iargumentsInterfaceType.symbol.flags & SymbolFlags.CompilerGenerated) &&\n                        mProp.kind() == SymbolKind.Variable &&\n                        (<VariableSymbol>mProp).variable.typeLink.type == this.typeFlow.iargumentsInterfaceType) {\n                        continue;\n                    }\n\n                    if (mProp.isInferenceSymbol()) {\n                        inferenceSymbol = <InferenceSymbol>mProp;\n                        if (inferenceSymbol.typeCheckStatus == TypeCheckStatus.NotStarted) {\n                            // REVIEW: TypeChanges: Does this ever really happen?  Maybe for out-of-order typecheck?\n                            this.typeFlow.typeCheck(mProp.declAST);\n                        }\n                    }\n                    mPropType = mProp.getType();\n\n                    if (!nProp) {\n                        // If it's not present on the type in question, look for the property on 'Object'\n                        if (this.typeFlow.objectInterfaceType) {\n                            nProp = this.typeFlow.objectInterfaceType.memberScope.find(mPropKeys[iMProp], false, false);\n                        }\n\n                        if (!nProp) {\n                            // Now, the property was not found on Object, but the type in question is a function, look\n                            // for it on function\n                            if (this.typeFlow.functionInterfaceType && (mPropType.call || mPropType.construct)) {\n                                nProp = this.typeFlow.functionInterfaceType.memberScope.find(mPropKeys[iMProp], false, false);\n                            }\n\n                            // finally, check to see if the property is optional\n                            if (!nProp) {\n                                if (!(mProp.flags & SymbolFlags.Optional)) {\n                                    comparisonCache[comboId] = undefined;\n                                    if (comparisonInfo) { // only surface the first error\n                                        comparisonInfo.flags |= TypeRelationshipFlags.RequiredPropertyIsMissing;\n                                        comparisonInfo.addMessageToFront(\"Type '\" + source.getTypeName() + \"' is missing property '\" + mPropKeys[iMProp] + \"' from type '\" + target.getTypeName() + \"'\");\n                                    }\n                                    return false;\n                                }\n                                else {\n                                    continue;\n                                }\n                            }\n                        }\n                    }\n\n                    if (nProp.isInferenceSymbol()) {\n                        inferenceSymbol = <InferenceSymbol>nProp;\n                        if (inferenceSymbol.typeCheckStatus == TypeCheckStatus.NotStarted) {\n                            this.typeFlow.typeCheck(nProp.declAST);\n                        }\n                    }\n\n\n                    nPropType = nProp.getType();\n\n                    // catch the mutually recursive or cached cases\n                    if (mPropType && nPropType && (comparisonCache[(nPropType.typeID << 16) | mPropType.typeID] != undefined)) {\n                        continue;\n                    }\n\n                    if (!this.sourceIsRelatableToTarget(nPropType, mPropType, assignableTo, comparisonCache, comparisonInfo)) {\n                        comparisonCache[comboId] = undefined;\n                        if (comparisonInfo) { // only surface the first error\n                            comparisonInfo.flags |= TypeRelationshipFlags.IncompatiblePropertyTypes;\n                            comparisonInfo.addMessageToFront(\"Types of property '\" + mProp.name + \"' of types '\" + source.getTypeName() + \"' and '\" + target.getTypeName() + \"' are incompatible\");\n                        }\n                        return false;\n                    }\n                }\n            }\n\n            // check signature groups\n            if (source.call || target.call) {\n                if (!this.signatureGroupIsRelatableToTarget(source.call, target.call, assignableTo, comparisonCache, comparisonInfo)) {\n                    if (comparisonInfo) {\n                        if (source.call && target.call) {\n                            comparisonInfo.addMessageToFront(\"Call signatures of types '\" + source.getTypeName() + \"' and '\" + target.getTypeName() + \"' are incompatible\");\n                        }\n                        else {\n                            var hasSig = target.call ? target.getTypeName() : source.getTypeName();\n                            var lacksSig = !target.call ? target.getTypeName() : source.getTypeName();\n                            comparisonInfo.setMessage(\"Type '\" + hasSig + \"' requires a call signature, but Type '\" + lacksSig + \"' lacks one\");\n                        }\n                        comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleSignatures;\n                    }\n                    comparisonCache[comboId] = undefined;\n                    return false;\n                }\n            }\n\n            if (source.construct || target.construct) {\n                if (!this.signatureGroupIsRelatableToTarget(source.construct, target.construct, assignableTo, comparisonCache, comparisonInfo)) {\n                    if (comparisonInfo) {\n                        if (source.construct && target.construct) {\n                            comparisonInfo.addMessageToFront(\"Construct signatures of types '\" + source.getTypeName() + \"' and '\" + target.getTypeName() + \"' are incompatible\");\n                        }\n                        else {\n                            var hasSig = target.construct ? target.getTypeName() : source.getTypeName();\n                            var lacksSig = !target.construct ? target.getTypeName() : source.getTypeName();\n                            comparisonInfo.setMessage(\"Type '\" + hasSig + \"' requires a construct signature, but Type '\" + lacksSig + \"' lacks one\");\n                        }\n                        comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleSignatures;\n                    }\n                    comparisonCache[comboId] = undefined;\n                    return false;\n                }\n            }\n\n            if (target.index) {\n                var targetIndex = !target.index && this.typeFlow.objectInterfaceType ? this.typeFlow.objectInterfaceType.index : target.index;\n                var sourceIndex = !source.index && this.typeFlow.objectInterfaceType ? this.typeFlow.objectInterfaceType.index : source.index;\n\n                if (!this.signatureGroupIsRelatableToTarget(sourceIndex, targetIndex, assignableTo, comparisonCache, comparisonInfo)) {\n                    if (comparisonInfo) {\n                        comparisonInfo.addMessageToFront(\"Index signatures of types '\" + source.getTypeName() + \"' and '\" + target.getTypeName() + \"' are incompatible\");\n                        comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleSignatures;\n                    }\n                    comparisonCache[comboId] = undefined;\n                    return false;\n                }\n            }\n\n            comparisonCache[comboId] = true;\n            return true;\n        }\n\n        // REVIEW: TypeChanges: Return an error context object so the user can get better diagnostic info\n        public signatureGroupIsRelatableToTarget(sourceSG: SignatureGroup, targetSG: SignatureGroup, assignableTo: bool, comparisonCache: any, comparisonInfo?: TypeComparisonInfo) {\n            if (sourceSG == targetSG) {\n                return true;\n            }\n\n            if (!(sourceSG && targetSG)) {\n                return false;\n            }\n\n            var mSig: Signature = null;\n            var nSig: Signature = null;\n            var foundMatch = false;\n\n            for (var iMSig = 0; iMSig < targetSG.signatures.length; iMSig++) {\n                mSig = targetSG.signatures[iMSig];\n\n                for (var iNSig = 0; iNSig < sourceSG.signatures.length; iNSig++) {\n                    nSig = sourceSG.signatures[iNSig];\n                    if (this.signatureIsRelatableToTarget(nSig, mSig, assignableTo, comparisonCache, comparisonInfo)) {\n                        foundMatch = true;\n                        break;\n                    }\n                }\n\n                if (foundMatch) {\n                    foundMatch = false;\n                    continue;\n                }\n                return false;\n            }\n\n            return true;\n        }\n\n        public signatureIsRelatableToTarget(sourceSig: Signature, targetSig: Signature, assignableTo: bool, comparisonCache: any, comparisonInfo?: TypeComparisonInfo) {\n\n            if (!sourceSig.parameters || !targetSig.parameters) {\n                return false;\n            }\n\n            var targetVarArgCount = targetSig.hasVariableArgList ? targetSig.nonOptionalParameterCount - 1 : targetSig.nonOptionalParameterCount;\n            var sourceVarArgCount = sourceSig.hasVariableArgList ? sourceSig.nonOptionalParameterCount - 1 : sourceSig.nonOptionalParameterCount;\n\n            if (sourceVarArgCount > targetVarArgCount && !targetSig.hasVariableArgList) {\n                if (comparisonInfo) {\n                    comparisonInfo.flags |= TypeRelationshipFlags.SourceSignatureHasTooManyParameters;\n                    comparisonInfo.addMessageToFront(\"Call signature expects \" + targetVarArgCount + \" or fewer parameters\");\n                }\n                return false;\n            }\n\n            var sourceReturnType = sourceSig.returnType.type;\n            var targetReturnType = targetSig.returnType.type;\n\n            if (targetReturnType != this.voidType) {\n                if (!this.sourceIsRelatableToTarget(sourceReturnType, targetReturnType, assignableTo, comparisonCache, comparisonInfo)) {\n                    if (comparisonInfo) {\n                        comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleReturnTypes;\n                        // No need to print this one here - it's printed as part of the signature error in sourceIsRelatableToTarget\n                        //comparisonInfo.addMessageToFront(\"Incompatible return types: '\" + sourceReturnType.getTypeName() + \"' and '\" + targetReturnType.getTypeName() + \"'\");\n                    }\n                    return false;\n                }\n            }\n\n            var len = (sourceVarArgCount < targetVarArgCount && sourceSig.hasVariableArgList) ? targetVarArgCount : sourceVarArgCount;\n            var sourceParamType: Type = null;\n            var targetParamType: Type = null;\n            var sourceParamName = \"\";\n            var targetParamName = \"\";\n\n            for (var iSource = 0, iTarget = 0; iSource < len; iSource++, iTarget++) {\n\n                if (!sourceSig.hasVariableArgList || iSource < sourceVarArgCount) {\n                    sourceParamType = (<ParameterSymbol>sourceSig.parameters[iSource]).parameter.typeLink.type;\n                    sourceParamName = (<ParameterSymbol>sourceSig.parameters[iSource]).parameter.symbol.name;\n                }\n                else if (iSource == sourceVarArgCount) {\n                    sourceParamType = (<ParameterSymbol>sourceSig.parameters[iSource]).parameter.typeLink.type;\n                    if (sourceParamType.elementType) {\n                        sourceParamType = sourceParamType.elementType;\n                    }\n                    sourceParamName = (<ParameterSymbol>sourceSig.parameters[iSource]).parameter.symbol.name;\n                }\n\n                if (iTarget < targetSig.parameters.length && iTarget < targetVarArgCount) {\n                    targetParamType = (<ParameterSymbol>targetSig.parameters[iTarget]).parameter.typeLink.type;\n                    targetParamName = (<ParameterSymbol>targetSig.parameters[iTarget]).parameter.symbol.name;\n                }\n                else if (targetSig.hasVariableArgList && iTarget == targetVarArgCount) {\n                    targetParamType = (<ParameterSymbol>targetSig.parameters[iTarget]).parameter.typeLink.type;\n                    if (targetParamType.elementType) {\n                        targetParamType = targetParamType.elementType;\n                    }\n                    targetParamName = (<ParameterSymbol>targetSig.parameters[iTarget]).parameter.symbol.name;\n                }\n\n                if (!(this.sourceIsRelatableToTarget(sourceParamType, targetParamType, assignableTo, comparisonCache, comparisonInfo) ||\n                        this.sourceIsRelatableToTarget(targetParamType, sourceParamType, assignableTo, comparisonCache, comparisonInfo))) {\n\n                    if (comparisonInfo) {\n                        comparisonInfo.flags |= TypeRelationshipFlags.IncompatibleParameterTypes;\n                    }\n                    return false;\n                }\n            }\n            return true;\n        }\n    }\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export class Continuation {\n        public exceptionBlock = -1;\n        constructor (public normalBlock: number) { }\n    }\n\n    function getBaseTypeLinks(bases: ASTList, baseTypeLinks: TypeLink[]) {\n        if (bases) {\n            var len = bases.members.length;\n            if (baseTypeLinks == null) {\n                baseTypeLinks = new TypeLink[];\n            }\n            for (var i = 0; i < len; i++) {\n                var baseExpr = bases.members[i];\n                var name = baseExpr;\n                var typeLink = new TypeLink();\n                typeLink.ast = name;\n                baseTypeLinks[baseTypeLinks.length] = typeLink;\n            }\n        }\n        return baseTypeLinks;\n    }\n\n    function getBases(type: Type, typeDecl: TypeDeclaration) {\n        type.extendsTypeLinks = getBaseTypeLinks(typeDecl.extendsList, type.extendsTypeLinks);\n        type.implementsTypeLinks = getBaseTypeLinks(typeDecl.implementsList, type.implementsTypeLinks);\n    }\n\n    function addPrototypeField(classType: Type, ast: AST, context: TypeCollectionContext) {\n        var field = new ValueLocation();\n        field.typeLink = new TypeLink();\n        field.typeLink.ast = ast;\n        field.typeLink.type = classType.instanceType;\n\n        var fieldSymbol =\n            new FieldSymbol(\"prototype\", ast.minChar,\n                            context.checker.locationInfo.unitIndex, true, field);\n        fieldSymbol.flags |= (SymbolFlags.Property | SymbolFlags.BuiltIn);\n        field.symbol = fieldSymbol;\n        fieldSymbol.declAST = ast;\n        classType.members.addPublicMember(\"prototype\", fieldSymbol);\n    }\n\n    export function createNewConstructGroupForType(type: Type) {\n        var signature = new Signature();\n        signature.returnType = new TypeLink();\n        signature.returnType.type = type.instanceType;\n        signature.parameters = [];\n\n        type.construct = new SignatureGroup();\n        type.construct.addSignature(signature);     \n    }\n\n    export function cloneParentConstructGroupForChildType(child: Type, parent: Type) {\n        child.construct = new SignatureGroup();\n        var sig: Signature = null;\n\n        if (!parent.construct) {\n            createNewConstructGroupForType(parent);\n        }\n\n        for (var i = 0; i < parent.construct.signatures.length; i++) { \n            sig = new Signature();\n            sig.parameters = parent.construct.signatures[i].parameters;\n            sig.nonOptionalParameterCount = parent.construct.signatures[i].nonOptionalParameterCount;\n            sig.typeCheckStatus = parent.construct.signatures[i].typeCheckStatus;\n            sig.declAST = parent.construct.signatures[i].declAST;\n            sig.returnType = new TypeLink();\n            sig.returnType.type = child.instanceType;\n            child.construct.addSignature(sig);\n        }\n\n    }\n\n    export var globalId = \"__GLO\";\n\n    export interface IAliasScopeContext {\n        topLevelScope: ScopeChain;\n        members: IHashTable;\n        tcContext: TypeCollectionContext;\n    }\n\n    function findTypeSymbolInScopeChain(name: string, scopeChain: ScopeChain): Symbol {\n        var symbol = scopeChain.scope.find(name, false, true);\n\n        if (symbol == null && scopeChain.previous) {\n            symbol = findTypeSymbolInScopeChain(name, scopeChain.previous);\n        }\n\n        return symbol;\n    }\n\n    function findSymbolFromAlias(alias: AST, context: IAliasScopeContext): Symbol {\n        var symbol: Symbol = null;\n        switch (alias.nodeType) {\n            case NodeType.Name:\n                var name = (<Identifier>alias).text;\n                var isDynamic = isQuoted(name);\n\n                var findSym = (id: string) => {\n                    if (context.members) {\n                        return context.members.lookup(name);\n                    }\n                    else {\n                        return findTypeSymbolInScopeChain(name, context.topLevelScope);\n                    }\n                }\n\n                if (isDynamic) {\n                    symbol = context.tcContext.checker.findSymbolForDynamicModule(name, context.tcContext.script.locationInfo.filename, findSym);\n                }\n                else {\n                    symbol = findSym(name);\n                }\n\n                break;\n\n            case NodeType.Dot:\n                var dottedExpr = <BinaryExpression>alias;\n                var op1Sym = findSymbolFromAlias(dottedExpr.operand1, context);\n\n                if (op1Sym && op1Sym.getType()) {\n                    symbol = findSymbolFromAlias(dottedExpr.operand2, context);\n                }\n\n                break;\n\n            default:\n                break;\n        }\n\n        if (symbol) {\n            var symType = symbol.getType();\n            if (symType) {\n                var members = symType.members;\n                if (members) {\n                    context.members = members.publicMembers;\n                }\n            }\n        }\n\n        return symbol;\n    }\n\n    export function preCollectImportTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n        var scopeChain = context.scopeChain;\n        var typeSymbol: TypeSymbol = null;\n        var modType: ModuleType = null;\n        var importDecl = <ImportDeclaration>ast;\n\n        // REVIEW: technically, this call isn't strictly necessary, since we'll find the type during the call to resolveTypeMembers\n        var aliasedModSymbol = findSymbolFromAlias(importDecl.alias, { topLevelScope: scopeChain, members: null, tcContext: context });\n        var isGlobal = context.scopeChain.container == context.checker.gloMod;\n\n        if (aliasedModSymbol) {\n            var aliasedModType = aliasedModSymbol.getType();\n\n            if (aliasedModType) {\n                modType = <ModuleType>aliasedModType;\n            }\n        }\n\n        typeSymbol = new TypeSymbol(importDecl.id.text, importDecl.id.minChar, importDecl.limChar - importDecl.minChar,\n                                    context.checker.locationInfo.unitIndex, modType);\n\n        typeSymbol.aliasLink = importDecl;\n\n        if (context.scopeChain.moduleDecl) {\n            typeSymbol.flags |= SymbolFlags.ModuleMember;\n            typeSymbol.declModule = context.scopeChain.moduleDecl;\n        }\n\n        typeSymbol.declAST = importDecl;\n        importDecl.id.sym = typeSymbol;\n        scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,\n                                context.checker.errorReporter, isGlobal, true, false);\n        scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,\n                                context.checker.errorReporter, isGlobal, false, false);\n        return true;\n    }\n\n    export function preCollectModuleTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n        var scopeChain = context.scopeChain;\n\n        var moduleDecl: ModuleDeclaration = <ModuleDeclaration>ast;\n\n        var isAmbient = hasFlag(moduleDecl.modFlags, ModuleFlags.Ambient);\n        var isEnum = hasFlag(moduleDecl.modFlags, ModuleFlags.IsEnum);\n        var isGlobal = context.scopeChain.container == context.checker.gloMod;\n        var isExported = hasFlag(moduleDecl.modFlags, ModuleFlags.Exported);\n        var modName = (<Identifier>moduleDecl.name).text;\n\n        var isDynamic = isQuoted(modName);\n\n        var symbol = scopeChain.scope.findLocal(modName, false, false);\n        var typeSymbol: TypeSymbol = null;\n        var modType: ModuleType = null;\n        if ((symbol == null) || (symbol.kind() != SymbolKind.Type)) {\n\n            if (modType == null) {\n                var enclosedTypes = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n                var ambientEnclosedTypes = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n                modType = new ModuleType(enclosedTypes, ambientEnclosedTypes);\n                if (isEnum) {\n                    modType.typeFlags |= TypeFlags.IsEnum;\n                }\n                modType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n                modType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n                modType.setHasImplementation();\n            }\n\n            typeSymbol = new TypeSymbol(modName, moduleDecl.name.minChar, modName.length,\n                                        context.checker.locationInfo.unitIndex, modType);\n            typeSymbol.isDynamic = isQuoted(moduleDecl.prettyName);\n\n            if (context.scopeChain.moduleDecl) {\n                typeSymbol.declModule = context.scopeChain.moduleDecl;\n            }\n            typeSymbol.declAST = moduleDecl;\n            typeSymbol.prettyName = moduleDecl.prettyName;\n            scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,\n                                    context.checker.errorReporter, isExported || isGlobal, true, isAmbient);\n            scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,\n                                    context.checker.errorReporter, isExported || isGlobal, false, isAmbient);\n            modType.symbol = typeSymbol;\n        }\n        else {\n            if (symbol && symbol.declAST && symbol.declAST.nodeType != NodeType.ModuleDeclaration) {\n                context.checker.errorReporter.simpleError(moduleDecl, \"Conflicting symbol name for module '\" + modName + \"'\");\n            }\n            typeSymbol = <TypeSymbol>symbol;\n\n            // initialize new private scope for the type\n            var publicEnclosedTypes = typeSymbol.type.getAllEnclosedTypes().publicMembers;\n            var publicEnclosedTypesTable = (publicEnclosedTypes == null) ? new StringHashTable() : publicEnclosedTypes;\n            var enclosedTypes = new ScopedMembers(new DualStringHashTable(publicEnclosedTypesTable, new StringHashTable()));\n\n            var publicEnclosedAmbientTypes = typeSymbol.type.getAllAmbientEnclosedTypes().publicMembers;\n            var publicAmbientEnclosedTypesTable = (publicEnclosedAmbientTypes == null) ? new StringHashTable() : publicEnclosedAmbientTypes;\n            var ambientEnclosedTypes = new ScopedMembers(new DualStringHashTable(publicAmbientEnclosedTypesTable, new StringHashTable()));\n\n            var publicMembers = typeSymbol.type.members.publicMembers;\n            var publicMembersTable = (publicMembers == null) ? new StringHashTable() : publicMembers;\n            var members = new ScopedMembers(new DualStringHashTable(publicMembersTable, new StringHashTable()));\n\n            var publicAmbientMembers = typeSymbol.type.ambientMembers.publicMembers;\n            var publicAmbientMembersTable = (publicAmbientMembers == null) ? new StringHashTable() : publicAmbientMembers;\n            var ambientMembers = new ScopedMembers(new DualStringHashTable(publicAmbientMembersTable, new StringHashTable()));\n\n            modType = new ModuleType(enclosedTypes, ambientEnclosedTypes);\n            if (isEnum) {\n                modType.typeFlags |= TypeFlags.IsEnum;\n            }\n            modType.members = members;\n            modType.ambientMembers = ambientMembers;\n            modType.setHasImplementation();\n            modType.symbol = typeSymbol;\n\n            typeSymbol.addLocation(moduleDecl.minChar);\n            typeSymbol.expansions.push(modType);\n            typeSymbol.expansionsDeclAST.push(moduleDecl);\n\n        }\n        if (context.scopeChain.moduleDecl) {\n            context.scopeChain.moduleDecl.recordNonInterface();\n        }\n        // REVIEW: If multiple disparate module decls for the same module don't agree\n        // in export privileges, how should we handle it?\n        if (isExported) {\n            typeSymbol.flags |= SymbolFlags.Exported;\n        }\n        if ((context.scopeChain.moduleDecl) ||\n            (context.scopeChain.container == context.checker.gloMod)) {\n            typeSymbol.flags |= SymbolFlags.ModuleMember;\n        }\n\n        moduleDecl.mod = modType;\n        pushTypeCollectionScope(typeSymbol, modType.members,\n                                modType.ambientMembers,\n                                modType.enclosedTypes,\n                                modType.ambientEnclosedTypes,\n                                context, null, null, moduleDecl);\n\n        return true;\n    }\n\n    export function preCollectClassTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n        var scopeChain = context.scopeChain;\n        var classDecl = <ClassDeclaration>ast;\n\n        var classType: Type;\n        var instanceType: Type;\n        var typeSymbol: TypeSymbol = null;\n        var className = (<Identifier>classDecl.name).text;\n        var alreadyInScope = false;\n        var isAmbient = hasFlag(classDecl.varFlags, VarFlags.Ambient);\n        var isExported = hasFlag(classDecl.varFlags, VarFlags.Exported);\n        var isGlobal = context.scopeChain.container == context.checker.gloMod;\n        var containerMod = <TypeSymbol>scopeChain.container;\n        var foundValSymbol = false;\n\n        typeSymbol = <TypeSymbol>scopeChain.scope.findLocal(className, false, true);\n        \n        // check the value space, since an override may have been declared with the type's name\n        // REVIEW-CLASSES\n        if (!typeSymbol) {\n            var valTypeSymbol = scopeChain.scope.findLocal(className, false, false);\n            \n            if (valTypeSymbol &&\n                valTypeSymbol.isType() &&\n                valTypeSymbol.declAST &&\n                valTypeSymbol.declAST.nodeType == NodeType.FuncDecl &&\n                (<FuncDecl>valTypeSymbol.declAST).isSignature()) {\n                \n                typeSymbol = <TypeSymbol>valTypeSymbol;\n                foundValSymbol = true;\n                \n                if (isExported) {\n                    typeSymbol.flags |= SymbolFlags.Exported;\n                }\n            \n                if (isAmbient) {\n                    typeSymbol.flags |= SymbolFlags.Ambient;\n                }                \n                \n                // the class was never entered into type space, so add it\n                context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,\n                                            context.checker.errorReporter, isExported || isGlobal, true, isAmbient);                \n            }\n        }\n        \n        if (typeSymbol && !foundValSymbol && (typeSymbol.declAST != classDecl)) {\n            typeSymbol = null;\n        }\n\n        if (typeSymbol == null) {\n            var valueSymbol = scopeChain.scope.findLocal(className, false, false);\n            classType = new Type();\n            classType.setHasImplementation();\n            instanceType = new Type();\n            instanceType.setHasImplementation();\n            classType.instanceType = instanceType;\n            classType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n            classType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n            addPrototypeField(classType, classDecl, context);\n            instanceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n            instanceType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n            typeSymbol = new TypeSymbol(className, classDecl.name.minChar, className.length,\n                                        context.checker.locationInfo.unitIndex, classType);\n            typeSymbol.declAST = classDecl;\n            typeSymbol.instanceType = instanceType;\n            classType.symbol = typeSymbol;\n            instanceType.symbol = typeSymbol;\n\n            if (context.scopeChain.moduleDecl) {\n                context.scopeChain.moduleDecl.recordNonInterface();\n                typeSymbol.declModule = context.scopeChain.moduleDecl;\n                typeSymbol.flags |= SymbolFlags.ModuleMember;\n            }\n\n            if (isExported) {\n                typeSymbol.flags |= SymbolFlags.Exported;\n            }\n            \n            if (isAmbient) {\n                typeSymbol.flags |= SymbolFlags.Ambient;\n            }\n\n            ast.type = classType;\n\n            // class in both name spaces (type for instance type; constructor representative in value space)\n            context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,\n                                            context.checker.errorReporter, isExported || isGlobal, true, isAmbient);\n\n            if (valueSymbol == null) {\n                context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,\n                                            context.checker.errorReporter, isExported || isGlobal, false, isAmbient);\n            }\n        }\n        else {                            \n            classType = typeSymbol.type;\n            \n            // If the instance type is null, a call overload was likely declared before the class constructor\n            if (classType.instanceType == null) {\n                classType.instanceType = new Type();\n                classType.instanceType.setHasImplementation();\n                classType.instanceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n                classType.instanceType.symbol = classType.symbol;\n                classType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n                classType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n            }\n            \n            instanceType = classType.instanceType;\n            ast.type = classType;\n        }\n        \n        // if the class has no declared constructor, either create a default signature or adapt \n        // it's base class's signature group\n        if (!classDecl.constructorDecl) {\n\n            if (typeSymbol && typeSymbol.declAST && typeSymbol.declAST.type && typeSymbol.declAST.type.call && !(<FuncDecl>typeSymbol.declAST).isOverload) {\n                context.checker.errorReporter.duplicateIdentifier(typeSymbol.declAST, typeSymbol.name);\n            }\n\n            createNewConstructGroupForType(classDecl.type);\n        }\n\n        classType.typeFlags |= TypeFlags.IsClass;\n        instanceType.typeFlags |= TypeFlags.IsClass;\n\n        getBases(instanceType, classDecl);\n        pushTypeCollectionScope(typeSymbol, instanceType.members, instanceType.ambientMembers, null, null,\n                                context, instanceType, classType, null);\n        return true;\n    }\n\n    export function preCollectInterfaceTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n        var scopeChain = context.scopeChain;\n        var interfaceDecl = <InterfaceDeclaration>ast;\n        var interfaceSymbol: TypeSymbol = null;\n        var interfaceType: Type = null;\n        var isExported = hasFlag(interfaceDecl.varFlags, VarFlags.Exported);\n        var isGlobal = context.scopeChain.container == context.checker.gloMod;\n        var alreadyInScope = true;\n\n        alreadyInScope = false;\n        var interfaceName = (<Identifier>interfaceDecl.name).text;\n        interfaceSymbol = <TypeSymbol>scopeChain.scope.findLocal(interfaceName, false, true);\n        if (interfaceSymbol == null) {\n            interfaceType = new Type();\n            interfaceSymbol = new TypeSymbol(interfaceName,\n                                        interfaceDecl.name.minChar,\n                                        interfaceName.length,\n                                        context.checker.locationInfo.unitIndex,\n                                        interfaceType);\n            interfaceType.symbol = interfaceSymbol;\n            // REVIEW: Shouldn't allocate another table for interface privates\n            interfaceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n            interfaceType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n            interfaceSymbol.declAST = interfaceDecl;\n            interfaceSymbol.declModule = context.scopeChain.moduleDecl;\n        }\n        else {\n            alreadyInScope = true;\n            interfaceType = interfaceSymbol.type;\n        }\n\n        if (!interfaceType) {\n            interfaceType = context.checker.anyType;\n        }\n\n        ast.type = interfaceType;\n        getBases(interfaceType, interfaceDecl);\n\n        if (isExported) {\n            interfaceSymbol.flags |= SymbolFlags.Exported;\n        }\n\n        if (context.scopeChain.moduleDecl) {\n            interfaceSymbol.flags |= SymbolFlags.ModuleMember;\n        }\n\n        if (!alreadyInScope) {\n            context.scopeChain.scope.enter(context.scopeChain.container, ast,\n                                            interfaceSymbol, context.checker.errorReporter, isGlobal || isExported, true, false); // REVIEW: Technically, interfaces should be ambient\n        }\n        pushTypeCollectionScope(interfaceSymbol, interfaceType.members, interfaceType.ambientMembers, null, null,\n                                context, interfaceType, null, null);\n        return true;\n    }\n\n    export function preCollectArgDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n        var scopeChain = context.scopeChain;\n        var argDecl = <ArgDecl>ast;\n        if (hasFlag(argDecl.varFlags, VarFlags.Public | VarFlags.Private)) {\n            var field = new ValueLocation();\n            var isPrivate = hasFlag(argDecl.varFlags, VarFlags.Private);\n            var fieldSymbol =\n                new FieldSymbol(argDecl.id.text, argDecl.id.minChar,\n                                context.checker.locationInfo.unitIndex,\n                                !hasFlag(argDecl.varFlags, VarFlags.Readonly),\n                                field);\n            fieldSymbol.transferVarFlags(argDecl.varFlags);\n            field.symbol = fieldSymbol;\n            fieldSymbol.declAST = ast;\n            argDecl.parameterPropertySym = fieldSymbol;\n\n            context.scopeChain.scope.enter(context.scopeChain.container, ast,\n                                            fieldSymbol, context.checker.errorReporter, !isPrivate, false, false);\n\n            field.typeLink = getTypeLink(argDecl.typeExpr, context.checker, argDecl.init == null);\n            argDecl.sym = fieldSymbol;\n        }\n        return false;\n    }\n\n    export function preCollectVarDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n        var scopeChain = context.scopeChain;\n        var varDecl = <VarDecl>ast;\n        var isAmbient = hasFlag(varDecl.varFlags, VarFlags.Ambient);\n        var isExported = hasFlag(varDecl.varFlags, VarFlags.Exported);\n        var isGlobal = context.scopeChain.container == context.checker.gloMod;\n        var isProperty = hasFlag(varDecl.varFlags, VarFlags.Property);\n        var isStatic = hasFlag(varDecl.varFlags, VarFlags.Static);\n        var isPrivate = hasFlag(varDecl.varFlags, VarFlags.Private);\n        var isOptional = hasFlag(varDecl.id.flags, ASTFlags.OptionalName);\n\n        if (context.scopeChain.moduleDecl) {\n            context.scopeChain.moduleDecl.recordNonInterface();\n        }\n        if (isProperty ||\n            isExported ||\n            (context.scopeChain.container == context.checker.gloMod) ||\n            context.scopeChain.moduleDecl) {\n            if (isAmbient) {\n                var existingSym =\n                    <FieldSymbol>scopeChain.scope.findLocal(varDecl.id.text, false, false);\n                if (existingSym) {\n                    varDecl.sym = existingSym;\n                    return false;\n                }\n            }\n\n            // Defensive error detection...\n            if (varDecl.id == null) {\n                context.checker.errorReporter.simpleError(varDecl, \"Expected variable identifier at this location\");\n                return false;\n            }\n\n            var field = new ValueLocation();\n            var fieldSymbol =\n                new FieldSymbol(varDecl.id.text, varDecl.id.minChar,\n                                context.checker.locationInfo.unitIndex,\n                                (varDecl.varFlags & VarFlags.Readonly) == VarFlags.None,\n                                field);\n            fieldSymbol.transferVarFlags(varDecl.varFlags);\n            if (isOptional) {\n                fieldSymbol.flags |= SymbolFlags.Optional;\n            }\n            field.symbol = fieldSymbol;\n            fieldSymbol.declAST = ast;\n            if ((context.scopeChain.moduleDecl) ||\n                (context.scopeChain.container == context.checker.gloMod)) {\n                fieldSymbol.flags |= SymbolFlags.ModuleMember;\n                fieldSymbol.declModule = context.scopeChain.moduleDecl;\n            }\n\n            // if it's static, enter it into the class's member list directly\n            if (hasFlag(varDecl.varFlags, VarFlags.Property) && isStatic && context.scopeChain.classType) {\n                if (!context.scopeChain.classType.members.publicMembers.add(varDecl.id.text, fieldSymbol)) {\n                    context.checker.errorReporter.duplicateIdentifier(ast, fieldSymbol.name);\n                }\n                fieldSymbol.container = context.scopeChain.classType.symbol;\n            }\n            else {\n                context.scopeChain.scope.enter(context.scopeChain.container,\n                                                ast,\n                                                fieldSymbol,\n                                                context.checker.errorReporter,\n                                                !isPrivate && (isProperty || isExported || isGlobal || isStatic),\n                                                false,\n                                                isAmbient);\n            }\n\n            if (hasFlag(varDecl.varFlags, VarFlags.Exported)) {\n                fieldSymbol.flags |= SymbolFlags.Exported;\n            }\n\n            field.typeLink = getTypeLink(varDecl.typeExpr, context.checker,\n                                        varDecl.init == null);\n            varDecl.sym = fieldSymbol;\n        }\n        return false;\n    }\n\n    export function preCollectFuncDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {\n        var scopeChain = context.scopeChain;\n\n        // REVIEW: This will have to change when we move to \"export\"\n        if (context.scopeChain.moduleDecl) {\n            context.scopeChain.moduleDecl.recordNonInterface();\n        }\n\n        var funcDecl = <FuncDecl>ast;\n        var fgSym: TypeSymbol = null;\n        var nameText = funcDecl.getNameText();\n        var isExported = hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported);\n        var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);\n        var isPrivate = hasFlag(funcDecl.fncFlags, FncFlags.Private);\n        var isConstructor = funcDecl.isConstructMember() || funcDecl.isConstructor;\n        var containerSym:TypeSymbol = <TypeSymbol> (((funcDecl.isMethod() && isStatic) || funcDecl.isAccessor()) && context.scopeChain.classType ? context.scopeChain.classType.symbol : context.scopeChain.container);\n        var containerScope: SymbolScope = context.scopeChain.scope;\n        var isGlobal = containerSym == context.checker.gloMod;\n        var isOptional = funcDecl.name && hasFlag(funcDecl.name.flags, ASTFlags.OptionalName);\n        var go = false;\n        var foundSymbol = false; \n\n        // If this is a class constructor, the \"container\" is actually the class declaration\n        if (isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n            containerSym = <TypeSymbol>containerSym.container;\n            containerScope = scopeChain.previous.scope;\n        }\n\n        funcDecl.unitIndex = context.checker.locationInfo.unitIndex;\n        \n        // If the parent is the constructor, and this isn't an instance method, skip it.\n        // That way, we'll set the type during scope assignment, and can be sure that the\n        // function will be placed in the constructor-local scope\n        if (!funcDecl.isConstructor &&\n            containerSym &&\n            containerSym.declAST &&\n            containerSym.declAST.nodeType == NodeType.FuncDecl &&\n            (<FuncDecl>containerSym.declAST).isConstructor &&\n            !funcDecl.isMethod()) {\n            return go;\n        }        \n\n        // Interfaces and overloads\n        if (hasFlag(funcDecl.fncFlags, FncFlags.Signature)) {\n            var instType = context.scopeChain.thisType;                       \n\n            // If the function is static, search in the class type's\n            if (nameText && nameText != \"__missing\") {\n                if (isStatic) {\n                    fgSym = containerSym.type.members.allMembers.lookup(nameText);\n                }\n                else {\n                    // REVIEW: This logic should be symmetric with preCollectClassTypes\n                    fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, false);\n                    \n                    // If we could not find the function symbol in the value context, look\n                    // in the type context.\n                    // This would be the case, for example, if a class constructor override\n                    // were declared before a call override for a given class\n                    if (fgSym == null) {\n                        fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, true);\n                    }\n                }\n                \n                if (fgSym) {\n                    foundSymbol = true;\n                    \n                    // We'll combine ambient and non-ambient funcdecls during typecheck (for contextual typing).,\n                    // So, if they don't agree, don't use the symbol we've found                    \n                    if (!funcDecl.isSignature() && (hasFlag(funcDecl.fncFlags, FncFlags.Ambient) != hasFlag(fgSym.flags, SymbolFlags.Ambient))) {\n                       fgSym = null;\n                    }\n                }                \n            }\n            \n            // a function with this symbol has not yet been declared in this scope\n            // REVIEW: In the code below, we need to ensure that only function overloads are considered\n            //  (E.g., if a vardecl has the same id as a function or class, we may use the vardecl symbol\n            //  as the overload.)  Defensively, however, the vardecl won't have a type yet, so it should\n            //  suffice to just check for a null type when considering the overload symbol in\n            //  createFunctionSignature\n            if (fgSym == null) {\n                if (!(funcDecl.isSpecialFn())) {                    \n                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, null, !foundSymbol).declAST.type.symbol;\n                }\n                else {\n                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, containerSym, false).declAST.type.symbol;                                                                         \n                }\n                \n                // set the symbol's declAST, which will point back to the first declaration (symbol or otherwise)\n                // related to this symbol\n                if (fgSym.declAST == null || !funcDecl.isSpecialFn()) {\n                    fgSym.declAST = ast;\n                }\n            }\n            else { // there exists a symbol with this name\n                \n                if ((fgSym.kind() == SymbolKind.Type)) {\n\n                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, false).declAST.type.symbol;\n                }\n                else {\n                    context.checker.errorReporter.simpleError(funcDecl, \"Function or method '\" + funcDecl.name.actualText + \"' already declared as a property\");\n                }\n            }\n         \n            if (funcDecl.isSpecialFn() && !isStatic) {\n                funcDecl.type = instType ? instType : fgSym.type; \n            }\n            else {\n                funcDecl.type = fgSym.type;\n            }            \n        }\n        else {\n            // declarations\n            \n            if (nameText) {\n                if (isStatic) {\n                    fgSym = containerSym.type.members.allMembers.lookup(nameText);\n                }\n                else {\n                    // in the constructor case, we want to check the parent scope for overloads\n                    if (funcDecl.isConstructor && context.scopeChain.previous) {\n                        fgSym = <TypeSymbol>context.scopeChain.previous.scope.findLocal(nameText, false, false);\n                    }\n                    \n                    if (fgSym == null) {\n                        fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, false);\n                    }\n                }\n                if (fgSym) {\n                    foundSymbol = true;\n                    \n                    if (!isConstructor && fgSym.declAST.nodeType == NodeType.FuncDecl && !(<FuncDecl>fgSym.declAST).isAccessor() && !(<FuncDecl>fgSym.declAST).isSignature()) {\n                        fgSym = null;\n                        foundSymbol = false;\n                    }\n                }                \n            }\n\n            // REVIEW: Move this check into the typecheck phase?  It's only being run over properties...\n            if (fgSym &&\n                !fgSym.isAccessor() &&\n                fgSym.type &&\n                fgSym.type.construct &&\n                fgSym.type.construct.signatures != [] &&\n                (fgSym.type.construct.signatures[0].declAST == null ||\n                    !hasFlag(fgSym.type.construct.signatures[0].declAST.fncFlags, FncFlags.Ambient)) &&\n                !funcDecl.isConstructor) {\n                context.checker.errorReporter.simpleError(funcDecl, \"Functions may not have class overloads\");\n            }\n\n            if (fgSym && !(fgSym.kind() == SymbolKind.Type) && funcDecl.isMethod() && !funcDecl.isAccessor() && !funcDecl.isConstructor) {\n                context.checker.errorReporter.simpleError(funcDecl, \"Function or method '\" + funcDecl.name.actualText + \"' already declared as a property\");\n                fgSym.type = context.checker.anyType;\n            }\n            var sig = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, !foundSymbol);\n\n            // it's a getter or setter function                                   \n            if (((!fgSym || fgSym.declAST.nodeType != NodeType.FuncDecl) && funcDecl.isAccessor()) || (fgSym && fgSym.isAccessor())) {\n                funcDecl.accessorSymbol = context.checker.createAccessorSymbol(funcDecl, fgSym, containerSym.type, (funcDecl.isMethod() && isStatic), true, containerScope, containerSym);\n            }\n\n            funcDecl.type.symbol.declAST = ast;\n            if (funcDecl.isConstructor) { // REVIEW: Remove when classes completely replace oldclass\n                go = true;\n            };\n        }\n        if (isExported) {\n            if (funcDecl.type.call) {\n                funcDecl.type.symbol.flags |= SymbolFlags.Exported;\n            }\n            \n            // Accessors are set to 'exported' above\n            if (fgSym && !fgSym.isAccessor() && fgSym.kind() == SymbolKind.Type && fgSym.type.call) {\n                fgSym.flags |= SymbolFlags.Exported;\n            }\n        }\n        if (context.scopeChain.moduleDecl && !funcDecl.isSpecialFn()) {\n            funcDecl.type.symbol.flags |= SymbolFlags.ModuleMember;\n            funcDecl.type.symbol.declModule = context.scopeChain.moduleDecl;\n        }\n\n        if (fgSym && isOptional) {\n            fgSym.flags |= SymbolFlags.Optional;\n        }\n\n        return go;\n    }\n\n    export function preCollectTypes(ast: AST, parent: AST, walker: IAstWalker) {\n        var context: TypeCollectionContext = walker.state;\n        var go = false;\n        var scopeChain = context.scopeChain;\n\n        if (ast.nodeType == NodeType.Script) {\n            var script: Script = <Script>ast;\n            context.script = script;\n            go = true;\n        }\n        else if (ast.nodeType == NodeType.List) {\n            go = true;\n        }\n        else if (ast.nodeType == NodeType.ImportDeclaration) {\n            go = preCollectImportTypes(ast, parent, context);\n        }\n        else if (ast.nodeType == NodeType.With) {\n            go = false;\n        }\n        else if (ast.nodeType == NodeType.ModuleDeclaration) {\n            go = preCollectModuleTypes(ast, parent, context);\n        }\n        else if (ast.nodeType == NodeType.ClassDeclaration) {\n            go = preCollectClassTypes(ast, parent, context);\n        }\n        else if (ast.nodeType == NodeType.Block) {\n            go = true;\n        }\n        else if (ast.nodeType == NodeType.InterfaceDeclaration) {\n            go = preCollectInterfaceTypes(ast, parent, context);\n        }\n        // This will be a constructor arg because this pass only traverses\n        // constructor arg lists\n        else if (ast.nodeType == NodeType.ArgDecl) {\n            go = preCollectArgDeclTypes(ast, parent, context);\n        }\n        else if (ast.nodeType == NodeType.VarDecl) {\n            go = preCollectVarDeclTypes(ast, parent, context);\n        }\n        else if (ast.nodeType == NodeType.FuncDecl) {\n            go = preCollectFuncDeclTypes(ast, parent, context);\n        }\n        else {\n            if (ast.isStatementOrExpression() && context.scopeChain.moduleDecl) {\n                context.scopeChain.moduleDecl.recordNonInterface();\n            }\n        }\n        walker.options.goChildren = go;\n        return ast;\n    }\n\n    export function postCollectTypes(ast: AST, parent: AST, walker: IAstWalker) {\n        var context: TypeCollectionContext = walker.state;\n\n        if (ast.nodeType == NodeType.ModuleDeclaration) {\n            popTypeCollectionScope(context);\n        }\n        else if (ast.nodeType == NodeType.ClassDeclaration) {\n            popTypeCollectionScope(context);\n        }\n        else if (ast.nodeType == NodeType.InterfaceDeclaration) {\n            popTypeCollectionScope(context);\n        }\n        return ast;\n    }\n\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n    export class ScopeChain {\n        public thisType: Type;\n        public classType: Type;\n        public fnc: FuncDecl;\n        public moduleDecl: ModuleDeclaration;\n\n        constructor (public container: Symbol, public previous: ScopeChain,\n                     public scope: SymbolScope) { }\n    }\n\n    export class BBUseDefInfo {\n        public defsBySymbol = new bool[];\n        public gen: BitVector;\n        public kill: BitVector;\n        public top: BitVector;\n        // use lists by symbol \n        public useIndexBySymbol = new number[][];\n\n        constructor (public bb: BasicBlock) { }\n\n        public updateTop() {\n            var temp = new BitVector(this.top.bitCount);\n            for (var i = 0, succLen = this.bb.successors.length; i < succLen; i++) {\n                var succ = this.bb.successors[i];\n                if (succ.useDef) {\n                    temp.union(succ.useDef.top);\n                }\n            }\n            temp.difference(this.kill);\n            temp.union(this.gen);\n            var changed = temp.notEq(this.top);\n            this.top = temp;\n            return changed;\n        }\n\n\n        public initialize(useDefContext: UseDefContext) {\n            var defSym = (sym: Symbol, context: UseDefContext) => {\n                if (context.isLocalSym(sym)) {\n                    var index = context.getSymbolIndex(sym);\n                    // clear pending uses\n                    this.useIndexBySymbol[index] = new number[];\n                    this.defsBySymbol[index] = true;\n                }\n            }\n\n            var useSym = (sym: Symbol, context: UseDefContext, ast: AST) => {\n                if (context.isLocalSym(sym)) {\n                    var symIndex = context.getSymbolIndex(sym);\n                    if (this.useIndexBySymbol[symIndex] == undefined) {\n                        this.useIndexBySymbol[symIndex] = new number[];\n                    }\n                    var symUses = this.useIndexBySymbol[symIndex];\n                    var astIndex = context.getUseIndex(ast);\n                    context.addUse(symIndex, astIndex);\n                    symUses.push(astIndex);\n                }\n            }\n\n            function initUseDefPre(cur: AST, parent: AST, walker: IAstWalker) {\n                var context: UseDefContext = walker.state;\n                if (cur == null) {\n                    cur = null;\n                }\n                if (cur.nodeType == NodeType.VarDecl) {\n                    var varDecl = <BoundDecl>cur;\n                    if (varDecl.init || hasFlag(varDecl.varFlags, VarFlags.AutoInit)) {\n                        defSym(varDecl.sym, context);\n                    }\n                }\n                else if (cur.nodeType == NodeType.Name) {\n                    // use\n                    if (parent) {\n                        if (parent.nodeType == NodeType.Asg) {\n                            var asg = <BinaryExpression>parent;\n                            if (asg.operand1 == cur) {\n                                return cur;\n                            }\n                        }\n                        else if (parent.nodeType == NodeType.VarDecl) {\n                            var parentDecl = <BoundDecl>parent;\n                            if (parentDecl.id == cur) {\n                                return cur;\n                            }\n                        }\n                    }\n                    var id = <Identifier>cur;\n                    useSym(id.sym, context, cur);\n                }\n                else if ((cur.nodeType >= NodeType.Asg) && (cur.nodeType <= NodeType.LastAsg)) {\n                    // def\n                    var asg = <BinaryExpression>cur;\n                    if (asg.operand1 && (asg.operand1.nodeType == NodeType.Name)) {\n                        var id = <Identifier>asg.operand1;\n                        defSym(id.sym, context);\n                    }\n                }\n                else if (cur.nodeType == NodeType.FuncDecl) {\n                    walker.options.goChildren = false;\n                }\n\n                return cur;\n            }\n\n            var options = new AstWalkOptions();\n            // traverse ASTs in reverse order of execution (to match uses with preceding defs)\n            options.reverseSiblings = true;\n\n            getAstWalkerFactory().walk(this.bb.content, initUseDefPre, null, options, useDefContext);\n        }\n\n        public initializeGen(useDefContext: UseDefContext) {\n            var symbolLen = this.useIndexBySymbol.length;\n            var bitCount = useDefContext.uses.length;\n            this.gen = new BitVector(bitCount);\n            for (var s = 0; s < symbolLen; s++) {\n                var symUses = this.useIndexBySymbol[s];\n                if ((symUses != undefined) && (symUses.length > 0)) {\n                    for (var u = 0, uLen = symUses.length; u < uLen; u++) {\n                        this.gen.set(symUses[u], true);\n                    }\n                }\n            }\n            this.top = this.gen;\n        }\n\n        public initializeKill(useDefContext: UseDefContext) {\n            this.kill = new BitVector(this.gen.bitCount);\n            for (var s = 0, symbolLen = this.defsBySymbol.length; s < symbolLen; s++) {\n                if (this.defsBySymbol[s]) {\n                    var globalSymUses = useDefContext.useIndexBySymbol[s];\n                    if (globalSymUses) {\n                        for (var u = 0, useLen = globalSymUses.length; u < useLen; u++) {\n                            this.kill.set(globalSymUses[u], true);\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    export class UseDefContext {\n        // global use lists by symbol\n        public useIndexBySymbol = new number[][];\n        // global list of uses (flat)\n        public uses = new AST[];\n        public symbols = new VariableSymbol[];\n        public symbolMap = new StringHashTable();\n        public symbolCount = 0;\n        public func: Symbol;\n\n        constructor () {\n        }\n\n        public getSymbolIndex(sym: Symbol) {\n            var name = sym.name;\n            var index = <number>(this.symbolMap.lookup(name));\n            if (index == null) {\n                index = this.symbolCount++;\n                this.symbols[index] = <VariableSymbol>sym;\n                this.symbolMap.add(name, index);\n            }\n            return index;\n        }\n\n        public addUse(symIndex: number, astIndex: number) {\n            var useBySym = this.useIndexBySymbol[symIndex];\n            if (useBySym == undefined) {\n                useBySym = new number[];\n                this.useIndexBySymbol[symIndex] = useBySym;\n            }\n            useBySym[useBySym.length] = astIndex;\n        }\n\n        public getUseIndex(ast: AST) {\n            this.uses[this.uses.length] = ast;\n            return this.uses.length - 1;\n        }\n\n        public isLocalSym(sym: Symbol) { return (sym && (sym.container == this.func) && (sym.kind() == SymbolKind.Variable)); }\n\n        public killSymbol(sym: VariableSymbol, bbUses: BitVector) {\n            var index: number = this.symbolMap.lookup(sym.name);\n            var usesOfSym = this.useIndexBySymbol[index];\n            for (var k = 0, len = usesOfSym.length; k < len; k++) {\n                bbUses.set(usesOfSym[k], true);\n            }\n        }\n    }\n\n    export class BitVector {\n        static packBits = 30;\n        public firstBits = 0;\n        public restOfBits: number[] = null;\n\n        constructor (public bitCount: number) {\n            if (this.bitCount > BitVector.packBits) {\n                this.restOfBits = new number[];\n                var len = Math.floor(this.bitCount / BitVector.packBits);\n                for (var i = 0; i < len; i++) {\n                    this.restOfBits[i] = 0;\n                }\n            }\n        }\n\n        public set(bitIndex: number, value: bool) {\n            if (bitIndex < BitVector.packBits) {\n                if (value) {\n                    this.firstBits |= (1 << bitIndex);\n                }\n                else {\n                    this.firstBits &= (~(1 << bitIndex));\n                }\n            }\n            else {\n                var offset = Math.floor(bitIndex / BitVector.packBits) - 1;\n                var localIndex = bitIndex % BitVector.packBits;\n                if (value) {\n                    this.restOfBits[offset] |= (1 << localIndex);\n                }\n                else {\n                    this.restOfBits[offset] &= (~(1 << localIndex));\n                }\n            }\n        }\n\n        public map(fn: (index: number) =>any) {\n            var k: number;\n            for (k = 0; k < BitVector.packBits; k++) {\n                if (k == this.bitCount) {\n                    return;\n                }\n                if (((1 << k) & this.firstBits) != 0) {\n                    fn(k);\n                }\n            }\n            if (this.restOfBits) {\n                var len: number;\n                var cumu = BitVector.packBits;\n                for (k = 0, len = this.restOfBits.length; k < len; k++) {\n                    var myBits = this.restOfBits[k];\n                    for (var j = 0; j < BitVector.packBits; j++) {\n                        if (((1 << j) & myBits) != 0) {\n                            fn(cumu);\n                        }\n                        cumu++;\n                        if (cumu == this.bitCount) {\n                            return;\n                        }\n                    }\n                }\n            }\n        }\n\n        // assume conforming sizes\n        public union(b: BitVector) {\n            this.firstBits |= b.firstBits;\n            if (this.restOfBits) {\n                for (var k = 0, len = this.restOfBits.length; k < len; k++) {\n                    var myBits = this.restOfBits[k];\n                    var bBits = b.restOfBits[k];\n                    this.restOfBits[k] = myBits | bBits;\n                }\n            }\n        }\n\n        // assume conforming sizes\n        public intersection(b: BitVector) {\n            this.firstBits &= b.firstBits;\n            if (this.restOfBits) {\n                for (var k = 0, len = this.restOfBits.length; k < len; k++) {\n                    var myBits = this.restOfBits[k];\n                    var bBits = b.restOfBits[k];\n                    this.restOfBits[k] = myBits & bBits;\n                }\n            }\n        }\n\n        // assume conforming sizes\n        public notEq(b: BitVector) {\n            if (this.firstBits != b.firstBits) {\n                return true;\n            }\n            if (this.restOfBits) {\n                for (var k = 0, len = this.restOfBits.length; k < len; k++) {\n                    var myBits = this.restOfBits[k];\n                    var bBits = b.restOfBits[k];\n                    if (myBits != bBits) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n\n        public difference(b: BitVector) {\n            var oldFirstBits = this.firstBits;\n            this.firstBits &= (~b.firstBits);\n            if (this.restOfBits) {\n                for (var k = 0, len = this.restOfBits.length; k < len; k++) {\n                    var myBits = this.restOfBits[k];\n                    var bBits = b.restOfBits[k];\n                    this.restOfBits[k] &= (~bBits);\n                }\n            }\n        }\n    }\n\n    export class BasicBlock {\n        // blocks that branch to the block after this one\n        public predecessors = new BasicBlock[];\n        public index = -1;\n        public markValue = 0;\n        public marked(markBase: number) { return this.markValue > markBase; }\n        public mark() {\n            this.markValue++;\n        }\n        public successors = new BasicBlock[];\n        public useDef: BBUseDefInfo = null;\n        public content = new ASTList();\n        public addSuccessor(successor: BasicBlock): void {\n            this.successors[this.successors.length] = successor;\n            successor.predecessors[successor.predecessors.length] = this;\n        }\n    }\n\n    export interface ITargetInfo {\n        stmt: AST;\n        continueBB: BasicBlock;\n        breakBB: BasicBlock;\n    }\n\n    export class ControlFlowContext {\n        public entry = null;\n        // first unreachable ast for each unreachable code segment\n        public unreachable: AST[] = null;\n        public noContinuation = false;\n        // statements enclosing the current statement\n        public statementStack = new ITargetInfo[];\n        public currentSwitch = new BasicBlock[];\n        public walker: IAstWalker;\n\n        constructor (public current: BasicBlock,\n                     public exit: BasicBlock) {\n            this.entry = this.current;\n        }\n\n        public walk(ast: AST, parent: AST) {\n            return this.walker.walk(ast, parent);\n        }\n\n        public pushSwitch(bb: BasicBlock) {\n            this.currentSwitch.push(bb);\n        }\n\n        public popSwitch() {\n            return this.currentSwitch.pop();\n        }\n\n        public reportUnreachable(er: ErrorReporter) {\n            if (this.unreachable && (this.unreachable.length > 0)) {\n                var len = this.unreachable.length;\n                for (var i = 0; i < len; i++) {\n                    var unreachableAST = this.unreachable[i];\n                    if (unreachableAST.nodeType != NodeType.EndCode) {\n                        er.simpleError(unreachableAST, \"unreachable code\");\n                    }\n                }\n            }\n        }\n\n        private printAST(ast: AST, outfile: ITextWriter) {\n            var printContext = new PrintContext(outfile, null);\n\n            printContext.increaseIndent();\n            //ast.walk(prePrintAST, postPrintAST, null, printContext);\n            getAstWalkerFactory().walk(ast, prePrintAST, postPrintAST, null, printContext);\n\n            printContext.decreaseIndent();\n        }\n\n        private printBlockContent(bb: BasicBlock, outfile: ITextWriter) {\n            var content = bb.content;\n            for (var i = 0, len = content.members.length; i < len; i++) {\n                var ast = content.members[i];\n                this.printAST(ast, outfile);\n            }\n        }\n\n        public markBase = 0;\n\n        public bfs(nodeFunc: (bb: BasicBlock) =>void , edgeFunc: (node1: BasicBlock, node2: BasicBlock) =>void ,\n            preEdges: () =>void , postEdges: () =>void ) {\n            var markValue = this.markBase++;\n            var q = new BasicBlock[];\n            q[q.length] = this.entry;\n\n            while (q.length > 0) {\n                var bb = q.pop();\n                if (!(bb.marked(markValue))) {\n                    bb.mark();\n                    if (nodeFunc) {\n                        nodeFunc(bb);\n                    }\n                    var succLen = bb.successors.length;\n                    if (succLen > 0) {\n                        if (preEdges) {\n                            preEdges();\n                        }\n                        for (var j = succLen - 1; j >= 0; j--) {\n                            var successor = bb.successors[j];\n                            if (!(successor.marked(this.markBase))) {\n                                if (edgeFunc) {\n                                    edgeFunc(bb, successor);\n                                }\n                                q[q.length] = successor;\n                            }\n                        }\n                        if (postEdges) {\n                            postEdges();\n                        }\n                    }\n                }\n            }\n        }\n\n        public linearBBs = new BasicBlock[];\n\n        public useDef(er: ErrorReporter, funcSym: Symbol) {\n            var useDefContext = new UseDefContext();\n            useDefContext.func = funcSym;\n            var useDefInit = (bb: BasicBlock) => {\n                bb.useDef = new BBUseDefInfo(bb);\n                bb.useDef.initialize(useDefContext);\n                this.linearBBs[this.linearBBs.length] = bb;\n            }\n            this.bfs(useDefInit, null, null, null);\n            var i: number, bbLen: number;\n            for (i = 0, bbLen = this.linearBBs.length; i < bbLen; i++) {\n                this.linearBBs[i].useDef.initializeGen(useDefContext);\n                this.linearBBs[i].useDef.initializeKill(useDefContext);\n            }\n            var changed = true;\n\n            while (changed) {\n                changed = false;\n                for (i = 0; i < bbLen; i++) {\n                    changed = this.linearBBs[i].useDef.updateTop() || changed;\n                }\n            }\n\n            var top = this.entry.useDef.top;\n            top.map((index) => {\n                var ast = <Identifier>useDefContext.uses[<number>index];\n                er.simpleError(ast, \"use of variable '\" + ast.actualText + \"' that is not definitely assigned\");\n            });\n        }\n\n        public print(outfile: ITextWriter) {\n            var index = 0;\n            var node = (bb: BasicBlock) => {\n                if (bb.index < 0) {\n                    bb.index = index++;\n                }\n                if (bb == this.exit) {\n                    outfile.WriteLine(\"Exit block with index \" + bb.index);\n                }\n                else {\n                    outfile.WriteLine(\"Basic block with index \" + bb.index);\n                    this.printBlockContent(bb, outfile);\n                }\n            }\n\n            function preEdges() {\n                outfile.Write(\"  Branches to \");\n            }\n\n            function postEdges() {\n                outfile.WriteLine(\"\");\n            }\n\n            function edge(node1: BasicBlock, node2: BasicBlock) {\n                if (node2.index < 0) {\n                    node2.index = index++;\n                }\n                outfile.Write(node2.index + \" \");\n            }\n\n            this.bfs(node, edge, preEdges, postEdges);\n            if (this.unreachable != null) {\n                for (var i = 0, len = this.unreachable.length; i < len; i++) {\n                    outfile.WriteLine(\"Unreachable basic block ...\");\n                    this.printAST(this.unreachable[i], outfile);\n                }\n            }\n        }\n\n        public pushStatement(stmt: Statement, continueBB: BasicBlock, breakBB: BasicBlock) {\n            this.statementStack.push({ stmt: stmt, continueBB: continueBB, breakBB: breakBB });\n        }\n\n        public popStatement() { return this.statementStack.pop(); }\n\n        public returnStmt() {\n            // TODO: make successor finally block if return stmt inside of try/finally \n            this.current.addSuccessor(this.exit);\n            this.setUnreachable();\n        }\n\n        public setUnreachable() {\n            this.current = null;\n            this.noContinuation = true;\n        }\n\n        public addUnreachable(ast: AST) {\n            if (this.unreachable === null) {\n                this.unreachable = new AST[];\n            }\n            this.unreachable[this.unreachable.length] = ast;\n        }\n\n        public unconditionalBranch(target: AST, isContinue: bool) {\n            var targetBB = null;\n            for (var i = 0, len = this.statementStack.length; i < len; i++) {\n                var targetInfo = this.statementStack[i];\n                if (targetInfo.stmt == target) {\n                    if (isContinue) {\n                        targetBB = targetInfo.continueBB;\n                    }\n                    else {\n                        targetBB = targetInfo.breakBB;\n                    }\n                    break;\n                }\n            }\n            if (targetBB) {\n                this.current.addSuccessor(targetBB);\n            }\n            this.setUnreachable();\n        }\n\n        public addContent(ast: AST): void {\n            if (this.current) {\n                this.current.content.append(ast);\n            }\n        }\n    }\n\n    export interface IResolutionData {\n        actuals: Type[];\n        exactCandidates: Signature[];\n        conversionCandidates: Signature[];\n        id: number;\n    }\n\n    export class ResolutionDataCache {\n        public cacheSize = 16;\n        public rdCache: IResolutionData[] = [];\n        public nextUp: number = 0;\n\n        constructor () {\n            for (var i = 0; i < this.cacheSize; i++) {\n                this.rdCache[i] = {\n                    actuals: new Type[],\n                    exactCandidates: new Signature[],\n                    conversionCandidates: new Signature[],\n                    id: i\n                };\n            }\n        }\n\n        public getResolutionData(): IResolutionData {\n            var rd: IResolutionData = null;\n\n            if (this.nextUp < this.cacheSize) {\n                rd = this.rdCache[this.nextUp];\n            }\n\n            if (rd == null) {\n                this.cacheSize++;\n                rd = {\n                    actuals: new Type[],\n                    exactCandidates: new Signature[],\n                    conversionCandidates: new Signature[],\n                    id: this.cacheSize\n                };\n                this.rdCache[this.cacheSize] = rd;\n            }\n\n            // cache operates as a stack - RD is always served up in-order\n            this.nextUp++;\n\n            return rd;\n        }\n\n        public returnResolutionData(rd: IResolutionData) {\n            // Pop to save on array allocations, which are a bottleneck\n            // REVIEW: On some VMs, Array.pop doesn't always pop the last value in the array\n            rd.actuals.length = 0;\n            rd.exactCandidates.length = 0;\n            rd.conversionCandidates.length = 0;\n\n            this.nextUp = rd.id;\n        }\n    }\n\n    export class TypeFlow {\n        public scope: SymbolScope;\n        public globalScope: SymbolScope;\n\n        public thisType: Type;\n        public thisFnc: FuncDecl = null;\n        public thisClassNode: TypeDeclaration = null;\n        public enclosingFncIsMethod = false;\n\n        // REVIEW: Prune in favor of typechecker fields\n        public doubleType: Type;\n        public booleanType: Type;\n        public stringType: Type;\n        public anyType: Type;\n        public regexType: Type;\n        public nullType: Type;\n        public voidType: Type;\n        public arrayAnyType: Type;\n\n        public arrayInterfaceType: Type = null;\n        public stringInterfaceType: Type = null;\n        public objectInterfaceType: Type = null;\n        public functionInterfaceType: Type = null;\n        public numberInterfaceType: Type = null;\n        public booleanInterfaceType: Type = null;\n        public iargumentsInterfaceType: Type = null;\n\n        public currentScript: Script = null;\n\n        public inImportTypeCheck = false;\n        public inTypeRefTypeCheck = false;\n        public inArrayElementTypeCheck = false;\n        public resolutionDataCache = new ResolutionDataCache();\n        public nestingLevel = 0;\n        public inSuperCall = false;\n\n        constructor (public logger: ILogger, public initScope: SymbolScope, public parser: Parser,\n                   public checker: TypeChecker) {\n            this.checker.typeFlow = this;\n            this.scope = this.initScope;\n            this.globalScope = this.initScope;\n            this.doubleType = this.checker.numberType;\n            this.booleanType = this.checker.booleanType;\n            this.stringType = this.checker.stringType;\n            this.anyType = this.checker.anyType;\n            this.regexType = this.anyType;\n            this.nullType = this.checker.nullType;\n            this.voidType = this.checker.voidType;\n            this.arrayAnyType = this.checker.makeArrayType(this.anyType);\n        }\n\n        public initLibs() {\n            var arraySym = this.globalScope.find(\"Array\", false, true);\n            if (arraySym && (arraySym.kind() == SymbolKind.Type)) {\n                this.arrayInterfaceType = (<TypeSymbol>arraySym).type;\n            }\n            var stringSym = this.globalScope.find(\"String\", false, true);\n            if (stringSym && (stringSym.kind() == SymbolKind.Type)) {\n                this.stringInterfaceType = (<TypeSymbol>stringSym).type;\n            }\n            var objectSym = this.globalScope.find(\"Object\", false, true);\n            if (objectSym && (objectSym.kind() == SymbolKind.Type)) {\n                this.objectInterfaceType = (<TypeSymbol>objectSym).type;\n            }\n            var fnSym = this.globalScope.find(\"Function\", false, true);\n            if (fnSym && (fnSym.kind() == SymbolKind.Type)) {\n                this.functionInterfaceType = (<TypeSymbol>fnSym).type;\n            }\n            var numberSym = this.globalScope.find(\"Number\", false, true);\n            if (numberSym && (numberSym.kind() == SymbolKind.Type)) {\n                this.numberInterfaceType = (<TypeSymbol>numberSym).type;\n            }\n            var booleanSym = this.globalScope.find(\"Boolean\", false, true);\n            if (booleanSym && (booleanSym.kind() == SymbolKind.Type)) {\n                this.booleanInterfaceType = (<TypeSymbol>booleanSym).type;\n            }\n            var regexSym = this.globalScope.find(\"RegExp\", false, true);\n            if (regexSym && (regexSym.kind() == SymbolKind.Type)) {\n                this.regexType = (<TypeSymbol>regexSym).type;\n            }\n        }\n\n        public cast(ast: AST, type: Type): AST {\n            return this.castWithCoercion(ast, type, true, false);\n        }\n\n        public castWithCoercion(ast: AST, type: Type, applyCoercion: bool, typeAssertion: bool): AST {\n            var comparisonInfo = new TypeComparisonInfo();\n            if (this.checker.sourceIsAssignableToTarget(ast.type, type, comparisonInfo) || (typeAssertion && this.checker.sourceIsAssignableToTarget(type, ast.type, comparisonInfo))) {\n                if (applyCoercion) {\n                    if (type == null) {\n                        ast.type = this.anyType;\n                    }\n                    else if (type.isClass()) {\n                        ast.type = type.instanceType;\n                    }\n                    else {\n                        ast.type = type;\n                    }\n                }\n                return ast;\n            }\n            else {\n                this.checker.errorReporter.incompatibleTypes(ast, ast.type, type, null, this.scope, comparisonInfo);\n                return ast;\n            }\n        }\n\n        public inScopeTypeCheck(ast: AST, enclosingScope: SymbolScope): AST {\n            var prevScope = this.scope;\n            this.scope = enclosingScope;\n            var svThisFnc = this.thisFnc;\n            var svThisType = this.thisType;\n            var svThisClassNode = this.thisClassNode;\n            var svCurrentModDecl = this.checker.currentModDecl;\n            var prevMethodStatus = this.enclosingFncIsMethod;\n            var container = this.scope.container;\n            var fnc: FuncDecl = null;\n            while (container) {\n                if (container.kind() == SymbolKind.Type) {\n                    var typeSym = <TypeSymbol>container;\n                    var type = typeSym.type;\n                    if (type.call) {\n                        if (fnc == null) {\n                            // use innermost function\n                            this.enclosingFncIsMethod = typeSym.isMethod;\n                            fnc = <FuncDecl>container.declAST;\n                        }\n                    }\n                    if (type.isClass()) {\n                        this.thisType = type.instanceType;\n                        if (typeSym.declAST &&\n                            (typeSym.declAST.nodeType == NodeType.ClassDeclaration)) {\n                            this.thisClassNode = <TypeDeclaration>typeSym.declAST;\n                        }\n                        // use innermost class\n                        break;\n                    }\n                    if (type.isModuleType()) {\n                        this.checker.currentModDecl = <ModuleDeclaration>typeSym.declAST;\n                        // use innermost module\n                        break;\n                    }\n                }\n                container = container.container;\n            }\n            this.thisFnc = fnc;\n\n            var updated = this.typeCheck(ast);\n\n            this.thisFnc = svThisFnc;\n            this.thisType = svThisType;\n            this.thisClassNode = svThisClassNode;\n            this.checker.currentModDecl = svCurrentModDecl;\n            this.enclosingFncIsMethod = prevMethodStatus;\n            this.scope = prevScope;\n            return updated;\n        }\n\n        public typeCheck(ast: AST): AST {\n            if (ast) {\n                return ast.typeCheck(this);\n            }\n            else {\n                return null;\n            }\n        }\n\n        public inScopeTypeCheckDecl(ast: AST) {\n            if (ast.nodeType == NodeType.VarDecl || ast.nodeType == NodeType.ArgDecl) {\n                this.inScopeTypeCheckBoundDecl(<BoundDecl>ast);\n            }\n            else if (ast.nodeType == NodeType.FuncDecl) {\n\n                var funcDecl = <FuncDecl>ast;\n\n                if (funcDecl.isAccessor()) {\n                    this.typeCheckFunction(funcDecl);\n                }\n            }\n        }\n\n        public inScopeTypeCheckBoundDecl(varDecl: BoundDecl) {\n            var sym = varDecl.sym;\n            var svThisFnc = this.thisFnc;\n            var svThisType = this.thisType;\n            var prevMethodStatus = this.enclosingFncIsMethod;\n            var prevLocationInfo = this.checker.locationInfo;\n            if (sym && sym.container) {\n                var instanceScope = hasFlag(varDecl.varFlags, VarFlags.ClassConstructorProperty) ? sym.container.getType().constructorScope : sym.container.instanceScope();\n                if (hasFlag(varDecl.varFlags, VarFlags.Property) && sym.container.declAST.nodeType == NodeType.FuncDecl) {\n                    this.thisFnc = <FuncDecl>sym.container.declAST;\n                }\n                if (instanceScope) {\n                    var prevScope = this.scope;\n                    this.scope = instanceScope;\n                    var container = sym.container;\n                    var svCurrentModDecl = this.checker.currentModDecl;\n                    if (this.checker.units &&\n                        (sym.unitIndex >= 0) &&\n                        (sym.unitIndex < this.checker.units.length)) {\n                        this.checker.locationInfo = this.checker.units[sym.unitIndex];\n                    }\n                    else {\n                        this.checker.locationInfo = unknownLocationInfo;\n                    }\n                    // REVIEW: container linkage for function expressions\n                    while (container) {\n                        if (container.kind() == SymbolKind.Type) {\n                            var typeSym = <TypeSymbol>container;\n                            var type = typeSym.type;\n                            if (type.call) {\n                                this.enclosingFncIsMethod = typeSym.isMethod;\n                            }\n                            if (type.isClass()) {\n                                this.thisType = type.instanceType;\n                            }\n                            if (type.isModuleType()) {\n                                this.checker.currentModDecl = <ModuleDeclaration>container.declAST;\n                                break;\n                            }\n                        }\n                        container = container.container;\n                    }\n\n                    this.typeCheckBoundDecl(varDecl);\n                    this.checker.currentModDecl = svCurrentModDecl;\n                    this.scope = prevScope;\n                }\n            }\n            this.thisFnc = svThisFnc;\n            this.thisType = svThisType;\n            this.checker.locationInfo = prevLocationInfo;\n            this.enclosingFncIsMethod = prevMethodStatus;\n        }\n\n        public resolveBoundDecl(varDecl: BoundDecl) {\n            if (varDecl.typeExpr) {\n                if (varDecl.typeExpr.type == null ||\n                    (varDecl.typeExpr.type && varDecl.typeExpr.type == this.anyType && this.scope) ||\n                    varDecl.typeExpr.type.symbol == null ||\n                    !this.checker.typeStatusIsFinished(varDecl.typeExpr.type.symbol.typeCheckStatus)) {\n                    this.typeCheck(varDecl.typeExpr);\n                }\n                varDecl.type = varDecl.typeExpr.type;\n                if (varDecl.sym) {\n                    varDecl.sym.setType(varDecl.type);\n                }\n            }\n            else if (varDecl.init == null) {\n                if (this.checker.styleSettings.implicitAny) {\n                    this.checker.errorReporter.styleError(varDecl, \"type implicitly set to 'any'\");\n                }\n                varDecl.type = this.anyType;\n                if (varDecl.sym) {\n                    if (varDecl.sym.isType()) {\n                        var tsym = <TypeSymbol>varDecl.sym;\n                        if (tsym.isMethod) {\n                            this.checker.errorReporter.simpleError(varDecl, \"Cannot bind method group to variable.  (Did you mean to use 'declare function' instead of 'declare var'?)\");\n                            return;\n                        }\n                        else {\n                            this.checker.errorReporter.simpleError(varDecl, \"Cannot bind type to variable\");\n                            return;\n                        }\n                    }\n                    varDecl.sym.setType(varDecl.type);\n                }\n            }\n        }\n\n        public typeCheckBoundDecl(varDecl: BoundDecl): VarDecl {\n            // symbol has already been added to the scope\n            var infSym = <InferenceSymbol>varDecl.sym;\n            if (infSym == null) {\n                if (varDecl.init) {\n                    varDecl.init = this.typeCheck(varDecl.init);\n                    varDecl.type = this.checker.widenType(varDecl.init.type);\n                }\n                else {\n                    if (this.checker.styleSettings.implicitAny) {\n                        this.checker.errorReporter.styleError(varDecl, \"type implicitly set to 'any'\");\n                    }\n                    varDecl.type = this.anyType;\n                }\n            }\n            else {\n                if (infSym.typeCheckStatus == TypeCheckStatus.Started) {\n                    if (this.checker.styleSettings.implicitAny) {\n                        this.checker.errorReporter.styleError(varDecl, \"type implicitly set to 'any'\");\n                    }\n                    varDecl.type = this.anyType;\n                    infSym.setType(this.anyType);\n                }\n                else if (infSym.typeCheckStatus == TypeCheckStatus.NotStarted) {\n                    infSym.typeCheckStatus = TypeCheckStatus.Started;\n                    this.checker.addStartedPTO(infSym);\n                    var resolved = false;\n                    if (varDecl.type == null) {\n                        // propagate declared type\n                        if (varDecl.typeExpr) {\n                            this.resolveBoundDecl(varDecl);\n                            resolved = true;\n                            varDecl.type = varDecl.typeExpr.type;\n                            infSym.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n                        }\n                    }\n\n                    if (varDecl.init) {\n                        // if the bound decl is a function-local static, we need to set the\n                        // encapsulating scope to the function's member scope\n                        var isLocalStatic = hasFlag(varDecl.varFlags, VarFlags.LocalStatic);\n                        var prevScope = this.scope;\n                        var applyTargetType = !varDecl.init.isParenthesized;\n                        if (isLocalStatic) {\n                            this.scope = varDecl.sym.container.getType().memberScope;\n                        }\n\n                        // Mark Lambda expressions with IsPropertyBound flag\n                        if (hasFlag(varDecl.varFlags, VarFlags.Property) && this.thisClassNode) {\n                            getAstWalkerFactory().walk(varDecl.init, (ast: AST, parent: AST, walker: IAstWalker) => {\n                                if (ast && ast.nodeType == NodeType.FuncDecl) {\n                                    if (hasFlag((<FuncDecl>ast).fncFlags, FncFlags.IsFatArrowFunction)) {\n                                        // Found a Lambda, mark it\n                                        (<FuncDecl>ast).fncFlags |= FncFlags.IsPropertyBound;\n                                    }\n                                    // Only mark the top level functions\n                                    walker.options.goChildren = false;\n                                }\n                                return ast;\n                            });\n                        }\n\n                        this.checker.typeCheckWithContextualType(varDecl.type, this.checker.inProvisionalTypecheckMode(), applyTargetType, varDecl.init);\n\n                        this.scope = prevScope;\n                        if (varDecl.type) {\n                            // If the cast is to a target type, in the case of a funcdecl,\n                            // we may overwrite the init's type with one generated from a signature.\n                            // In that case, we need to preserve the contained scope of the actual decl\n                            var preserveScope = false;\n                            var preservedContainedScope = null;\n\n                            if (varDecl.init.type) {\n                                preservedContainedScope = varDecl.init.type.containedScope;\n                                preserveScope = true;\n                                if (varDecl.init.type == this.voidType) {\n                                    this.checker.errorReporter.simpleError(varDecl, \"Cannot assign type 'void' to variable '\" + varDecl.id.actualText + \"'\");\n                                }\n                            }\n\n                            varDecl.init = this.castWithCoercion(varDecl.init, varDecl.type, applyTargetType && !this.checker.inProvisionalTypecheckMode(), false);\n\n                            if (preserveScope && varDecl.init.type.containedScope == null) {\n                                varDecl.init.type.containedScope = preservedContainedScope;\n                            }\n                        }\n                        else {\n                            varDecl.type = this.checker.widenType(varDecl.init.type);\n                            if (varDecl.type == this.voidType) {\n                                this.checker.errorReporter.simpleError(varDecl, \"Cannot assign type 'void' to variable '\" + varDecl.id.actualText + \"'\");\n                                varDecl.type = this.anyType;\n                            }\n                        }\n                        infSym.setType(varDecl.type);\n                    }\n                    else {\n                        if (!resolved) {\n                            this.resolveBoundDecl(varDecl);\n                        }\n                    }\n                    infSym.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n                }\n                else if (this.checker.typeStatusIsFinished(infSym.typeCheckStatus) &&\n                         (infSym.declAST != varDecl)) {\n                    if (varDecl.init) {\n                        varDecl.init = this.typeCheck(varDecl.init);\n                        varDecl.type = infSym.getType();\n                        varDecl.init = this.cast(varDecl.init, varDecl.type);\n                    }\n                }\n            }\n            if (varDecl.id && varDecl.sym) {\n                varDecl.id.sym = varDecl.sym;\n            }\n\n            // Check if variable satisfies type privacy\n            if (varDecl.sym && varDecl.sym.container) {\n                this.checkTypePrivacy(varDecl.sym.getType(), varDecl.sym, (typeName: string, isModuleName: bool) => this.varPrivacyErrorReporter(varDecl, typeName, isModuleName));\n            }\n            return <VarDecl>varDecl;\n        }\n\n        private varPrivacyErrorReporter(varDecl: BoundDecl, typeName: string, isModuleName: bool) {\n            var typestring = \"\";\n            if (isModuleName) {\n                var quotestring = \"\";\n                if (!isQuoted(typeName)) {\n                    quotestring = \"'\";\n                }\n                typestring = \" is using inaccessible module \" + quotestring + typeName + quotestring;\n            } else {\n                typestring = \" has or is using private type '\" + typeName + \"'\";\n            }\n\n            if (hasFlag(varDecl.varFlags, VarFlags.Public)) {\n                if (varDecl.sym.container.declAST.nodeType == NodeType.InterfaceDeclaration) {\n                    this.checker.errorReporter.simpleError(varDecl, \"property '\" + varDecl.sym.name + \"' of exported interface\" + typestring);\n                } else {\n                    this.checker.errorReporter.simpleError(varDecl, \"public member '\" + varDecl.sym.name + \"' of exported class\" + typestring);\n                }\n            } else {\n                this.checker.errorReporter.simpleError(varDecl, \"exported variable '\" + varDecl.sym.name + \"'\" + typestring);\n            }\n        }\n\n        public typeCheckSuper(ast: AST): AST {\n            if (this.thisType && (this.enclosingFncIsMethod && !this.thisFnc.isStatic()) && this.thisType.baseClass()) {\n                ast.type = this.thisType.baseClass();\n            }\n            else {\n                // redirect 'super' used within lambdas\n                if (!this.enclosingFncIsMethod &&\n                    this.thisType && this.thisType.baseClass() &&\n                    this.thisFnc && hasFlag(this.thisFnc.fncFlags, FncFlags.IsFatArrowFunction)) {\n                    // Find the closest non lambda function\n                    var enclosingFnc = this.thisFnc.enclosingFnc;\n                    while (hasFlag(enclosingFnc.fncFlags, FncFlags.IsFatArrowFunction)) {\n                        enclosingFnc = enclosingFnc.enclosingFnc;\n                    }\n\n                    // If the lambda is enclosed is a valid member, use the base type\n                    if (enclosingFnc && (enclosingFnc.isMethod() || enclosingFnc.isConstructor) && !enclosingFnc.isStatic()) {\n                        ast.type = this.thisType.baseClass();\n                        enclosingFnc.setHasSuperReferenceInFatArrowFunction();\n                        return ast;\n                    }\n                }\n\n                ast.type = this.anyType;\n                this.checker.errorReporter.invalidSuperReference(ast);\n            }\n            return ast;\n        }\n\n        public typeCheckThis(ast: AST): AST {\n           ast.type = this.anyType;\n            var illegalThisRef = false;\n            if (this.thisFnc == null) {\n                // 'this' in class bodies should bind to 'any'\n                if (this.thisType) {\n                    if (this.thisClassNode && this.thisClassNode.nodeType == NodeType.ClassDeclaration) {\n                        illegalThisRef = true;\n                    }\n                    else {\n                        ast.type = this.thisType;\n                    }\n                }\n                else if (this.checker.currentModDecl) {\n                    this.checker.errorReporter.simpleError(ast, \"'this' may not be referenced within module bodies\");\n                }\n            }\n            else {\n                if (this.thisClassNode && (hasFlag(this.thisFnc.fncFlags, FncFlags.IsPropertyBound) || (this.inSuperCall && hasFlag((<ClassDeclaration>this.thisClassNode).varFlags, VarFlags.ClassSuperMustBeFirstCallInConstructor)))) {\n                    illegalThisRef = true;\n                }\n                if (this.thisFnc.isMethod() || this.thisFnc.isConstructor || this.thisFnc.isTargetTypedAsMethod) {\n                    if (this.thisType && !(this.thisFnc.fncFlags & FncFlags.Static)) {\n                        ast.type = this.thisType;\n                    }\n                }\n            }\n\n            // redirect 'this' used within lambdas\n            if (!this.enclosingFncIsMethod &&\n                this.thisFnc &&\n                hasFlag(this.thisFnc.fncFlags, FncFlags.IsFatArrowFunction)) {\n\n                    // if the enclosing function was bound to a property,\n                    // checkInitSelf would not have been able to mark the \n                    // function for a self init\n                if (this.thisFnc.boundToProperty) {\n                    var container = this.thisFnc.boundToProperty.sym.container;\n                    if (container.declAST.nodeType == NodeType.FuncDecl) {\n                        (<FuncDecl>container.declAST).setHasSelfReference();\n                    }\n                }\n                else {\n                    var encFnc = this.thisFnc.enclosingFnc;\n                    var firstEncFnc = encFnc;\n\n                    while (encFnc) {\n                        if (this.thisClassNode && hasFlag(encFnc.fncFlags, FncFlags.IsPropertyBound)) {\n                            illegalThisRef = true;\n                        }\n\n                        if (!hasFlag(encFnc.fncFlags, FncFlags.IsFatArrowFunction) || encFnc.hasSelfReference()) {\n                            encFnc.setHasSelfReference();\n                            break;\n                        }\n\n                        encFnc = encFnc.enclosingFnc;\n                    }\n\n                    if (!encFnc && firstEncFnc) {\n                        encFnc = firstEncFnc;\n                        encFnc.setHasSelfReference();\n                    }\n                    else if (!encFnc) { // the lambda is bound at the top-level...\n                        if (this.thisClassNode) {\n                            (<ClassDeclaration>this.thisClassNode).varFlags |= VarFlags.MustCaptureThis;\n                        }\n                        else if (this.checker.currentModDecl) {\n                            this.checker.currentModDecl.modFlags |= ModuleFlags.MustCaptureThis;\n                        }\n                        else {\n                            this.checker.mustCaptureGlobalThis = true;\n                        }\n                    }\n\n                    if (encFnc && (encFnc.isMethod() || encFnc.isConstructor) && this.thisType && !hasFlag(encFnc.fncFlags, FncFlags.Static)) {\n                        ast.type = this.thisType;\n                    }\n                }\n            }\n\n            if (illegalThisRef) {\n                this.checker.errorReporter.simpleError(ast, \"Keyword 'this' cannot be referenced in initializers in a class body, or in super constructor calls\");\n            }\n            return ast;\n        }\n\n        public setTypeFromSymbol(ast: AST, symbol: Symbol): void {\n            if (symbol.isVariable()) {\n                if (symbol.isInferenceSymbol()) {\n                    var infSym = <InferenceSymbol>symbol;\n                    if (infSym.declAST &&\n                        !this.checker.typeStatusIsFinished(infSym.typeCheckStatus)) {\n                        this.inScopeTypeCheckDecl(infSym.declAST);\n                    }\n                    if (!this.checker.styleSettings.innerScopeDeclEscape) {\n                        if (infSym.declAST && (infSym.declAST.nodeType == NodeType.VarDecl)) {\n                            if (this.nestingLevel < (<VarDecl>infSym.declAST).nestingLevel) {\n                                this.checker.errorReporter.styleError(ast, \"Illegal reference to a variable defined in more nested scope\");\n                            }\n                        }\n                    }\n                }\n                ast.type = symbol.getType();\n                if (!symbol.writeable()) {\n                    ast.flags = ast.flags & (~(ASTFlags.Writeable));\n                }\n            }\n            else if (symbol.isType()) {\n                ast.type = symbol.getType();\n                ast.flags = ast.flags & (~(ASTFlags.Writeable));\n            }\n            else {\n                ast.type = this.anyType;\n                this.checker.errorReporter.symbolDoesNotReferToAValue(ast, symbol.name);\n            }\n        }\n\n        public typeCheckName(ast: AST): AST {\n            var identifier = <Identifier>ast;\n\n            if (this.checker.inWith) {\n                identifier.type = this.anyType;\n            }\n            else {\n                var typespace = this.inTypeRefTypeCheck;\n                var idText = identifier.text;\n                var originalIdText = idText;\n                var isDynamicModuleName = isQuoted(identifier.text);\n\n                var symbol = this.scope.find(idText, false, typespace);\n\n                if (symbol == null && isDynamicModuleName) {\n                    symbol = this.checker.findSymbolForDynamicModule(idText, this.currentScript.locationInfo.filename, (id) => this.scope.find(id, false, typespace));\n                }\n\n                if (!symbol) {\n                    if (!identifier.isMissing()) {\n                        this.checker.errorReporter.unresolvedSymbol(identifier, identifier.text);\n                    }\n                    identifier.type = this.anyType;\n                }\n                else {\n                    if (optimizeModuleCodeGen && symbol && symbol.isType()) {\n                        var symType = symbol.getType();\n                        // Once the type has been referenced outside of a type ref position, there's\n                        // no going back                        \n                        if (symType && (<TypeSymbol>symbol).aliasLink && (<TypeSymbol>symbol).onlyReferencedAsTypeRef) {\n\n                            var modDecl = <ModuleDeclaration>symType.symbol.declAST;\n                            if (modDecl && hasFlag(modDecl.modFlags, ModuleFlags.IsDynamic)) {\n                                (<TypeSymbol>symbol).onlyReferencedAsTypeRef = this.inTypeRefTypeCheck;\n                            }\n                        }\n                    }\n\n                    if (symbol.declAST &&\n                        symbol.declAST.nodeType == NodeType.FuncDecl &&\n                        !(<FuncDecl>symbol.declAST).returnTypeAnnotation &&\n                        (<FuncDecl>symbol.declAST).signature.typeCheckStatus == TypeCheckStatus.Started) {\n                        (<FuncDecl>symbol.declAST).type.symbol.flags |= SymbolFlags.RecursivelyReferenced;\n                        (<FuncDecl>symbol.declAST).signature.returnType.type = this.anyType;\n                    }\n\n                    this.setTypeFromSymbol(ast, symbol);\n                    identifier.sym = symbol;\n                    if (this.thisFnc) {\n                        if (this.thisFnc.type && symbol.container != this.thisFnc.type.symbol) {\n                            this.thisFnc.freeVariables[this.thisFnc.freeVariables.length] = symbol;\n                        }\n                    }\n                }\n            }\n            return ast;\n        }\n\n        public typeCheckScript(script: Script): Script {\n            this.checker.locationInfo = script.locationInfo;\n            this.scope = this.checker.globalScope;\n\n            // if it's a top-level module, the globals have already been added to the implicit\n            // module decl\n            if (!script.topLevelMod) {\n                this.addLocalsFromScope(this.scope, this.checker.gloMod,\n                                   script.vars, this.checker.globals, true);\n            }\n\n            this.currentScript = script;\n            script.bod = <ASTList>this.typeCheck(script.bod);\n            this.currentScript = null;\n            return script;\n        }\n\n        public typeCheckBitNot(ast: AST): AST {\n            var unex = <UnaryExpression>ast;\n            unex.operand = this.typeCheck(unex.operand);\n            unex.type = this.doubleType;\n            return unex;\n        }\n\n        public typeCheckUnaryNumberOperator(ast: AST): AST {\n            var unex = <UnaryExpression>ast;\n            unex.operand = this.typeCheck(unex.operand);\n            unex.type = this.doubleType;\n            return ast;\n        }\n\n        public typeCheckLogNot(ast: AST): AST {\n            var unex = <UnaryExpression>ast;\n            unex.operand = this.typeCheck(unex.operand);\n            unex.type = this.booleanType;\n            return unex;\n        }\n\n        public astIsWriteable(ast: AST): bool {\n            return hasFlag(ast.flags, ASTFlags.Writeable);\n        }\n\n        public typeCheckIncOrDec(ast: AST): AST {\n            var unex = <UnaryExpression>ast;\n            var lval = unex.operand;\n            if (!this.astIsWriteable(unex)) {\n                this.checker.errorReporter.valueCannotBeModified(unex);\n                unex.type = this.doubleType;\n            }\n            else {\n                unex = <UnaryExpression> this.typeCheckUnaryNumberOperator(ast);\n                if (unex.operand.type != this.checker.numberType && unex.operand.type != this.checker.anyType && !(unex.operand.type.typeFlags & TypeFlags.IsEnum)) {\n                    this.checker.errorReporter.simpleError(ast, \"'++' and '--' may only be applied to operands of type 'number' or 'any'\");\n                }\n            }\n            return unex;\n        }\n\n        public typeCheckBitwiseOperator(ast: AST, assignment: bool): AST {\n            var binex = <BinaryExpression>ast;\n            var resultType: Type = null;\n            binex.operand1 = this.typeCheck(binex.operand1);\n            binex.operand2 = this.typeCheck(binex.operand2);\n            var leftType = binex.operand1.type;\n            var rightType = binex.operand2.type;\n\n            if (assignment && (!this.astIsWriteable(binex))) {\n                this.checker.errorReporter.valueCannotBeModified(binex);\n            }\n\n            if (this.checker.styleSettings.bitwise) {\n                this.checker.errorReporter.styleError(ast, \"use of \" + nodeTypeTable[binex.nodeType]);\n            }\n\n            if (this.checker.sourceIsSubtypeOfTarget(leftType, this.doubleType) && (this.checker.sourceIsSubtypeOfTarget(rightType, this.doubleType))) {\n                resultType = this.doubleType;\n            }\n            else if ((leftType == this.booleanType) &&\n                     (rightType == this.booleanType)) {\n                resultType = this.booleanType;\n            }\n            else if (leftType == this.anyType) {\n                if ((rightType == this.anyType) ||\n                    (rightType == this.doubleType) ||\n                    (rightType == this.booleanType)) {\n                    resultType = this.anyType;\n                }\n            }\n            else if (rightType == this.anyType) {\n                if ((leftType == this.anyType) ||\n                    (leftType == this.doubleType) ||\n                    (leftType == this.booleanType)) {\n                    resultType = this.anyType;\n                }\n            }\n            if (resultType == null) {\n                resultType = this.anyType;\n                this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType,\n                                                        binex.printLabel(), this.scope);\n            }\n            binex.type = resultType;\n            return binex;\n        }\n\n        public typeCheckArithmeticOperator(ast: AST, assignment: bool): AST {\n            var binex = <BinaryExpression>ast;\n            binex.operand1 = this.typeCheck(binex.operand1);\n            binex.operand2 = this.typeCheck(binex.operand2);\n            var leftType = binex.operand1.type;\n            var rightType = binex.operand2.type;\n\n            if (assignment && (!this.astIsWriteable(binex.operand1))) {\n                this.checker.errorReporter.valueCannotBeModified(binex);\n            }\n\n            if (this.checker.styleSettings.bitwise &&\n                ((binex.nodeType == NodeType.And) ||\n                (binex.nodeType == NodeType.Or) ||\n                (binex.nodeType == NodeType.AsgAnd) ||\n                (binex.nodeType == NodeType.AsgOr))) {\n                this.checker.errorReporter.styleError(ast, \"use of \" + nodeTypeTable[binex.nodeType]);\n            }\n\n            if (leftType == null || rightType == null) {\n                this.checker.errorReporter.simpleError(binex, \"Could not typecheck arithmetic operation.  Possible recursive typecheck error?\");\n                binex.type = this.anyType;\n                return binex;\n            }\n            var nodeType = binex.nodeType;\n\n            if (this.checker.isNullOrUndefinedType(leftType)) {\n                leftType = rightType;\n            }\n            if (this.checker.isNullOrUndefinedType(rightType)) {\n                rightType = leftType;\n            }\n            leftType = this.checker.widenType(leftType);\n            rightType = this.checker.widenType(rightType);\n\n            if (nodeType == NodeType.Add || nodeType == NodeType.AsgAdd) {\n\n                if (leftType == this.checker.stringType || rightType == this.checker.stringType) {\n                    binex.type = this.checker.stringType;\n                }\n                else if (leftType == this.checker.numberType && rightType == this.checker.numberType) {\n                    binex.type = this.checker.numberType;\n                }\n                else if (this.checker.sourceIsSubtypeOfTarget(leftType, this.checker.numberType) && this.checker.sourceIsSubtypeOfTarget(rightType, this.checker.numberType)) {\n                    binex.type = this.checker.numberType;\n                }\n                else if (leftType == this.checker.anyType || rightType == this.checker.anyType) {\n                    binex.type = this.checker.anyType;\n                }\n                else {\n                    binex.type = this.anyType;\n                    this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType,\n                                                            binex.printLabel(), this.scope);\n                }\n            }\n            else {\n                if (leftType == this.checker.numberType && rightType == this.checker.numberType) {\n                    binex.type = this.checker.numberType;\n                }\n                else if (this.checker.sourceIsSubtypeOfTarget(leftType, this.checker.numberType) && this.checker.sourceIsSubtypeOfTarget(rightType, this.checker.numberType)) {\n                    binex.type = this.checker.numberType;\n                }\n                else if (leftType == this.checker.anyType || rightType == this.checker.anyType) {\n                    binex.type = this.checker.numberType;\n                }\n                else {\n                    binex.type = this.anyType;\n                    this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType,\n                                                            binex.printLabel(), this.scope);\n                }\n            }\n\n            return binex;\n        }\n\n        public typeCheckDotOperator(ast: AST): AST {\n            var binex = <BinaryExpression>ast;\n            var leftIsFnc = false;\n            binex.operand1 = this.typeCheck(binex.operand1);\n            var leftType = binex.operand1.type;\n            var leftScope: SymbolScope = null;\n            // REVIEW: replace with get member scope\n            if (leftType) {\n                if (leftType == this.anyType) {\n                    binex.type = this.anyType;\n                    return binex;\n                }\n                else if (leftType == this.stringType) {\n                    if (this.stringInterfaceType) {\n                        leftScope = this.stringInterfaceType.memberScope;\n                    }\n                    else {\n                        binex.type = this.anyType;\n                        return binex;\n                    }\n                }\n                else if (leftType == this.doubleType) {\n                    if (this.numberInterfaceType) {\n                        leftScope = this.numberInterfaceType.memberScope;\n                    }\n                    else {\n                        binex.type = this.anyType;\n                        return binex;\n                    }\n                }\n                else if (leftType == this.booleanType) {\n                    if (this.booleanInterfaceType) {\n                        leftScope = this.booleanInterfaceType.memberScope;\n                    }\n                    else {\n                        binex.type = this.anyType;\n                        return binex;\n                    }\n                }\n                else if ((leftType.call || leftType.construct) && leftType.members == null) {\n                    if (this.functionInterfaceType) {\n                        leftScope = this.functionInterfaceType.memberScope;\n                    }\n                    else {\n                        binex.type = this.anyType;\n                        return binex;\n                    }\n                }\n                else if (leftType.elementType) {\n                    if (this.arrayInterfaceType) {\n                        var arrInstType = leftType.elementType.getArrayBase(this.arrayInterfaceType, this.checker);\n                        leftScope = arrInstType.memberScope;\n                    }\n                    else {\n                        binex.type = this.anyType;\n                        return binex;\n                    }\n                }\n                else {\n                    leftScope = leftType.memberScope;\n                }\n            }\n            if (leftScope == null) {\n                this.checker.errorReporter.expectedClassOrInterface(binex);\n                binex.type = this.anyType;\n            }\n            else {\n                var propertyName = <Identifier>binex.operand2;\n                var lhsIsEnclosingType = (this.thisClassNode && binex.operand1.type == this.thisClassNode.type.instanceType) || this.inTypeRefTypeCheck;\n                var symbol = leftScope.find(propertyName.text, !lhsIsEnclosingType, this.inTypeRefTypeCheck); // only search the public members, unless the rhs is a 'this' pointer\n\n                // If the symbol wasn't found, delegate to the appropriate 'virtual' parent type\n                if (!symbol) {\n                    if (this.objectInterfaceType && leftType) {\n                        // check 'Object' for the symbol\n                        if (leftType.isReferenceType()) {\n                            symbol = this.objectInterfaceType.memberScope.find(propertyName.text, false, this.inTypeRefTypeCheck);\n                        }\n                        if (!symbol) {\n                            // check 'Function', if appropriate\n                            if (this.functionInterfaceType && (leftType.call || leftType.construct)) {\n                                symbol = this.functionInterfaceType.memberScope.find(propertyName.text, false, this.inTypeRefTypeCheck);\n                            }\n                        }\n                    }\n                }\n\n                if (!symbol || (!symbol.visible(leftScope, this.checker))) {\n                    binex.type = this.anyType;\n\n                    if (symbol == null) {\n                        this.checker.errorReporter.simpleError(propertyName, \"The property '\" + propertyName.actualText + \"' does not exist on value of type '\" + leftType.getScopedTypeName(this.scope) + \"'\");\n                    }\n                    else if (!this.inTypeRefTypeCheck) {  // if it's a dotted type reference, we'll catch the visibility error during binding\n                        this.checker.errorReporter.simpleError(binex, \"The property '\" + propertyName.actualText + \" on type '\" + leftType.getScopedTypeName(this.scope) + \"' is not visible\");\n                    }\n                }\n                else {\n                    if (symbol.isVariable()) {\n                        if (symbol.isInferenceSymbol()) {\n                            var infSym = <InferenceSymbol>symbol;\n                            if (infSym.declAST && !this.checker.typeStatusIsFinished(infSym.typeCheckStatus)) {\n                                this.inScopeTypeCheckDecl(infSym.declAST);\n                            }\n                        }\n                    }\n                    propertyName.sym = symbol;\n                    binex.type = symbol.getType();\n                }\n            }\n            if (binex.type == null) {\n                binex.type = this.anyType;\n            }\n\n            return binex;\n        }\n\n        public typeCheckBooleanOperator(ast: AST): AST {\n            var binex = <BinaryExpression>ast;\n            binex.operand1 = this.typeCheck(binex.operand1);\n            binex.operand2 = this.typeCheck(binex.operand2);\n            var leftType = binex.operand1.type;\n            var rightType = binex.operand2.type;\n            if ((!(this.checker.sourceIsAssignableToTarget(leftType, rightType))) &&\n                (!(this.checker.sourceIsAssignableToTarget(rightType, leftType)))) {\n                this.checker.errorReporter.incompatibleTypes(binex, leftType, rightType, binex.printLabel(), this.scope);\n            }\n            binex.type = this.booleanType;\n            return binex;\n        }\n\n        public typeCheckAsgOperator(ast: AST): AST {\n            var binex = <BinaryExpression>ast;\n            var applyTargetType = !binex.operand2.isParenthesized;\n            binex.operand1 = this.typeCheck(binex.operand1);\n\n            this.checker.typeCheckWithContextualType(binex.operand1.type, this.checker.inProvisionalTypecheckMode(), applyTargetType, binex.operand2);\n\n            var leftType = binex.operand1.type;\n            var rightType = binex.operand2.type;\n\n            if (!(this.astIsWriteable(binex.operand1))) {\n                this.checker.errorReporter.valueCannotBeModified(binex);\n            }\n            if (binex.operand1.nodeType == NodeType.Call) {\n                var callEx = <CallExpression>binex.operand1;\n            }\n            var preserveScope = false;\n            var preservedContainedScope = null;\n            if (binex.operand2.type) {\n                preservedContainedScope = binex.operand2.type.containedScope;\n                preserveScope = true;\n            }\n            // Do not re-write the AST in provisional typecheck mode\n            binex.operand2 = this.castWithCoercion(binex.operand2, leftType, applyTargetType && !this.checker.inProvisionalTypecheckMode(), false);\n            if (preserveScope && binex.operand2.type.containedScope == null) {\n                binex.operand2.type.containedScope = preservedContainedScope;\n            }\n            binex.type = rightType;\n            return binex;\n        }\n\n        public typeCheckIndex(ast: AST): AST {\n            var binex = <BinaryExpression>ast;\n            binex.operand1 = this.typeCheck(binex.operand1); // ObjExpr\n            binex.operand2 = this.typeCheck(binex.operand2); // IndexExpr\n\n            if (!this.checker.styleSettings.literalSubscript) {\n                if (binex.operand2.nodeType == NodeType.QString) {\n                    this.checker.errorReporter.styleError(ast, \"use literal subscript ('.') notation instead)\");\n                }\n            }\n\n            var objExprType = binex.operand1.type;\n            var indexExprType = binex.operand2.type;\n\n            if (objExprType.elementType) { // arrays\n                if (indexExprType == this.checker.anyType || indexExprType == this.checker.numberType || hasFlag(indexExprType.typeFlags, TypeFlags.IsEnum)) {\n                    binex.type = objExprType.elementType;\n                }\n                else if (indexExprType == this.checker.stringType) {\n                    binex.type = this.checker.anyType;\n                }\n                else {\n                    this.checker.errorReporter.simpleError(binex, \"Illegal property access\");\n                    binex.type = this.checker.anyType;\n                }\n            }\n            else if (objExprType.index) { // types with index sigs\n\n                if (indexExprType == this.checker.anyType ||\n                    !((objExprType.index.flags & SignatureFlags.IsStringIndexer) || (objExprType.index.flags & SignatureFlags.IsNumberIndexer)) || // REVIEW: unvalidated type expression\n                    ((objExprType.index.flags & SignatureFlags.IsStringIndexer) && indexExprType == this.checker.stringType) ||\n                    ((objExprType.index.flags & SignatureFlags.IsNumberIndexer) && (indexExprType == this.checker.numberType || hasFlag(indexExprType.typeFlags, TypeFlags.IsEnum)))) {\n                    var sig = this.resolveOverload(ast, objExprType.index);\n                    if (sig) {\n                        binex.type = sig.returnType.type;//objExprType.index.signatures[0].returnType.type;\n                    }\n                    else {\n                        binex.type = this.checker.anyType;\n                    }\n                }\n                else if (indexExprType == this.checker.stringType) {\n                    binex.type = this.checker.anyType;\n                }\n                else {\n                    this.checker.errorReporter.simpleError(binex, \"Illegal property access\");\n                    binex.type = this.checker.anyType;\n                }\n            }\n            else if ((objExprType == this.checker.anyType ||\n                     objExprType == this.checker.stringType ||\n                     objExprType == this.checker.numberType ||\n                     objExprType == this.checker.booleanType ||\n                     objExprType.isReferenceType()) &&\n                     (indexExprType == this.checker.anyType ||\n                      indexExprType == this.checker.stringType ||\n                      (indexExprType == this.checker.numberType || hasFlag(indexExprType.typeFlags, TypeFlags.IsEnum)))) { // REVIEW: Do we want to allow indexes of type 'number'?\n                binex.type = this.checker.anyType;\n            }\n            else {\n                this.checker.errorReporter.simpleError(binex, \"Illegal property access\");\n                binex.type = this.checker.anyType;\n            }\n\n            return binex;\n        }\n\n        public typeCheckInOperator(binex: BinaryExpression): BinaryExpression {\n            binex.operand1 = this.cast(this.typeCheck(binex.operand1), this.stringType);\n            binex.operand2 = this.typeCheck(binex.operand2);\n\n            if (!((binex.operand1.type == this.checker.anyType || binex.operand1.type == this.checker.stringType) &&\n                    (binex.operand2.type == this.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand2.type, this.objectInterfaceType)))) {\n                this.checker.errorReporter.simpleError(binex, \"The in operator requires the left operand to be of type Any or the String primitive type, and the right operand to be of type Any or an object type\");\n            }\n\n            binex.type = this.booleanType;\n            return binex;\n        }\n\n        public typeCheckShift(binex: BinaryExpression, assignment: bool): BinaryExpression {\n            binex.operand1 = this.cast(this.typeCheck(binex.operand1), this.doubleType);\n            binex.operand2 = this.cast(this.typeCheck(binex.operand2), this.doubleType);\n            if (assignment && (!(this.astIsWriteable(binex.operand1)))) {\n                this.checker.errorReporter.valueCannotBeModified(binex);\n            }\n            binex.type = this.doubleType;\n            return binex;\n        }\n\n        public typeCheckQMark(trinex: ConditionalExpression): ConditionalExpression {\n            trinex.operand1 = this.typeCheck(trinex.operand1);\n            trinex.operand2 = this.typeCheck(trinex.operand2);\n            trinex.operand3 = this.typeCheck(trinex.operand3);\n            var leftType = trinex.operand2.type;\n            var rightType = trinex.operand3.type;\n\n            if (leftType == rightType) {\n                trinex.type = leftType;\n            }\n            else {\n                if (this.checker.sourceIsSubtypeOfTarget(leftType, rightType)) {\n                    trinex.type = rightType;\n                }\n                else if (this.checker.sourceIsSubtypeOfTarget(rightType, leftType)) {\n                    trinex.type = leftType;\n                }\n                else {\n                    trinex.type = this.anyType;\n                    this.checker.errorReporter.incompatibleTypes(trinex, leftType, rightType, trinex.printLabel(), this.scope);\n                }\n            }\n\n            return trinex;\n        }\n\n        public addFormals(container: Symbol, signature: Signature,\n            table: IHashTable) {\n            var len = signature.parameters.length;\n            for (var i = 0; i < len; i++) {\n                var symbol = <ParameterSymbol>signature.parameters[i];\n                symbol.container = container;\n                table.add(symbol.name, symbol);\n            }\n        }\n\n        // REVIEW: We use isModContainer instead of container.getType().isModuleType because container.type may be null at this\n        // juncture\n        public addLocalsFromScope(scope: SymbolScope, container: Symbol, vars: ASTList, table: IHashTable, isModContainer: bool) {\n            var len = vars.members.length;\n            var hasArgsDef = false;\n            for (var i = 0; i < len; i++) {\n                var local = <VarDecl>vars.members[i];\n                if (((local.sym == null) || (local.sym.kind() != SymbolKind.Field))) {\n                    var result: Symbol = null;\n                    if ((result = table.lookup(local.id.text)) == null) {\n                        var localVar: ValueLocation = new ValueLocation();\n                        localVar.typeLink = new TypeLink();\n                        var varSym = null;\n\n                        if (hasFlag(local.varFlags, VarFlags.Static)) {\n                            local.varFlags |= VarFlags.LocalStatic;\n                            varSym = new FieldSymbol(local.id.text, local.minChar,\n                                                      this.checker.locationInfo.unitIndex,\n                                                      true, localVar);\n                        }\n                        else {\n                            varSym = new VariableSymbol(local.id.text, local.minChar,\n                                                      this.checker.locationInfo.unitIndex,\n                                                      localVar);\n                        }\n                        varSym.transferVarFlags(local.varFlags);\n                        localVar.symbol = varSym;\n                        varSym.declAST = local;\n                        localVar.typeLink.ast = local.typeExpr;\n                        this.checker.resolveTypeLink(scope, localVar.typeLink, false);\n                        if ((local.type == null) && (local.init == null)) {\n                            local.type = this.anyType;\n                        }\n                        localVar.typeLink.type = local.type;\n                        localVar.symbol.container = container;\n                        local.sym = localVar.symbol;\n                        table.add(local.id.text, varSym);\n                        if (local.id.text == \"arguments\") {\n                            hasArgsDef = true;\n                        }\n                    }\n                    else {\n                        local.type = result.getType();\n                        local.sym = result;\n                    }\n                }\n            }\n            if (!isModContainer) {\n                if (!hasArgsDef) {\n                    var argLoc = new ValueLocation();\n                    argLoc.typeLink = new TypeLink();\n                    var theArgSym = new VariableSymbol(\"arguments\", vars.minChar,\n                                                     this.checker.locationInfo.unitIndex,\n                                                     argLoc);\n\n                    // if the user is using a custom lib.d.ts where IArguments has not been defined\n                    // (or they're compiling with the --nolib option), use 'any' as the argument type\n                    if (!this.iargumentsInterfaceType) {\n                        var argumentsSym = scope.find(\"IArguments\", false, true);\n\n                        if (argumentsSym) {\n                            argumentsSym.flags |= SymbolFlags.CompilerGenerated;\n                            this.iargumentsInterfaceType = argumentsSym.getType();\n                        }\n                        else {\n                            this.iargumentsInterfaceType = this.anyType;\n                        }\n                    }\n                    argLoc.typeLink.type = this.iargumentsInterfaceType;\n                    table.add(\"arguments\", theArgSym);\n                }\n            }\n        }\n\n        // REVIEW: isClass param may now be redundant\n        public addConstructorLocalArgs(container: Symbol, args: ASTList, table: IHashTable, isClass: bool): void {\n            if (args) {\n                var len = args.members.length;\n                for (var i = 0; i < len; i++) {\n                    var local = <ArgDecl>args.members[i];\n                    if ((local.sym == null) ||\n                        (isClass || (local.sym.kind() != SymbolKind.Field))) {\n                        var result: Symbol = null;\n                        if ((result = table.lookup(local.id.text)) == null) {\n                            this.resolveBoundDecl(local);\n                            var localVar: ValueLocation = new ValueLocation();\n                            localVar.typeLink = new TypeLink();\n                            var varSym = new ParameterSymbol(local.id.text, local.minChar,\n                                                                   this.checker.locationInfo.unitIndex,\n                                                                   localVar);\n                            varSym.declAST = local;\n                            localVar.symbol = varSym;\n                            localVar.typeLink.type = local.type;\n                            localVar.symbol.container = container;\n                            local.sym = localVar.symbol;\n                            table.add(local.id.text, varSym);\n                        }\n                        else {\n                            local.type = result.getType();\n                            local.sym = result;\n                        }\n                    }\n                }\n            }\n        }\n\n        public checkInitSelf(funcDecl: FuncDecl): bool {\n            if (!funcDecl.isMethod()) {\n                var freeVars = funcDecl.freeVariables;\n                for (var k = 0, len = freeVars.length; k < len; k++) {\n                    var sym = freeVars[k];\n                    if (sym.isInstanceProperty()) {\n                        return true;\n                    }\n                }\n            }\n            var fns = funcDecl.scopes;\n            var fnsLen = fns.members.length;\n\n            for (var j = 0; j < fnsLen; j++) {\n                var fn = <FuncDecl>fns.members[j];\n                if (this.checkInitSelf(fn)) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        public checkPromoteFreeVars(funcDecl: FuncDecl, constructorSym: Symbol): void {\n            var freeVars = funcDecl.freeVariables;\n            for (var k = 0, len = freeVars.length; k < len; k++) {\n                var sym = freeVars[k];\n                if ((!sym.isInstanceProperty()) && (sym.container == constructorSym)) {\n                    instanceFilter.reset();\n                    if (this.scope.search(instanceFilter, sym.name, false, false)) {\n                        this.checker.errorReporter.simpleError(funcDecl, \"Constructor-local variable shadows class property '\" + sym.name + \"'. To access the class property, use 'self.\" + sym.name + \"'\");\n                    }\n\n                    this.checker.errorReporter.simpleError(funcDecl, \"Constructor-local variables may not be accessed from instance method bodies. Consider changing local variable '\" + sym.name + \"' to a class property\")\n                }\n            }\n        }\n\n        public allReturnsAreVoid(funcDecl: FuncDecl) {\n            // in the case of a function or method with no declared return type, walk the body to \n            // pre-emptively determine if the function has a return type of void\n            //\n            // REVIEW: Eventually, we'll want to perform exit graph analysis to determine\n            // if the function ever \"escapes\" without a return expression\n            // This would require moving some of this logic into the function's typecheck-proper,\n            // which would slow things down a fair bit, but would open up more analysis opportunities\n            var allReturnsAreVoid = true;\n\n            if (funcDecl.signature.returnType.type == null) {\n                var preFindReturnExpressionTypes = function (ast: AST, parent: AST, walker: IAstWalker) {\n                    var go = true;\n                    switch (ast.nodeType) {\n                        case NodeType.FuncDecl:\n                            // don't recurse into a function decl - we don't want to confuse a nested\n                            // return type with the top-level function's return type\n                            go = false;\n                            break;\n                        case NodeType.Return:\n                            var returnStmt: ReturnStatement = <ReturnStatement>ast;\n\n                            if (returnStmt.returnExpression) {\n                                allReturnsAreVoid = false;\n                                go = false;\n                            }\n\n                        default:\n                            break;\n                    }\n                    walker.options.goChildren = go;\n                    walker.options.goNextSibling = go;\n                    return ast;\n                }\n\n                getAstWalkerFactory().walk(funcDecl.bod, preFindReturnExpressionTypes);\n            }\n\n            return allReturnsAreVoid;\n        }\n\n        public classConstructorHasSuperCall(funcDecl: FuncDecl) {\n            var foundSuper = false;\n\n            var preFindSuperCall = function (ast: AST, parent: AST, walker: IAstWalker) {\n\n                var go = true;\n\n                switch (ast.nodeType) {\n                    case NodeType.FuncDecl:\n                        go = false;\n                        break;\n                    case NodeType.Call:\n                        var call = <CallExpression>ast;\n\n                        if (call.target.nodeType == NodeType.Super) {\n                            go = false;\n                            foundSuper = true;\n                            break;\n                        }\n                        break;\n                    default:\n                        break;\n                }\n                walker.options.goChildren = go;\n                return ast;\n            }\n\n            getAstWalkerFactory().walk(funcDecl.bod, preFindSuperCall);\n\n            return foundSuper;\n        }\n\n        private baseListPrivacyErrorReporter(bases: ASTList, i: number, declSymbol: Symbol, extendsList: bool, typeName: string, isModuleName: bool) {\n            var baseSymbol = bases.members[i].type.symbol;\n            var declTypeString = (declSymbol.declAST.nodeType == NodeType.InterfaceDeclaration) ? \"interface\" : \"class\";\n            var baseListTypeString = extendsList ? \"extends\" : \"implements\";\n            var baseTypeString = (baseSymbol.declAST.nodeType == NodeType.InterfaceDeclaration) ? \"interface\" : \"class\";\n            var typestring = \"\";\n            if (isModuleName) {\n                var quotestring = \"\";\n                if (!isQuoted(typeName)) {\n                    quotestring = \"'\";\n                }\n                typestring = \" is using inaccessible module \";\n                baseTypeString = \" \" + baseTypeString + \" from private module \" + quotestring + typeName + quotestring;\n            } else {\n                baseTypeString = \" private \" + baseTypeString + \" '\" + typeName + \"'\";\n            }\n            this.checker.errorReporter.simpleError(bases.members[i], \"exported \" + declTypeString + \" '\" + declSymbol.name + \"' \" + baseListTypeString + baseTypeString);\n        }\n\n        // Check if declSymbol can satisfy baselist privacy\n        private typeCheckBaseListPrivacy(bases: ASTList, declSymbol: Symbol, extendsList: bool) {\n            if (bases) {\n                var basesLen = bases.members.length;\n                for (var i = 0; i < basesLen; i++) {\n                    if (!bases.members[i].type || bases.members[i].type == this.checker.anyType) {\n                        // This type is coming from external module so it has to be exported, or we're recovering from an\n                        // error condition\n                        continue;\n                    }\n\n                    this.checkSymbolPrivacy(bases.members[i].type.symbol, declSymbol, (typeName: string, isModuleName: bool) => this.baseListPrivacyErrorReporter(bases, i, declSymbol, extendsList, typeName, isModuleName));\n                }\n            }\n        }\n\n        // Checks if the privacy is satisfied by typeSymbol that is used in the declaration inside container\n        private checkSymbolPrivacy(typeSymbol: TypeSymbol, declSymbol: Symbol, errorCallback: (typeName: string, isModuleName: bool) => void ) {\n            var externalModuleSymbol: TypeSymbol = null;\n            var declSymbolPath: Symbol[] = null;\n\n            // Type is visible type, so this can be used by anyone.\n            if (typeSymbol.isExternallyVisible(this.checker)) {\n                // Symbol could be from external module, go ahead and find the external module\n                var typeSymbolPath = typeSymbol.pathToRoot();\n                declSymbolPath = declSymbol.pathToRoot();\n                var typeSymbolLength = typeSymbolPath.length;\n                var declSymbolPathLength = declSymbolPath.length;\n\n                if (typeSymbolLength > 0) {\n                    if (typeSymbolPath[typeSymbolLength - 1].getType().isModuleType() &&\n                        (<TypeSymbol>typeSymbolPath[typeSymbolLength - 1]).isDynamic &&\n                        typeSymbolPath[typeSymbolLength - 1] != declSymbolPath[declSymbolPathLength - 1]) {\n                        // Symbol from external module that was imported using one of the import statement\n                        externalModuleSymbol = <TypeSymbol>typeSymbolPath[typeSymbolLength - 1];\n                    } else if (typeSymbolLength > 1) {\n                        // Is symbol from declared quoted module\n                        if (typeSymbolPath[typeSymbolLength - 2].getType().isModuleType() &&\n                            (<TypeSymbol>typeSymbolPath[typeSymbolLength - 2]).isDynamic &&\n                            (declSymbolPathLength == 1 || typeSymbolPath[typeSymbolLength - 2] != declSymbolPath[declSymbolPathLength - 2])) {\n                            // From quoted module name\n                            externalModuleSymbol = <TypeSymbol>typeSymbolPath[typeSymbolLength - 2];\n                        }\n                    }\n                }\n\n                if (externalModuleSymbol == null) {\n                    return;\n                }\n            }\n\n            // Interface symbol doesn't reflect correct Exported state so use AST instead\n            var interfaceDecl: InterfaceDeclaration = declSymbol.getInterfaceDeclFromSymbol(this.checker);\n            if (interfaceDecl && !hasFlag(interfaceDecl.varFlags, VarFlags.Exported)) {\n                return;\n            }\n\n            var checkVisibilitySymbol = declSymbol;\n            // Var decl symbol doesnt reflect correct exported state so use AST instead\n            var varDecl = declSymbol.getVarDeclFromSymbol();\n            if (varDecl) {\n                if (hasFlag(varDecl.varFlags, VarFlags.Private)) {\n                    return;\n                } else if (hasFlag(varDecl.varFlags, VarFlags.Public)) {\n                    // Its a member from class so check visibility of its container\n                    checkVisibilitySymbol = declSymbol.container;\n                }\n            }\n\n            // If the container is visible from global scrope it is error\n            if (checkVisibilitySymbol.isExternallyVisible(this.checker)) {\n                var privateSymbolName = typeSymbol.name;\n\n                // If imported typeSymbol mark it as visible externally and verify that the symbol it imports is visible externally\n                if (externalModuleSymbol != null) {\n                    var prettyName = externalModuleSymbol.getPrettyNameOfDynamicModule(declSymbolPath);\n                    if (prettyName != null) {\n                        this.currentScript.AddExternallyVisibleImportedSymbol(prettyName.symbol, this.checker);\n                        return;\n                    } else {\n                        privateSymbolName = externalModuleSymbol.prettyName;\n                    }\n                }\n\n                // Visible declaration using non visible type.\n                errorCallback(privateSymbolName, typeSymbol.name != privateSymbolName);\n            }\n        }\n\n        // Checks if the privacy is satisfied by type that is used in the declaration inside container\n        private checkTypePrivacy(type: Type, declSymbol: Symbol, errorCallback: (typeName: string, isModuleName : bool) =>void ) {\n            // Primitive types\n            if (!(type && type.primitiveTypeClass == Primitive.None)) {\n                return;\n            }\n\n\n            // If type is array, check element type\n            if (type.isArray()) {\n                return this.checkTypePrivacy(type.elementType, declSymbol, errorCallback);\n            }\n\n            // Going to be printing symbol name, verify if symbol can be emitted\n            if (type.symbol && type.symbol.name && type.symbol.name != \"_anonymous\" &&\n                        (((type.call == null) && (type.construct == null) && (type.index == null)) ||\n                        (type.members && (!type.isClass())))) {\n                return this.checkSymbolPrivacy(<TypeSymbol>type.symbol, declSymbol, errorCallback);\n            }\n\n            if (type.members) {\n                // Verify symbols for members\n                type.members.allMembers.map((key, s, unused) => {\n                    var sym = <Symbol>s;\n                    if (!hasFlag(sym.flags, SymbolFlags.BuiltIn)) {\n                        this.checkTypePrivacy(sym.getType(), declSymbol, errorCallback);\n                    }\n                }, null);\n            }\n\n            this.checkSignatureGroupPrivacy(type.call, declSymbol, errorCallback);\n            this.checkSignatureGroupPrivacy(type.construct, declSymbol, errorCallback);\n            this.checkSignatureGroupPrivacy(type.index, declSymbol, errorCallback);\n        }\n\n        // Checks if the privacy is satisfied by typeSymbol that is used in the declaration inside container\n        private checkSignatureGroupPrivacy(sgroup: SignatureGroup, declSymbol: Symbol, errorCallback: (typeName: string, isModuleName : bool) =>void ) {\n            if (sgroup) {\n                var len = sgroup.signatures.length;\n                for (var i = 0; i < sgroup.signatures.length; i++) {\n                    var signature = sgroup.signatures[i];\n                    if (len > 1 && signature == sgroup.definitionSignature) {\n                        // In case of overloads don't look up for overload defintion types.\n                        continue;\n                    }\n\n                    if (signature.returnType) {\n                        this.checkTypePrivacy(signature.returnType.type, declSymbol, errorCallback);\n                    }\n\n                    var paramLen = signature.parameters.length;\n                    for (var j = 0; j < paramLen; j++) {\n                        var param = signature.parameters[j];\n                        this.checkTypePrivacy(param.getType(), declSymbol, errorCallback);\n                    }\n                }\n            }\n        }\n\n        private functionArgumentPrivacyErrorReporter(funcDecl: FuncDecl, p: number, paramSymbol: Symbol, typeName: string, isModuleName: bool) {\n            var isGetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor);\n            var isSetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.SetAccessor);\n            var isPublicFunc = hasFlag(funcDecl.fncFlags, FncFlags.Public);\n            var isContainerInterface = funcDecl.type.symbol.getInterfaceDeclFromSymbol(this.checker) != null;\n            var typestring = \"\";\n            if (isModuleName) {\n                var quotestring = \"\";\n                if (!isQuoted(typeName)) {\n                    quotestring = \"'\";\n                }\n                typestring = \" is using inaccessible module \" + quotestring + typeName + quotestring;\n            } else {\n                typestring = \" has or is using private type '\" + typeName + \"'\";\n            }\n\n            if (!isContainerInterface) {\n                if (funcDecl.isConstructor) {\n                    this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], \"exported class's constructor parameter '\" + paramSymbol.name + \"'\" + typestring);\n                } else if (isSetter) {\n                    this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], (isPublicFunc ? \"public\" : \"exported\") + \" setter parameter '\" + paramSymbol.name + \"'\" + typestring);\n                } else if (!isGetter) {\n                    this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], (isPublicFunc ? \"public\" : \"exported\") + \" function parameter '\" + paramSymbol.name + \"'\" + typestring);\n                }\n            } else {\n                if (funcDecl.isConstructMember()) {\n                    this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], \"exported interface's constructor parameter '\" + paramSymbol.name + \"'\" + typestring);\n                } else if (funcDecl.isCallMember()) {\n                    this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], \"exported interface's call parameter '\" + paramSymbol.name + \"'\" + typestring);\n                } else if (!funcDecl.isIndexerMember()) {\n                    this.checker.errorReporter.simpleError(funcDecl.arguments.members[p], \"exported interface's function parameter '\" + paramSymbol.name + \"'\" + typestring);\n                }\n            }\n        }\n\n        private returnTypePrivacyError(astError: AST, funcDecl: FuncDecl, typeName: string, isModuleName: bool) {\n            var isGetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor);\n            var isSetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.SetAccessor);\n            var isPublicFunc = hasFlag(funcDecl.fncFlags, FncFlags.Public);\n            var isContainerInterface = funcDecl.type.symbol.getInterfaceDeclFromSymbol(this.checker) != null;\n            var typestring = \"\";\n            if (isModuleName) {\n                var quotestring = \"\";\n                if (!isQuoted(typeName)) {\n                    quotestring = \"'\";\n                }\n                typestring = \" is using inaccessible module \" + quotestring + typeName + quotestring;\n            } else {\n                typestring = \" has or is using private type '\" + typeName + \"'\";\n            }\n            if (!isContainerInterface) {\n                if (isGetter) {\n                    this.checker.errorReporter.simpleError(astError, (isPublicFunc ? \"public\" : \"exported\") + \" getter return type\" + typestring);\n                } else if (!isSetter) {\n                    this.checker.errorReporter.simpleError(astError, (isPublicFunc ? \"public\" : \"exported\") + \" function return type\" + typestring);\n                }\n            } else {\n                if (funcDecl.isConstructMember()) {\n                    this.checker.errorReporter.simpleError(astError, \"exported interface's constructor return type\" + typestring);\n                } else if (funcDecl.isCallMember()) {\n                    this.checker.errorReporter.simpleError(astError, \"exported interface's call return type\" + typestring);\n                } else if (funcDecl.isIndexerMember()) {\n                    this.checker.errorReporter.simpleError(astError, \"exported interface's indexer return type\" + typestring);\n                } else {\n                    this.checker.errorReporter.simpleError(astError, \"exported interface's function return type\" + typestring);\n                }\n            }\n        }\n\n        private functionReturnTypePrivacyErrorReporter(funcDecl: FuncDecl, signature: Signature, typeName: string, isModuleName: bool) {\n            var reportOnFuncDecl = false;\n\n            // Error coming from return annotation\n            if (funcDecl.returnTypeAnnotation != null &&\n                funcDecl.returnTypeAnnotation.type == signature.returnType.type) {\n                this.returnTypePrivacyError(funcDecl.returnTypeAnnotation, funcDecl, typeName, isModuleName);\n            }\n\n            // Check if return statement's type matches the one that we concluded\n            for (var i = 0; i < funcDecl.returnStatementsWithExpressions.length; i++) {\n                if (funcDecl.returnStatementsWithExpressions[i].type == signature.returnType.type) {\n                    this.returnTypePrivacyError(funcDecl.returnStatementsWithExpressions[i], funcDecl, typeName, isModuleName);\n                } else {\n                    reportOnFuncDecl = true;\n                }\n            }\n\n            if (reportOnFuncDecl) {\n                // Show on function decl\n                this.returnTypePrivacyError(funcDecl, funcDecl, typeName, isModuleName);\n            }\n        }\n\n        public typeCheckFunction(funcDecl: FuncDecl): FuncDecl {\n            this.nestingLevel = 0;\n            var fnType = funcDecl.type;\n\n            var fgSym = fnType.symbol;\n            var signature = funcDecl.signature;\n\n            if (this.checker.typeStatusIsFinished(signature.typeCheckStatus)) {\n                return funcDecl;\n            }\n            else if (signature.typeCheckStatus == TypeCheckStatus.Started) {\n                if (!funcDecl.returnTypeAnnotation &&\n                    funcDecl.bod &&\n                       !funcDecl.isSignature() &&\n                       !(funcDecl.isConstructor) &&\n                       this.allReturnsAreVoid(funcDecl)) {\n\n                    signature.returnType.type = this.voidType;\n                    return funcDecl;\n                }\n                else {\n                    if (funcDecl.returnTypeAnnotation == null) {\n                        if (this.checker.styleSettings.implicitAny) {\n                            this.checker.errorReporter.styleError(funcDecl, \"type implicitly set to 'any'\");\n                        }\n                        signature.returnType.type = this.anyType;\n                        fgSym.flags |= SymbolFlags.RecursivelyReferenced;\n                    }\n                    return funcDecl;\n                }\n            }\n\n            signature.typeCheckStatus = TypeCheckStatus.Started;\n            this.checker.addStartedPTO(signature);\n            var prevScope = this.scope;\n            var prevFnc = this.thisFnc;\n            var prevMethodStatus = this.enclosingFncIsMethod;\n            var prevClassNode = this.thisClassNode;\n            this.enclosingFncIsMethod = funcDecl.isMethod() || funcDecl.isConstructor;\n            this.thisFnc = funcDecl;\n            var container = funcDecl.type.symbol;\n            var prevThisType = this.thisType;\n            var prevLocationInfo = this.checker.locationInfo;\n            var funcTable: IHashTable = null;\n            var acceptedContextualType = false;\n            var targetParams: ParameterSymbol[] = null;\n            var targetReturnType: Type = null;\n            var isGetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor);\n            var isSetter = funcDecl.isAccessor() && hasFlag(funcDecl.fncFlags, FncFlags.SetAccessor);\n            var accessorType: Type = (isGetter || isSetter) && funcDecl.accessorSymbol ? funcDecl.accessorSymbol.getType() : null;\n            var prevModDecl = this.checker.currentModDecl;\n\n            if (funcDecl.isConstructor && !funcDecl.isOverload) {\n                if (fnType.instanceType == null) {\n                    this.checker.errorReporter.simpleError(funcDecl, \"Malformed function body (is this a class named the same as an existing interface?)\");\n                    return funcDecl;\n                }\n\n                this.scope = fnType.instanceType.constructorScope;\n                var ssb = <SymbolScopeBuilder>this.scope;\n                funcTable = ssb.valueMembers.allMembers;\n            }\n            else if ((funcDecl.isSpecialFn() && !(funcDecl.fncFlags & FncFlags.Signature)) || funcDecl.isOverload) {\n                funcTable = funcDecl.symbols;\n                // if the function is static, we just want to use the \n                // current scope\n                if (!hasFlag(funcDecl.fncFlags, FncFlags.Static) && fnType.containedScope) {\n                    this.scope = fnType.containedScope;\n                }\n            }\n            else {\n                if (funcDecl.bod) {\n                    this.scope = fnType.containedScope;\n                }\n                var ssb = <SymbolScopeBuilder>this.scope;\n\n                // If it is null, it's an ambient declaration with no body, so it doesn't strictly matter\n                // if funcTable is not set\n                if (ssb && ssb.valueMembers) {\n                    funcTable = ssb.valueMembers.allMembers;\n                }\n            }\n\n            // If it's a class constructor, we need to check for the presence (or absense) of calls\n            // to the 'super' constructor\n            //\n            // A super constructor call must exist if:\n            //  - the class has a base class\n            //\n            // A super constructor call must be the first statement in the function body if:\n            //  - the constructor has parameter properties or\n            //  - the class body has initialized property decls\n            //\n            // A super constructor call may not exist if:\n            //  - The class has no base type, or inherits directly from 'Object'\n            if (funcDecl.isConstructor && funcDecl.bod && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {\n\n                var hasBaseType = hasFlag(funcDecl.classDecl.type.instanceType.typeFlags, TypeFlags.HasBaseType);\n                var noSuperCallAllowed = !hasBaseType || hasFlag(funcDecl.classDecl.type.instanceType.typeFlags, TypeFlags.HasBaseTypeOfObject);\n                var superCallMustBeFirst = hasFlag((<ClassDeclaration>funcDecl.classDecl).varFlags, VarFlags.ClassSuperMustBeFirstCallInConstructor);\n\n                if (noSuperCallAllowed && this.classConstructorHasSuperCall(funcDecl)) {\n                    this.checker.errorReporter.simpleError(funcDecl, \"Calls to 'super' constructor are not allowed in classes that either inherit directly from 'Object' or have no base class\");\n                }\n                else if (hasBaseType) {\n                    if (superCallMustBeFirst) {\n                        if (!funcDecl.bod ||\n                            !funcDecl.bod.members.length ||\n                            !((funcDecl.bod.members[0].nodeType == NodeType.Call && (<CallExpression>funcDecl.bod.members[0]).target.nodeType == NodeType.Super) ||\n                            (hasFlag(funcDecl.bod.flags, ASTFlags.StrictMode) && funcDecl.bod.members.length > 1 &&\n                             funcDecl.bod.members[1].nodeType == NodeType.Call && (<CallExpression>funcDecl.bod.members[1]).target.nodeType == NodeType.Super))) {\n                            this.checker.errorReporter.simpleError(funcDecl, \"If a derived class contains initialized properties or constructor parameter properties, the first statement in the constructor body must be a call to the super constructor\");\n                        }\n                    }\n                    else if (!this.classConstructorHasSuperCall(funcDecl)) {\n                        this.checker.errorReporter.simpleError(funcDecl, \"Constructors for derived classes must contain a call to the class's 'super' constructor\");\n                    }\n                }\n            }\n\n            // If we've typechecked this method \"out of order\" (not by walking the class, but through a method call somewhere else),\n            // we need to reset the current class node in question, so that visibility checks on class members don't fail\n            if (funcDecl.isMethod() && funcDecl.type.enclosingType) {\n\n                var enclosingClassNode: TypeDeclaration = null;\n\n                if (funcDecl.type.enclosingType.symbol.declAST.nodeType == NodeType.FuncDecl) {\n                    enclosingClassNode = <TypeDeclaration>(<FuncDecl>funcDecl.type.enclosingType.symbol.declAST).classDecl;\n                }\n                else if (funcDecl.type.enclosingType.symbol.declAST.nodeType == NodeType.ClassDeclaration) {\n                    enclosingClassNode = <TypeDeclaration>funcDecl.type.enclosingType.symbol.declAST;\n                }\n\n                if (enclosingClassNode) {\n                    this.thisClassNode = enclosingClassNode;\n                }\n            }\n\n            // if this function is contained in a module, we may be in the midst of a recursive typecheck operation\n            // should that be the case, we need to properly set the current module (for visibility tests)\n            if (fnType.enclosingType) {;\n                var enclosingSym = fnType.symbol.container;\n\n                // if the enclosing type is a class, grab the parent module\n                if (enclosingSym && enclosingSym.isType() && enclosingSym.getType().isClass()) {\n                    enclosingSym = enclosingSym.container;\n                }\n\n                if (enclosingSym && enclosingSym.declAST && enclosingSym.declAST.nodeType == NodeType.ModuleDeclaration) {\n                    this.checker.currentModDecl = <ModuleDeclaration>enclosingSym.declAST;\n                }\n            }\n\n            if (funcDecl.unitIndex > 0) {\n                if (this.checker.units &&\n                    (funcDecl.unitIndex < this.checker.units.length)) {\n                    this.checker.locationInfo = this.checker.units[funcDecl.unitIndex];\n                }\n                else {\n                    this.checker.locationInfo = unknownLocationInfo;\n                }\n            }\n\n            if (fnType.enclosingType) {\n                this.thisType = fnType.enclosingType;\n            }\n            else {\n                this.thisType = prevThisType;\n            }\n\n            var paramLen = signature.parameters.length;\n\n            if (!funcDecl.isConstructor && funcDecl.bod && !funcDecl.isSignature()) {\n                var tmpParamScope = this.scope;\n                var ssb = <SymbolScopeBuilder>this.scope;\n\n                // Attempt to contextually type the function declaration             \n                if (!funcDecl.isMethod() && funcDecl.returnTypeAnnotation == null) {\n\n                    // the funcDecl may be a candidate for contextual typing                 \n                    // REVIEW: prevScope will only be null in the case of an upstream error\n                    if (prevScope && funcDecl.name && !funcDecl.name.isMissing()) {\n                        // Go ahead and check for an ambient symbol\n                        var considerSym: Symbol = prevScope.findAmbient(funcDecl.name.text, false, false);\n\n                        if (considerSym && considerSym.declAST && considerSym.declAST.type) {\n                            // REVIEW: Ambients beget signatures, and signatures don't need to be typechecked\n                            //typeCheck(considerSym.declAST);\n                            this.checker.setContextualType(considerSym.declAST.type, false);\n                        }\n                    }\n\n                    if (this.checker.hasTargetType()) {\n                        var candidateTypeContext = this.checker.getTargetTypeContext();\n                        var candidateType = candidateTypeContext.contextualType;\n\n                        if (this.checker.canContextuallyTypeFunction(candidateType, funcDecl, true)) {\n\n                            // Safe to do this, since the indices and fields are guaranteed to be\n                            // non-null and valid by the above call to canContextuallyTypeFunction\n                            var candidateSigs = candidateType.construct ? candidateType.construct : candidateType.call;\n                            candidateTypeContext.targetSig = candidateSigs.signatures[0];\n                            var candidateParams = candidateTypeContext.targetSig.parameters;\n\n                            // the target type has been accepted\n                            targetParams = candidateParams;\n                            targetReturnType = candidateTypeContext.targetSig.returnType.type;\n\n                            // Set \"this\" if applicable\n                            if (candidateTypeContext.targetSig.declAST) {\n                                if (candidateTypeContext.targetSig.declAST.isConstructor) {\n                                    //candidateTypeContext.targetThis=candidateType.instanceType;\n                                    //this.thisType = candidateType.instanceType;\n                                    funcDecl.isTargetTypedAsMethod = true;\n                                }\n                                else if (candidateTypeContext.targetSig.declAST.isMethod()) {\n                                    //candidateTypeContext.targetThis=candidateTypeContext.targetSig.declAST.type.enclosingType;\n                                    //this.thisType = candidateTypeContext.targetSig.declAST.type.enclosingType;\n                                    funcDecl.isTargetTypedAsMethod = true;\n                                }\n                            }\n                            fgSym.type = candidateTypeContext.contextualType;\n                            acceptedContextualType = true;\n                        }\n                        else if (candidateType && funcDecl.isAccessor()) {\n                            accessorType = candidateType;\n                            candidateTypeContext.targetAccessorType = accessorType;\n                        }\n                        else {\n                            this.checker.killCurrentContextualType();\n                        }\n                    }\n                }\n\n                // typecheck parameters\n                // Add parameter symbols to current scope for typechecking (in case default params reference each other)\n                // Order matters here - default parameters can reference previously defined parameters\n                var paramTable = ssb.valueMembers;\n                this.scope = new SymbolScopeBuilder(paramTable, null, null, null, prevScope, container);\n\n                for (var p = 0; p < paramLen; p++) {\n                    var symbol = signature.parameters[p];\n                    var ast = <ArgDecl>symbol.declAST\n\n                    if (this.checker.hasTargetType() && (targetParams && (this.checker.getTargetTypeContext().targetSig.hasVariableArgList || p < targetParams.length))) {\n                        var candidateTypeContext = this.checker.getTargetTypeContext();\n                        var hasVarArgList = candidateTypeContext.targetSig.hasVariableArgList;\n                        ast.type = hasVarArgList && p >= targetParams.length - 1 ? targetParams[targetParams.length - 1].getType().elementType : targetParams[p].getType();\n                        ast.sym.setType(ast.type);\n                        (<InferenceSymbol>ast.sym).typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n                    }\n                    else {\n                        this.typeCheck(ast);\n                    }\n\n                    // infer the setter type, if necessary\n                    if (isSetter && accessorType) {\n                        ast = <ArgDecl>this.cast(ast, accessorType);\n                    }\n\n                    symbol.container = container;\n                    // Verify the parameter for the privacy\n                    this.checkTypePrivacy(symbol.getType(), container, (typeName: string, isModuleName: bool) => this.functionArgumentPrivacyErrorReporter(funcDecl, p, symbol, typeName, isModuleName));\n                    paramTable.publicMembers.add(symbol.name, symbol);\n                }\n                this.scope = tmpParamScope;\n            }\n            else {\n                this.typeCheck(funcDecl.arguments)\n\n                // Because some terms were not yet type-checkable during binding, ensure that\n                // param symbols are updated with the proper argument types\n                for (var p = 0; p < paramLen; p++) {\n                    signature.parameters[p].parameter.typeLink.type = funcDecl.arguments.members[p].type;\n                    // Verify the parameter for the privacy\n                    this.checkTypePrivacy(signature.parameters[p].getType(), container, (typeName: string, isModuleName: bool) => this.functionArgumentPrivacyErrorReporter(funcDecl, p, signature.parameters[p], typeName, isModuleName));\n                    if ((<ArgDecl>funcDecl.arguments.members[p]).parameterPropertySym) {\n                        (<ArgDecl>funcDecl.arguments.members[p]).parameterPropertySym.setType(funcDecl.arguments.members[p].type);\n                    }\n                }\n\n                if ((funcDecl.fncFlags & FncFlags.IndexerMember)) {\n                    if (!paramLen || paramLen > 1) {\n                        this.checker.errorReporter.simpleError(funcDecl, \"Index signatures may take one and only one parameter\");\n                    }\n                    else if (funcDecl.arguments.members[0].type == this.checker.numberType) {\n                        fnType.index.flags |= SignatureFlags.IsNumberIndexer;\n                    }\n                    else if (funcDecl.arguments.members[0].type == this.checker.stringType) {\n                        fnType.index.flags |= SignatureFlags.IsStringIndexer;\n                    }\n                    else {\n                        this.checker.errorReporter.simpleError(funcDecl.arguments.members[0], \"Index signatures may only take 'string' or 'number' as their parameter\");\n                    }\n\n                }\n            }\n\n            // typecheck body\n            if (funcDecl.bod && (!funcDecl.isSignature())) {\n                if (!(funcDecl.isConstructor)) {\n                    this.addFormals(container, signature, funcTable);\n                }\n                else {\n                    this.addConstructorLocalArgs(funcDecl.type.symbol, funcDecl.arguments, funcTable, hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod));\n\n                    if (this.thisClassNode && this.thisClassNode.extendsList) {\n                        var tmpScope = this.scope;\n                        var funcMembers = new ScopedMembers(<DualStringHashTable>funcTable);\n                        this.scope = new FilteredSymbolScopeBuilder(funcMembers, prevScope, funcDecl.type.symbol,\n                                                             function (sym) {\n                                                                 return sym.kind() == SymbolKind.Parameter;\n                                                             });\n                        this.typeCheckBaseCalls(this.thisClassNode.extendsList);\n                        this.scope = tmpScope;\n                    }\n                }\n\n                // Because this function may have been typechecked in a different visiblity context as its caller (e.g., this\n                // function is being typechecked as a result of a call, before the declaration could be typechecked), we need\n                // to set the enclosing module\n                var prevMod = this.checker.currentModDecl;\n                if (funcDecl.type &&\n                    funcDecl.type.symbol &&\n                    !funcDecl.isMethod() &&\n                    funcDecl.type.symbol.declModule) {\n                    this.checker.currentModDecl = funcDecl.type.symbol.declModule;\n                }\n\n\n                // unset the contextual type before typechecking the function body\n                if (acceptedContextualType) {\n                    this.checker.setContextualType(null, this.checker.inProvisionalTypecheckMode());\n                }\n\n                this.typeCheck(funcDecl.bod);\n\n                if (acceptedContextualType) {\n                    this.checker.unsetContextualType();\n                }\n\n                this.checker.currentModDecl = prevMod;\n\n                if (this.checker.checkControlFlow) {\n                    var cfg = funcDecl.buildControlFlow();\n                    if (this.checker.printControlFlowGraph) {\n                        cfg.print(this.checker.errorReporter.outfile);\n                    }\n                    cfg.reportUnreachable(this.checker.errorReporter);\n                    if (this.checker.checkControlFlowUseDef) {\n                        cfg.useDef(this.checker.errorReporter, funcDecl.type.symbol);\n                    }\n                }\n\n                if (funcDecl.isConstructor) {\n                    var fns: ASTList = funcDecl.scopes;\n                    var fnsLen = fns.members.length;\n                    var freeVars: Symbol[];\n                    var sym: Symbol;\n                    var j = 0;\n                    for (; j < fnsLen; j++) {\n                        var fn = <FuncDecl>fns.members[j];\n                        if (!fn.isSignature()) {\n                            if (hasFlag(fn.fncFlags, FncFlags.Method) && (!hasFlag(fn.fncFlags, FncFlags.Static))) {\n                                this.checkPromoteFreeVars(fn, funcDecl.type.symbol);\n                            }\n                        }\n                    }\n                }\n            }\n\n            this.scope = prevScope;\n            this.thisFnc = prevFnc;\n            this.thisClassNode = prevClassNode;\n            this.enclosingFncIsMethod = prevMethodStatus;\n            this.thisType = prevThisType;\n            this.checker.locationInfo = prevLocationInfo;\n            this.checker.currentModDecl = prevModDecl;\n\n            signature.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n\n            // set the return type\n            if (funcDecl.returnTypeAnnotation) {\n                this.checkForVoidConstructor(funcDecl.returnTypeAnnotation.type, funcDecl.returnTypeAnnotation);\n\n                if (signature.returnType.type == null) {\n                    this.checker.resolveTypeLink(this.scope, signature.returnType, false);\n                }\n            }\n            else if (targetReturnType) {\n                signature.returnType.type = targetReturnType;\n            }\n\n            // If no return type annotation has been applied to the function declaration\n            // unify the return types from the given return statements\n\n            if (!(fgSym.flags & SymbolFlags.RecursivelyReferenced) && funcDecl.returnStatementsWithExpressions.length > 0) {\n                var collection: ITypeCollection = {\n                    getLength: () => { return funcDecl.returnStatementsWithExpressions.length; },\n                    setTypeAtIndex: (index: number, type: Type) => { funcDecl.returnStatementsWithExpressions[index].type = type; },\n                    getTypeAtIndex: (index: number) => { return funcDecl.returnStatementsWithExpressions[index].type; }\n                }\n\n                var bestCommonReturnType = funcDecl.returnStatementsWithExpressions[0].type;\n                bestCommonReturnType = this.checker.findBestCommonType(bestCommonReturnType, null, collection, true);\n\n                if (bestCommonReturnType) {\n                    signature.returnType.type = this.checker.widenType(bestCommonReturnType);\n                }\n                else {\n                    for (var i = 0; i < funcDecl.returnStatementsWithExpressions.length; i++) {\n                        this.checker.errorReporter.simpleError(funcDecl.returnStatementsWithExpressions[i], \"Incompatible return type\");\n                    }\n                    signature.returnType.type = this.anyType;\n                }\n            }\n\n            var onlyHasThrow = false;\n\n            if (signature.returnType.type == null) {\n                if (hasFlag(funcDecl.fncFlags, FncFlags.HasReturnExpression)) {\n                    if (this.checker.styleSettings.implicitAny) {\n                        this.checker.errorReporter.styleError(funcDecl, \"type implicitly set to 'any'\");\n                    }\n                    signature.returnType.type = this.anyType;\n                }\n                else {\n                    signature.returnType.type = this.voidType;\n                }\n            }\n            else if (signature.returnType.type == this.nullType || signature.returnType.type == this.checker.undefinedType) {\n                signature.returnType.type = this.anyType;\n            }\n            else if ((signature.returnType.type != this.voidType && signature.returnType.type != this.checker.undefinedType && signature.returnType.type != this.anyType)) {\n                // the signature declared a non-void type, but there's no return statement\n                if (!funcDecl.isSignature() &&\n                    !funcDecl.isConstructor &&\n                    !hasFlag(funcDecl.fncFlags, FncFlags.HasReturnExpression) &&\n                    !hasFlag(funcDecl.fncFlags, FncFlags.IsFatArrowFunction)) {\n                        // relax the restriction if the method only contains a single \"throw\" statement\n                    onlyHasThrow = (funcDecl.bod.members.length > 0) && (funcDecl.bod.members[0].nodeType == NodeType.Throw)\n\n                    if (!onlyHasThrow) {\n                        this.checker.errorReporter.simpleError(funcDecl.returnTypeAnnotation || funcDecl,\n                             \"Function declared a non-void return type, but has no return expression\");\n                    }\n                }\n\n                // Type check for return type Privacy\n                this.checkTypePrivacy(signature.returnType.type, container, (typeName: string, isModuleName: bool) => this.functionReturnTypePrivacyErrorReporter(funcDecl, signature, typeName, isModuleName));\n            }\n\n            // if the function declaration is a getter or a setter, set the type of the associated getter/setter symbol\n            if (funcDecl.accessorSymbol) {\n                var accessorType = funcDecl.accessorSymbol.getType();\n                if (!onlyHasThrow && hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor) && !hasFlag(funcDecl.fncFlags, FncFlags.HasReturnExpression)) {\n                    this.checker.errorReporter.simpleError(funcDecl, \"Getters must return a value\");\n                }\n                if (accessorType) {\n                    if ((hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor) && accessorType != signature.returnType.type) ||\n                        (funcDecl.arguments.members.length > 0 && accessorType != funcDecl.arguments.members[0].type)) {\n                        this.checker.errorReporter.simpleError(funcDecl, \"Getter and setter types do not agree\");\n                    }\n                }\n                else {\n                    if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n                        funcDecl.accessorSymbol.setType(signature.returnType.type);\n                    }\n                    else {\n                        if (funcDecl.arguments.members.length != 1) {\n                            this.checker.errorReporter.simpleError(funcDecl, \"Setters may have one and only one argument\");\n                        }\n                        else {\n                            funcDecl.accessorSymbol.setType(funcDecl.arguments.members[0].type);\n                        }\n                    }\n                }\n            }\n\n            this.typeCheckOverloadSignatures(fnType, funcDecl);\n            return funcDecl;\n        }\n\n        public typeCheckBases(type: Type) {\n            var seenInterface = false;\n            var bases = type.extendsList;\n            var baseLinks = type.extendsTypeLinks;\n            if (bases) {\n                var len = bases.length;\n\n                if (len > 0) {\n                    type.typeFlags |= TypeFlags.HasBaseType;\n                }\n\n                for (var i = 0; i < len; i++) {\n                    if (bases[i] == this.checker.anyType) {\n                        // This may be the type from imported module and hence the type was not really resolved to the correct one.\n                        // Try resolving it again\n                        baseLinks[i].type = null;\n                        // There are no contextual errors when trying to verify the base class\n                        var oldErrors = this.checker.errorReporter.getCapturedErrors();\n                        CompilerDiagnostics.assert(oldErrors.length == 0, \"There shouldnt be any contextual errors when typechecking base type names\");\n                        this.checker.errorReporter.pushToErrorSink = true;\n                        bases[i] = this.checker.resolveBaseTypeLink(baseLinks[i], type.containedScope);\n                        this.checker.errorReporter.pushToErrorSink = false;\n                        this.checker.errorReporter.freeCapturedErrors();\n                    }\n\n                    var base = bases[i];\n                    var baseRef = baseLinks[i].ast;\n\n                    // make sure it's the global 'Object' and not some alias\n                    var baseTypeOfObject = base.symbol && base.symbol.name == \"Object\" && base.symbol.container == this.checker.gloMod;\n\n                    if (baseTypeOfObject) {\n                        type.typeFlags |= TypeFlags.HasBaseTypeOfObject;\n                    }\n\n                    if (base.isClassInstance()) {\n                        if (!(type.isClassInstance())) {\n                            this.checker.errorReporter.simpleError(baseRef, \"Interface base type must be interface\");\n                        }\n                        else {\n                            if (seenInterface) {\n                                this.checker.errorReporter.simpleError(baseRef, \"Class may not follow interface as base type\");\n                            }\n                        }\n                    }\n                    else if (base.isModuleType()) {\n                        this.checker.errorReporter.simpleError(baseRef, \"Types may not be derived from module types\");\n                    }\n                    else if (base.members) {\n                        if (!seenInterface) {\n                            seenInterface = true;\n                        }\n                    }\n                    else {\n                        if (!(type.isClassInstance())) {\n                            this.checker.errorReporter.simpleError(baseRef,\n                                                                     \"Interface base type must be interface\");\n                        }\n                        else {\n                            this.checker.errorReporter.simpleError(baseRef,\n                                                                     \"Base type must be interface or class\");\n                        }\n                        break;\n                    }\n                }\n            }\n        }\n\n        public checkMembersImplementInterfaces(implementingType: Type) {\n            var instanceType = implementingType.getInstanceType();\n            if (instanceType.implementsList) {\n                var len = instanceType.implementsList.length;\n\n                for (var i = 0; i < len; i++) {\n                    var interfaceType = instanceType.implementsList[i];\n                    var comparisonInfo = new TypeComparisonInfo();\n                    if (!this.checker.sourceIsSubtypeOfTarget(instanceType, interfaceType, comparisonInfo)) {\n                        var emsg = \"Class '\" + instanceType.getTypeName() +\n                              \"' declares interface '\" + interfaceType.getTypeName() +\n                              \"' but does not implement it\";\n                        if (!comparisonInfo.message) {\n                            this.checker.errorReporter.simpleErrorFromSym(instanceType.symbol, emsg);\n                        }\n                        else {\n                            this.checker.errorReporter.simpleErrorFromSym(instanceType.symbol, emsg + \": \" + comparisonInfo.message);\n                        }\n                    }\n                }\n            }\n        }\n\n        public typeCheckBaseCalls(bases: ASTList) {\n            if (bases == null) {\n                return;\n            }\n            var basesLen = bases.members.length;\n            for (var i = 0; i < basesLen; i++) {\n                var baseExpr = bases.members[i];\n                var baseSymbol: Symbol = null;\n                if (baseExpr.nodeType == NodeType.Call) {\n                    this.typeCheckNew(baseExpr);\n                }\n            }\n        }\n\n        public assertUniqueNamesInBaseTypes(names: IHashTable, type: Type, classDecl: InterfaceDeclaration, checkUnique: bool): void {\n            if (type) {\n                if (type.members) {\n                    type.members.publicMembers.map((key, s, c) => {\n                        var sym = <Symbol>s;\n                        var dup = names.lookup(sym.name);\n                        if (dup) {\n                            if (checkUnique) {\n                                this.checker.errorReporter.simpleError(classDecl,\n                                                                  \"duplicate member name in bases for \" + classDecl.name.actualText + \": \" + type.symbol.name + \" and \" + dup.container.name + \" both contain member with name \" + sym.name);\n                            }\n                        }\n                        else {\n                            names.add(sym.name, sym);\n                        }\n                    }, null);\n                }\n                if (type.extendsList) {\n                    var len = type.extendsList.length;\n                    for (var i = 0; i < len; i++) {\n                        if (!(type.extendsList[i].symbol.flags & SymbolFlags.RecursivelyReferenced)) {\n                            this.assertUniqueNamesInBaseTypes(names, type.extendsList[i], classDecl, checkUnique);\n                        }\n                    }\n                }\n            }\n        }\n\n        public checkBaseTypeMemberInheritance(derivedType: Type, derivedTypeDecl: AST): void {\n            var instanceType = derivedType.getInstanceType();\n            if (instanceType.extendsList == null) {\n                return;\n            }\n\n            var len = instanceType.extendsList.length;\n            if (len > 0) {\n                var names = new StringHashTable();\n                if (instanceType.isClassInstance()) {\n                    for (var i = 0; i < len; i++) {\n                        this.assertUniqueNamesInBaseTypes(names, instanceType.extendsList[i], <InterfaceDeclaration>derivedTypeDecl, i > 0);\n                    }\n                }\n\n                if (instanceType.members) {\n                    instanceType.members.publicMembers.map((key, s, c) => {\n                        var sym = <Symbol>s;\n                        for (var j = 0; j < len; j++) {\n                            var base = instanceType.extendsList[j];\n                            if (base.memberScope == null) {\n                                this.checker.errorReporter.simpleError(derivedTypeDecl, \"Base type '\" + base.symbol.name + \"' lacks an implementation.\")\n                            }\n                            else {\n                                var bSym = base.memberScope.find(sym.name, false, false);\n                                if (bSym) {\n                                    var aType = sym.getType();\n                                    var bType = bSym.getType();\n                                    if (!(this.checker.sourceIsSubtypeOfTarget(aType, bType))) {\n                                        this.checker.errorReporter.simpleErrorFromSym(sym,\n                                                                          \"Type of overridden member '\" + sym.name + \"' is not subtype of original member defined by type '\" + bSym.container.name + \"'\");\n                                    }\n                                    else if ((sym.kind() == SymbolKind.Type) &&\n                                             (bSym.kind() == SymbolKind.Field)) {\n                                        this.checker.errorReporter.simpleErrorFromSym(sym,\n                                                                          \"Cannot override field '\" + sym.name + \"' with method\");\n                                    }\n                                }\n                            }\n                        }\n                    }, null);\n                }\n            }\n        }\n\n        public typeCheckClass(classDecl: ClassDeclaration): ClassDeclaration {\n            var typeSymbol = <TypeSymbol>classDecl.type.symbol;\n\n            if (typeSymbol.typeCheckStatus == TypeCheckStatus.Finished) {\n                return classDecl;\n            }\n            else if (typeSymbol.typeCheckStatus == TypeCheckStatus.Started) {\n                // REVIEW: report this recursion\n                //checker.errorReporter.recursionRequiresTypeAnnotation(classDecl);\n                return classDecl;\n            }\n            else {\n                typeSymbol.typeCheckStatus = TypeCheckStatus.Started;\n                this.checker.addStartedPTO(typeSymbol);\n            }\n\n            var prevScope = this.scope;\n            var svClassNode = this.thisClassNode;\n            this.thisClassNode = classDecl;\n            var classType = classDecl.type;\n            this.typeCheckBases(classType.instanceType);\n\n            this.typeCheckBaseListPrivacy(classDecl.extendsList, typeSymbol, true);\n            this.typeCheckBaseListPrivacy(classDecl.implementsList, typeSymbol, false);\n\n            var prevThisType = this.thisType;\n            this.thisType = classType.instanceType;\n            this.scope = classType.instanceType.containedScope;\n\n            // Add the constructor locals, if necessary\n            if (classDecl.constructorDecl) {\n                this.scope = classType.instanceType.constructorScope;\n                var ssb = <SymbolScopeBuilder>this.scope;\n                var funcTable = ssb.valueMembers.allMembers;\n\n                this.addConstructorLocalArgs(classDecl.constructorDecl.type.symbol, classDecl.constructorDecl.arguments, funcTable, true);\n            }\n\n            this.typeCheck(classDecl.members);\n            typeSymbol.typeCheckStatus = TypeCheckStatus.Finished;\n            this.checkBaseTypeMemberInheritance(classType, classDecl);\n            this.checkMembersImplementInterfaces(classType);\n\n            this.typeCheckOverloadSignatures(classType, classDecl);\n            this.typeCheckOverloadSignatures(classType.instanceType, classDecl);\n\n            // if the class has no declared constructor, adapt its base class's signature group, if necessary\n            if (!classDecl.constructorDecl) {\n                if (classDecl.extendsList &&\n                    classDecl.extendsList.members.length &&\n                    classDecl.extendsList.members[0].type &&\n                    classDecl.extendsList.members[0].type.symbol.type.isClass()) {\n                    cloneParentConstructGroupForChildType(classDecl.type, classDecl.extendsList.members[0].type.symbol.type);\n                }\n            }\n\n            this.thisType = prevThisType;\n            this.thisClassNode = svClassNode;\n            this.scope = prevScope;\n            return classDecl;\n        }\n\n        public typeCheckOverloadSignatures(type: Type, ast: AST) {\n            if (type.call) {\n                type.call.typeCheck(this.checker, ast, type.construct != null);\n            }\n            if (type.construct) {\n                type.construct.typeCheck(this.checker, ast, false);\n            }\n            if (type.index) {\n                type.index.typeCheck(this.checker, ast, false);\n            }\n        }\n\n        public typeCheckInterface(interfaceDecl: InterfaceDeclaration): InterfaceDeclaration {\n            // overloads will be typechecked inline by the members\n            //this.typeCheckOverloadSignatures(interfaceDecl.type, interfaceDecl);\n            this.typeCheckBases(interfaceDecl.type);\n            this.typeCheckBaseListPrivacy(interfaceDecl.extendsList, interfaceDecl.type.symbol, true);\n            this.typeCheck(interfaceDecl.members);\n            this.checkBaseTypeMemberInheritance(interfaceDecl.type, interfaceDecl);\n\n            // propagate base type signatures\n            if (interfaceDecl.extendsList) {\n                for (var i = 0; i < interfaceDecl.extendsList.members.length; i++) {\n                    if (interfaceDecl.extendsList.members[i].type.call) {\n                        if (interfaceDecl.type.call) {\n                            interfaceDecl.type.call.signatures = interfaceDecl.type.call.signatures.concat(interfaceDecl.extendsList.members[i].type.call.signatures);\n                        }\n                        else {\n                            interfaceDecl.type.call = interfaceDecl.extendsList.members[i].type.call;\n                        }\n                    }\n                    if (interfaceDecl.extendsList.members[i].type.construct) {\n                        if (interfaceDecl.type.construct) {\n                            interfaceDecl.type.construct.signatures = interfaceDecl.type.construct.signatures.concat(interfaceDecl.extendsList.members[i].type.construct.signatures);\n                        }\n                        else {\n                            interfaceDecl.type.construct = interfaceDecl.extendsList.members[i].type.construct;\n                        }\n                    }\n                    if (interfaceDecl.extendsList.members[i].type.index) {\n                        if (interfaceDecl.type.index) {\n                            interfaceDecl.type.index.signatures = interfaceDecl.type.index.signatures.concat(interfaceDecl.extendsList.members[i].type.index.signatures);\n                        }\n                        else {\n                            interfaceDecl.type.index = interfaceDecl.extendsList.members[i].type.index;\n                        }\n                    }\n                }\n            }\n\n            return interfaceDecl;\n        }\n\n        public typeCheckImportDecl(importDecl: ImportDeclaration) {\n            var mod: ModuleType = <ModuleType>importDecl.alias.type;\n            var sym: TypeSymbol = null;\n            var prevInImportTC = this.inImportTypeCheck;\n            this.inImportTypeCheck = true;\n\n            this.typeCheck(importDecl.alias);\n            mod = <ModuleType>importDecl.alias.type;\n\n            if (mod == null) {\n                this.checker.errorReporter.simpleError(importDecl.alias, \"Could not resolve module alias '\" + importDecl.id.actualText + \"'\");\n                mod = <ModuleType>this.checker.anyType;\n                (<TypeSymbol>importDecl.id.sym).type = mod;\n            }\n\n            importDecl.id.type = mod;\n            sym = mod.symbol;\n\n            if (!mod.isModuleType()) {\n                this.checker.errorReporter.simpleError(importDecl.alias, \"A module cannot be aliased to a non-module type\");\n            }\n            else {\n                sym.type = mod;\n                \n                // Add the imported module to the AMD dependency list\n                if (this.checker.typeFlow.currentScript && \n                    this.checker.typeFlow.currentScript.topLevelMod && \n                    this.checker.typeFlow.currentScript.topLevelMod.mod) \n                {\n                    this.checker.typeFlow.currentScript.topLevelMod.mod.importedModules.push(importDecl);\n                }\n\n                (<TypeSymbol>importDecl.id.sym).type = mod;\n\n                if (mod.symbol && mod.symbol.declAST) {\n                    (<ModuleDeclaration>mod.symbol.declAST).modFlags &= ~ModuleFlags.ShouldEmitModuleDecl;\n                }\n\n                //importDecl.id.sym = sym;\n                // REVIEW: Uncomment when you can toggle module codegen targets from the language service\n                //else if (typeFlow.checker.currentModDecl == null && \n                //            hasFlag((<ModuleDecl>sym.declAST).modFlags,ModuleFlags.IsDynamic) &&\n                //            moduleGenTarget == ModuleGenTarget.Asynchronous) \n                //{\n                //    typeFlow.checker.errorReporter.simpleError(alias, \"In AMD codegen mode, dynamic modules may not be referenced from global scope.  (Wrap the file in a module declaration.)\");\n                //}\n            }\n            this.inImportTypeCheck = prevInImportTC;\n            return importDecl;\n        }\n\n        public typeCheckModule(moduleDecl: ModuleDeclaration): ModuleDeclaration {\n\n            // In some really nasty cases of error recovery, we may not have a type\n            if (!moduleDecl.mod) {\n                return moduleDecl;\n            }\n\n            if (this.currentScript) {\n                this.currentScript.requiresGlobal = true;\n            }\n            var mod = moduleDecl.mod;\n            var sym: TypeSymbol = null;\n\n            var prevScope = this.scope;\n            var prevThisType = this.thisType;\n            var prevCurrentModDecl = this.checker.currentModDecl;\n            this.checker.currentModDecl = moduleDecl;\n\n            this.thisType = null;\n            this.scope = mod.containedScope;\n            this.typeCheck(moduleDecl.members);\n            sym = mod.symbol;\n\n            this.checker.currentModDecl = prevCurrentModDecl;\n            this.thisType = prevThisType;\n            this.scope = prevScope;\n\n            moduleDecl.type = mod;\n\n            if (sym) {\n                sym.typeCheckStatus = TypeCheckStatus.Finished;\n            }\n            return moduleDecl;\n        }\n\n        public typeCheckFor(forStmt: ForStatement): ForStatement {\n            forStmt.init = this.typeCheck(forStmt.init);\n            this.nestingLevel++;\n            forStmt.cond = this.typeCheck(forStmt.cond);\n            this.typeCheckCondExpr(forStmt.cond);\n            forStmt.incr = this.typeCheck(forStmt.incr);\n            this.nestingLevel--;\n            forStmt.body = this.typeCheck(forStmt.body);\n            this.typeCheckCompoundStmtBlock(forStmt.body, \"for statement\");\n            forStmt.type = this.voidType;\n            return forStmt;\n        }\n\n        public typeCheckWith(withStmt: WithStatement): WithStatement {\n            if (this.checker.errorsOnWith) {\n                this.checker.errorReporter.simpleError(withStmt.expr, \"All symbols within a 'with' block will be typed as 'any'\");\n            }\n            withStmt.expr = this.typeCheck(withStmt.expr);\n            this.checker.inWith = true;\n            withStmt.body = this.typeCheck(withStmt.body);\n            this.typeCheckCompoundStmtBlock(withStmt.body, \"with statement\");\n            this.checker.inWith = false;\n            return withStmt;\n        }\n\n        public typeCheckForIn(forInStmt: ForInStatement): ForInStatement {\n            forInStmt.obj = this.typeCheck(forInStmt.obj);\n            forInStmt.lval = this.cast(this.typeCheck(forInStmt.lval), this.checker.stringType);\n            if (forInStmt.lval.nodeType == NodeType.VarDecl) {\n\n                var varDecl = <VarDecl>forInStmt.lval;\n                if (varDecl.typeExpr) {\n                    this.checker.errorReporter.simpleError(varDecl, \"Variable declarations for for/in expressions may not contain a type annotation\");\n                }\n\n                if (varDecl.sym) {\n                    varDecl.sym.setType(this.checker.stringType);\n                }\n            }\n            forInStmt.body = this.typeCheck(forInStmt.body);\n            this.typeCheckCompoundStmtBlock(forInStmt.body, \"for in statement\");\n            return forInStmt;\n        }\n\n        public typeCheckWhile(whileStmt: WhileStatement): WhileStatement {\n            whileStmt.cond = this.typeCheck(whileStmt.cond);\n            this.typeCheckCondExpr(whileStmt.cond);\n            whileStmt.body = this.typeCheck(whileStmt.body);\n            this.typeCheckCompoundStmtBlock(whileStmt.body, \"while statement\");\n            whileStmt.type = this.voidType;\n            return whileStmt;\n        }\n\n        public typeCheckDoWhile(doWhileStmt: DoWhileStatement): DoWhileStatement {\n            doWhileStmt.cond = this.typeCheck(doWhileStmt.cond);\n            this.typeCheckCondExpr(doWhileStmt.cond);\n            doWhileStmt.body = this.typeCheck(doWhileStmt.body);\n            this.typeCheckCompoundStmtBlock(doWhileStmt.body, \"do while statement\");\n            doWhileStmt.type = this.voidType;\n            return doWhileStmt;\n        }\n\n        public typeCheckCondExpr(cond: AST) {\n            if (this.checker.styleSettings.assignmentInCond) {\n                if ((cond !== null) &&\n                    (cond.nodeType >= NodeType.Asg) &&\n                    (cond.nodeType <= NodeType.LastAsg)) {\n                    this.checker.errorReporter.simpleError(cond, \"top-level assignment statement in conditional expression\");\n                }\n            }\n        }\n\n        public typeCheckCompoundStmtBlock(stmts: AST, stmtType: string) {\n            if (this.checker.styleSettings.blockInCompoundStmt && stmts) {\n                if (stmts.nodeType != NodeType.Block) {\n                    this.checker.errorReporter.styleError(stmts, stmtType + \" requires a block\");\n                }\n            }\n        }\n        public typeCheckIf(ifStmt: IfStatement): IfStatement {\n            ifStmt.cond = this.typeCheck(ifStmt.cond);\n            this.typeCheckCondExpr(ifStmt.cond);\n            ifStmt.thenBod = this.typeCheck(ifStmt.thenBod);\n            ifStmt.elseBod = this.typeCheck(ifStmt.elseBod);\n            this.typeCheckCompoundStmtBlock(ifStmt.thenBod, \"if statement\");\n            this.typeCheckCompoundStmtBlock(ifStmt.elseBod, \"if statement\");\n            ifStmt.type = this.voidType;\n            return ifStmt;\n        }\n\n        public typeFromAccessorFuncDecl(funcDecl: FuncDecl) {\n            if (!funcDecl.isAccessor()) {\n                return null;\n            }\n\n            if (hasFlag(funcDecl.fncFlags, FncFlags.GetAccessor)) {\n                return funcDecl.type.call.signatures[0].returnType.type;\n            }\n            else {\n                return funcDecl.type.call.signatures[0].parameters[0].getType();\n            }\n        }\n\n        public typeCheckObjectLit(objectLit: UnaryExpression): void {\n\n            var resultType = new Type();\n            resultType.symbol = new TypeSymbol(this.checker.anon, objectLit.minChar,\n                                             objectLit.limChar - objectLit.minChar,\n                                             this.checker.locationInfo.unitIndex,\n                                             resultType);\n\n            resultType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n            resultType.memberScope = new SymbolTableScope(resultType.members, null, null, null, null);\n\n            var aggScope = new SymbolAggregateScope(resultType.symbol);\n            aggScope.addParentScope(resultType.memberScope);\n            aggScope.addParentScope(this.scope);\n            resultType.containedScope = aggScope;\n            var memberDecls = <ASTList>objectLit.operand;\n            var prevThisType = this.thisType;\n            var acceptTargetType = false;\n            var targetType: Type = null;\n\n            if (this.checker.hasTargetType()) {\n                targetType = this.checker.getTargetTypeContext().contextualType;\n\n                if (targetType && targetType.symbol && !this.checker.typeStatusIsFinished(targetType.symbol.typeCheckStatus)) {\n                    if (targetType.symbol.declAST) {\n                        this.typeCheck(targetType.symbol.declAST);\n                    }\n                }\n                acceptTargetType = true;\n            }\n\n            if (memberDecls) {\n                for (var i = 0, len = memberDecls.members.length; i < len; i++) {\n\n                    var binex = <BinaryExpression>memberDecls.members[i];\n\n                    var id = binex.operand1;\n                    var text: string;\n                    var targetMember: Symbol = null;\n                    var fieldSymbol: FieldSymbol = null;\n\n                    if (id.nodeType == NodeType.Name) {\n                        text = (<Identifier>id).text;\n                    }\n                    else if (id.nodeType == NodeType.QString) {\n                        // TODO: set text to unescaped string\n                        var idText = (<StringLiteral>id).text;\n                        text = idText.substring(1, idText.length - 1);\n                    }\n                    else {\n                        this.checker.errorReporter.simpleError(objectLit,\n                                                          \"malformed object literal\");\n                        resultType = this.anyType;\n                        break;\n                    }\n\n                    if (acceptTargetType && targetType.memberScope) {\n                        targetMember = targetType.memberScope.find(text, false, false);\n                    }\n\n                    // before typechecking an accessor function member, we need to initialize its accessor symbol\n                    if (binex.operand2.nodeType == NodeType.FuncDecl && (<FuncDecl>binex.operand2).isAccessor()) {\n\n                        var funcDecl = <FuncDecl>binex.operand2;\n                        var accessorSym: FieldSymbol = resultType.members.publicMembers.lookup(text);\n\n                        accessorSym = this.checker.createAccessorSymbol(funcDecl, accessorSym, resultType, true, false, resultType.memberScope, null);\n                        funcDecl.accessorSymbol = accessorSym;\n                        fieldSymbol = accessorSym;\n                        if (id.nodeType == NodeType.Name) {\n                            (<Identifier>id).sym = accessorSym;\n                        }\n                    }\n\n                    this.checker.typeCheckWithContextualType(acceptTargetType && targetMember ? targetMember.getType() : null, false, acceptTargetType, binex.operand2);\n\n                    if (acceptTargetType && targetMember) {\n                        // Note that we accept 'any' in place of a valid subtype                     \n                        if ((binex.operand2.type == this.anyType || this.checker.sourceIsAssignableToTarget(binex.operand2.type, targetMember.getType())) ||\n                            (binex.operand2.nodeType == NodeType.FuncDecl &&\n                            (<FuncDecl>binex.operand2).isAccessor() &&\n                                this.typeFromAccessorFuncDecl(<FuncDecl>binex.operand2) == targetMember.getType())) {\n                                    // set the field type to the proper contextual type\n                                    // this is especially important in the 'any' case, so that\n                                    // fields typed to 'any' aren't accepted for contextual typing,\n                                    // but never properly set to the target type\n                            binex.operand1.type = targetMember.getType();\n                        }\n                    }\n                    else {\n                        // here we sub in 'any' for 'undefined' to account for field initialization to\n                        // 'undefined'  \n                        binex.operand2.type = binex.operand2.type == this.checker.undefinedType ? this.anyType : binex.operand2.type;\n                    }\n\n                    // the field symbol hasn't been set by a getter or setter\n                    if (fieldSymbol == null) {\n                        var memberType = binex.operand2.type;\n                        var field = new ValueLocation();\n                        fieldSymbol =\n                            new FieldSymbol(text, id.minChar,\n                                            this.checker.locationInfo.unitIndex,\n                                            true, field);\n                        fieldSymbol.flags |= SymbolFlags.Property;\n                        field.symbol = fieldSymbol;\n                        fieldSymbol.typeCheckStatus = this.checker.getTypeCheckFinishedStatus();\n                        field.typeLink = new TypeLink();\n                        field.typeLink.type = memberType;\n                        resultType.members.publicMembers.add(text, fieldSymbol);\n                    }\n                    fieldSymbol.isObjectLitField = true;\n                }\n            }\n\n            this.thisType = prevThisType;\n            objectLit.type = resultType;\n            if (targetType) {\n                objectLit.targetType = targetType;\n            }\n        }\n\n        public typeCheckArrayLit(arrayLit: UnaryExpression): void {\n            var elements = <ASTList>arrayLit.operand;\n            var elementType = this.anyType;\n            var targetElementType: Type = null;\n            var comparisonInfo = new TypeComparisonInfo();\n            comparisonInfo.onlyCaptureFirstError = true;\n\n            // if the target type is an array type, extract the element type\n            if (this.checker.hasTargetType()) {\n                var targetType = this.checker.getTargetTypeContext().contextualType;\n                if (targetType.elementType) {\n                    targetElementType = targetType.elementType;\n                }\n            }\n\n            if (elements) {\n\n                var prevInArrayElemTypeCheck = this.inArrayElementTypeCheck;\n\n                this.inArrayElementTypeCheck = true;\n                this.checker.typeCheckWithContextualType(targetElementType, this.checker.inProvisionalTypecheckMode(), targetElementType != null, elements);\n                this.inArrayElementTypeCheck = prevInArrayElemTypeCheck;\n\n                elementType = elements.members[0].type;\n\n                var collection: ITypeCollection = {\n                    getLength: () => { return elements.members.length; },\n                    setTypeAtIndex: (index: number, type: Type) => { elements.members[index].type = type; },\n                    getTypeAtIndex: (index: number) => { return elements.members[index].type; }\n                }\n\n                elementType = this.checker.findBestCommonType(elementType, targetElementType, collection, false, comparisonInfo);\n\n                // if the array type is the undefined type, we should widen it to any\n                // if it's of the null type, only widen it if it's not in a nested array element, so as not to \n                // short-circuit any checks for the best common type\n                if (elementType == this.checker.undefinedType || (!prevInArrayElemTypeCheck && elementType == this.nullType)) {\n                    elementType = this.anyType;\n                }\n            }\n            if (!elementType) {\n                var emsg = \"Incompatible types in array literal expression\";\n                if (!comparisonInfo.message) {\n                    this.checker.errorReporter.simpleError(arrayLit, emsg);\n                }\n                else {\n                    this.checker.errorReporter.simpleError(arrayLit, emsg + \": \" + comparisonInfo.message);\n                }\n                elementType = this.anyType;\n            }\n            else if (targetElementType) {\n                // for the case of zero-length 'any' arrays, we still want to set the contextual type, if\n                // need be\n                if (this.checker.sourceIsAssignableToTarget(elementType, targetElementType)) {\n                    elementType = targetElementType;\n                }\n            }\n\n            arrayLit.type = this.checker.makeArrayType(elementType);\n\n        }\n\n        public checkForVoidConstructor(type: Type, ast: AST) {\n            if (type &&\n                type.construct &&\n                type.construct.signatures.length > 0) {\n\n                for (var i = 0; i < type.construct.signatures.length; i++) {\n                    if (type.construct.signatures[i].returnType.type == this.checker.voidType) {\n                        this.checker.errorReporter.simpleError(ast, \"Constructors may not have a return type of 'void'\");\n                        break;\n                    }\n                }\n            }\n        }\n\n        // REVIEW: the code below could set the signature type of the function to the current return\n        // type, which would have a benefit of reducing the risk of a recursive typecheck scenario, but is\n        // is technically wrong - mergeOrdered will only work properly if the best common supertype\n        // comes before any sibling types.  This would mean that if a function, \"color()\", returned\n        // three types (in order) - \"Red\", \"Blue\", and \"IColor\", an \"Incompatible return type\" error \n        // would be triggered.  However, if \"color()\" returned (in order) \"Red\", \"IColor\" and \"Blue\"\n        // no error would be triggered, and the return type of the function would be \"IColor\"\n        public typeCheckReturn(returnStmt: ReturnStatement): ReturnStatement {\n\n            if (this.thisFnc) {\n                var targetType: Type = null;\n\n                // determine the target type\n                if (this.checker.hasTargetType()) {\n                    var tcContext = this.checker.getTargetTypeContext();\n                    var accessorType = tcContext.targetAccessorType;\n\n                    if (accessorType) {\n                        targetType = accessorType;\n                    }\n                    else {\n                        var targetSig = this.checker.getTargetTypeContext().targetSig;\n                        if (targetSig && targetSig.returnType.type != this.voidType) {\n                            targetType = targetSig.returnType.type;\n                        }\n                    }\n                }\n\n                if (returnStmt.returnExpression) {\n                    this.thisFnc.fncFlags |= FncFlags.HasReturnExpression;\n\n                    if (targetType == null && this.thisFnc.returnTypeAnnotation && this.thisFnc.returnTypeAnnotation.type && this.thisFnc.returnTypeAnnotation.type != this.voidType) {\n                        targetType = this.thisFnc.returnTypeAnnotation.type;\n                    }\n\n                    this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), targetType != null, returnStmt.returnExpression);\n\n                    var expectedReturnType: Type =\n                        (this.thisFnc.returnTypeAnnotation && this.thisFnc.returnTypeAnnotation.type) ?\n                            this.thisFnc.returnTypeAnnotation.type :\n                            targetType;\n                    if (expectedReturnType) {\n                        if (expectedReturnType == this.voidType && returnStmt.returnExpression.type != this.voidType) {\n                            this.checker.errorReporter.simpleError(returnStmt,\n                                                              \"Return with value expression in void function\");\n\n                            // even though we've raised an error, use the more specific type\n                            returnStmt.type = returnStmt.returnExpression.type;\n                        }\n                        else {\n                            returnStmt.returnExpression = this.cast(returnStmt.returnExpression, expectedReturnType);\n                            returnStmt.type = expectedReturnType;\n                        }\n                    }\n                    else {\n                        if (targetType) {\n                            if (returnStmt.returnExpression.type != this.voidType) {\n                                returnStmt.returnExpression = this.cast(returnStmt.returnExpression, targetType);\n                            }\n                            else {\n                                returnStmt.returnExpression.type = targetType;\n                            }\n                        }\n                        returnStmt.type = returnStmt.returnExpression.type;\n                    }\n                    this.thisFnc.returnStatementsWithExpressions[this.thisFnc.returnStatementsWithExpressions.length] = returnStmt;\n                }\n                else {\n                    returnStmt.type = targetType == null ? this.checker.voidType : targetType; //((this.thisFnc.returnTypeAnnotation && this.thisFnc.returnTypeAnnotation.type) ? this.thisFnc.returnTypeAnnotation.type : this.checker.voidType) : targetType;\n                }\n            }\n\n            return returnStmt;\n        }\n\n        public typeCheckInstOf(ast: AST): AST {\n            var binex = <BinaryExpression>ast;\n            binex.operand1 = this.typeCheck(binex.operand1);\n            binex.operand2 = this.typeCheck(binex.operand2);\n\n            if (!((binex.operand1.type == this.checker.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand1.type, this.objectInterfaceType)) &&\n                    (binex.operand2.type == this.anyType || this.checker.sourceIsSubtypeOfTarget(binex.operand2.type, this.functionInterfaceType)))) {\n                this.checker.errorReporter.simpleError(ast, \"The instanceof operator requires the left operand to be of type Any or an object type, and the right operand to be of type Any or a subtype of the Function interface type\");\n            }\n            binex.type = this.booleanType;\n            return binex;\n        }\n\n        public typeCheckCommaOperator(ast: AST): AST {\n            var binex = <BinaryExpression>ast;\n            binex.operand1 = this.typeCheck(binex.operand1);\n            binex.operand2 = this.typeCheck(binex.operand2);\n            binex.type = binex.operand2.type;\n            return binex;\n        }\n\n        public typeCheckLogOr(binex: BinaryExpression): BinaryExpression {\n            binex.operand1 = this.typeCheck(binex.operand1);\n            binex.operand2 = this.typeCheck(binex.operand2);\n            var leftType = binex.operand1.type;\n            var rightType = binex.operand2.type;\n\n            if (leftType == this.checker.anyType || rightType == this.checker.anyType) {\n                binex.type = this.checker.anyType;\n            }\n            else if (leftType == this.checker.booleanType) {\n                if (rightType == this.checker.booleanType) {\n                    binex.type = this.checker.booleanType;\n                }\n                else {\n                    binex.type = this.checker.anyType;\n                }\n            }\n            else if (leftType == this.checker.numberType) {\n                if (rightType == this.checker.numberType) {\n                    binex.type = this.checker.numberType;\n                }\n                else {\n                    binex.type = this.checker.anyType;\n                }\n            }\n            else if (leftType == this.checker.stringType) {\n                if (rightType == this.checker.stringType) {\n                    binex.type = this.checker.stringType;\n                }\n                else {\n                    binex.type = this.checker.anyType;\n                }\n            }\n            else {\n                if (this.checker.sourceIsSubtypeOfTarget(leftType, rightType)) {\n                    binex.type = rightType;\n                }\n                else if (this.checker.sourceIsSubtypeOfTarget(rightType, leftType)) {\n                    binex.type = leftType;\n                }\n                else {\n                    binex.type = this.checker.anyType;\n                }\n            }\n            return binex;\n        }\n\n        public typeCheckLogAnd(binex: BinaryExpression): BinaryExpression {\n            binex.operand1 = this.typeCheck(binex.operand1);\n            binex.operand2 = this.typeCheck(binex.operand2);\n            binex.type = binex.operand2.type;\n            return binex;\n        }\n\n        public tryAddCandidates(signature: Signature, actuals: Type[], exactCandidates: Signature[], conversionCandidates: Signature[], comparisonInfo: TypeComparisonInfo): void {\n            var lowerBound = signature.nonOptionalParameterCount; // required parameters\n            var upperBound = signature.parameters.length; // required and optional parameters\n            var formalLen = lowerBound;\n            var acceptable = false;\n\n            if ((actuals.length >= lowerBound) && (signature.hasVariableArgList || actuals.length <= upperBound)) {\n                formalLen = (signature.hasVariableArgList ? signature.parameters.length : actuals.length);\n                acceptable = true;\n            }\n\n            var repeatType: Type = null;\n\n            if (acceptable || signature.hasVariableArgList) {\n                // assumed structure here is checked when signature is formed\n                if (signature.hasVariableArgList) {\n                    formalLen -= 1;\n                    repeatType = (<ParameterSymbol>signature.parameters[formalLen]).parameter.typeLink.type;\n                    repeatType = repeatType.elementType;\n                    acceptable = actuals.length >= formalLen;\n                }\n                var len = actuals.length;\n\n                var exact = acceptable;\n                var convert = acceptable;\n                for (var i = 0; i < len; i++) {\n                    var typeA: Type;\n                    if (i < formalLen) {\n                        typeA =\n                            (<ParameterSymbol>signature.parameters[i]).parameter.typeLink.type;\n                    }\n                    else {\n                        typeA = repeatType;\n                    }\n\n                    var typeB = actuals[i];\n                    if (!typeA || !typeB || !(this.checker.typesAreIdentical(typeA, typeB))) {\n                        exact = false;\n                    }\n                    // is the argument assignable to the parameter?\n                    if (!this.checker.sourceIsAssignableToTarget(typeB, typeA, comparisonInfo)) {\n                        convert = false;\n                    }\n                    if (!(exact || convert)) {\n                        break;\n                    }\n                }\n                if (exact) {\n                    exactCandidates[exactCandidates.length] = signature;\n                }\n                else if (convert && (exactCandidates.length == 0)) {\n                    conversionCandidates[conversionCandidates.length] = signature;\n                }\n\n            }\n        }\n\n        public resolveOverload(application: AST, group: SignatureGroup): Signature {\n            var rd = this.resolutionDataCache.getResolutionData();\n            var actuals = rd.actuals;\n            var exactCandidates = rd.exactCandidates;\n            var conversionCandidates = rd.conversionCandidates;\n            var candidate: Signature = null;\n            var hasOverloads = group.signatures.length > 1;\n            var comparisonInfo = new TypeComparisonInfo();\n            var args: ASTList = null;\n            var target: AST = null;\n\n            if (application.nodeType == NodeType.Call || application.nodeType == NodeType.New) {\n                var callEx = <CallExpression>application;\n                args = callEx.arguments;\n                target = callEx.target;\n                if (callEx.arguments) {\n                    var len = callEx.arguments.members.length;\n                    for (var i = 0; i < len; i++) {\n                        actuals[i] = callEx.arguments.members[i].type;\n                    }\n                }\n            }\n            else if (application.nodeType == NodeType.Index) {\n                var binExp = <BinaryExpression>application;\n                target = binExp.operand1;\n                args = new ASTList();\n                args.members[0] = binExp.operand2;\n                actuals[0] = binExp.operand2.type;\n            }\n\n            for (var j = 0, groupLen = group.signatures.length; j < groupLen; j++) {\n                var signature = group.signatures[j];\n                if (hasOverloads && signature == group.definitionSignature && !this.checker.canCallDefinitionSignature) {\n                    continue;\n                }\n                if (!signature.returnType.type && signature.declAST &&\n                    (signature.typeCheckStatus != TypeCheckStatus.Finished)) {\n                    this.typeCheckFunction(signature.declAST);\n                }\n                this.tryAddCandidates(signature, actuals, exactCandidates, conversionCandidates, comparisonInfo);\n            }\n            if (exactCandidates.length == 0) {\n\n                var applicableCandidates = this.checker.getApplicableSignatures(conversionCandidates, args, comparisonInfo);\n                if (applicableCandidates.length > 0) {\n                    var candidateInfo = this.checker.findMostApplicableSignature(applicableCandidates, args);\n                    if (candidateInfo.ambiguous) {\n                        this.checker.errorReporter.simpleError(target, \"Ambiguous call expression - could not choose overload\");\n                    }\n                    candidate = candidateInfo.sig;\n                }\n                else {\n                    var emsg = \"Supplied parameters do not match any signature of call target\";\n                    if (comparisonInfo.message) {\n                        this.checker.errorReporter.simpleError(target, emsg + \":\\n\\t\" + comparisonInfo.message);\n                    }\n                    else {\n                        this.checker.errorReporter.simpleError(target, emsg);\n                    }\n                }\n            }\n            else {\n                if (exactCandidates.length > 1) {\n                    var applicableSigs: ApplicableSignature[] = [];\n                    for (var i = 0; i < exactCandidates.length; i++) {\n                        applicableSigs[i] = { signature: exactCandidates[i], hadProvisionalErrors: false };\n                    }\n                    var candidateInfo = this.checker.findMostApplicableSignature(applicableSigs, args);\n                    if (candidateInfo.ambiguous) {\n                        this.checker.errorReporter.simpleError(target, \"Ambiguous call expression - could not choose overload\");\n                    }\n                    candidate = candidateInfo.sig;\n                }\n                else {\n                    candidate = exactCandidates[0];\n                }\n            }\n\n            this.resolutionDataCache.returnResolutionData(rd);\n            return candidate;\n        }\n\n        public typeCheckNew(ast: AST): AST {\n            var callEx = <CallExpression>ast;\n\n            callEx.target = this.typeCheck(callEx.target);\n            var target = callEx.target;\n            if (target.type.construct || target.type.call) {\n                this.preTypeCheckCallArgs(callEx.arguments);\n            }\n            else {\n                callEx.arguments = <ASTList>this.typeCheck(callEx.arguments);\n            }\n\n            if (target.type == this.anyType) {\n                callEx.type = this.anyType;\n                callEx.arguments = <ASTList>this.typeCheck(callEx.arguments);\n            }\n            else {\n                if (target.type.construct) {\n                    var signature = this.resolveOverload(callEx, target.type.construct);\n                    if (signature == null) {\n                        callEx.type = this.anyType;\n                    }\n                    else if (signature.returnType.type == this.voidType) {\n                        callEx.type = this.anyType;\n                        callEx.signature = signature;\n                    }\n                    else {\n                        callEx.type = signature.returnType.type;\n                        callEx.signature = signature;\n                    }\n                }\n                else if (target.type.call) {\n                    var signature = this.resolveOverload(callEx, target.type.call);\n                    if (signature == null) {\n                        callEx.type = this.anyType;\n                    }\n                    else if ((signature.returnType.type == this.voidType) || (signature.returnType.type == this.anyType)) {\n                        callEx.type = this.anyType;\n                        callEx.signature = signature;\n                    }\n                    else {\n                        this.checker.errorReporter.simpleError(callEx.target,\n                           \"new expression only valid on constructors\");\n                    }\n                }\n                else if (target.type.elementType) {\n                    callEx.type = target.type;\n                }\n                else {\n                    this.checker.errorReporter.invalidCall(callEx, callEx.nodeType, this.scope);\n                    callEx.type = this.anyType;\n                }\n            }\n\n            this.postTypeCheckCallArgs(callEx);\n\n            return callEx;\n        }\n\n        // Typecheck all args that cannot be affected by contextual typing of overloads\n        public preTypeCheckCallArgs(args: ASTList) {\n\n            if (!args) {\n                return;\n            }\n\n            for (var i = 0; i < args.members.length; i++) {\n                switch (args.members[i].nodeType) {\n                    case NodeType.FuncDecl:\n                    case NodeType.ObjectLit:\n                    case NodeType.ArrayLit:\n                        continue;\n                    default:\n                        this.typeCheck(args.members[i]);\n                        break;\n                }\n            }\n        }\n\n        public postTypeCheckCallArgs(callEx: CallExpression) {\n\n            var acceptedTargetType = false;\n            var i = 0;\n\n            if (callEx.target &&\n                callEx.target.type &&\n                callEx.signature &&\n                callEx.arguments) {\n                var sig = callEx.signature;\n\n                if (sig && callEx.arguments.members.length >= sig.nonOptionalParameterCount) {\n                    acceptedTargetType = true;\n                    var targetType: Type = null;\n                    var nonVarArgFormalParamLength = sig.hasVariableArgList ? sig.parameters.length - 1 : sig.parameters.length;\n                    var nonVarArgActualParamLength = callEx.arguments.members.length < nonVarArgFormalParamLength ? callEx.arguments.members.length : nonVarArgFormalParamLength\n\n                    for (i = 0; i < nonVarArgActualParamLength; i++) {\n                        targetType = sig.parameters[i].getType();\n                        switch (callEx.arguments.members[i].nodeType) {\n                            case NodeType.FuncDecl:\n                            case NodeType.ObjectLit:\n                            case NodeType.ArrayLit:\n                                this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), !sig.parameters[i].declAST.isParenthesized, callEx.arguments.members[i]);\n                                break;\n                        }\n                    }\n\n                    if (sig.hasVariableArgList) {\n                        var varArgParamIndex = sig.nonOptionalParameterCount - 1;\n                        targetType = sig.parameters[varArgParamIndex].getType();\n                        if (targetType) {\n                            targetType = targetType.elementType;\n                        }\n                        var isParenthesized = !sig.parameters[varArgParamIndex].declAST.isParenthesized;\n                        for (i = nonVarArgActualParamLength; i < callEx.arguments.members.length; i++) {\n                            switch (callEx.arguments.members[i].nodeType) {\n                                case NodeType.FuncDecl:\n                                case NodeType.ObjectLit:\n                                case NodeType.ArrayLit:\n                                    this.checker.typeCheckWithContextualType(targetType, this.checker.inProvisionalTypecheckMode(), isParenthesized, callEx.arguments.members[i]);\n                                    break;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (!acceptedTargetType && callEx.arguments) {\n                this.checker.killCurrentContextualType();\n\n                for (i = 0; i < callEx.arguments.members.length; i++) {\n                    switch (callEx.arguments.members[i].nodeType) {\n                        case NodeType.FuncDecl:\n                        case NodeType.ObjectLit:\n                        case NodeType.ArrayLit:\n                            this.typeCheck(callEx.arguments.members[i]);\n                            break;\n                        default:\n                            continue;\n                    }\n                }\n            }\n        }\n\n        public typeCheckCall(ast: AST): AST {\n            var callEx = <CallExpression>ast;\n            if (this.checker.styleSettings.newMustBeUsed && (ast.nodeType == NodeType.New)) {\n                if (hasFlag(ast.flags, ASTFlags.IsStatement)) {\n                    this.checker.errorReporter.styleError(ast, \"use of new expression as a statement\");\n                }\n            }\n            else if ((!this.checker.styleSettings.evalOK) && (ast.nodeType == NodeType.Call)) {\n                if ((callEx.target.nodeType == NodeType.Name) && ((<Identifier>callEx.target).text == \"eval\")) {\n                    this.checker.errorReporter.styleError(callEx, \"eval not permitted\");\n                }\n            }\n\n            if (callEx.target.nodeType == NodeType.FuncDecl) {\n                (<FuncDecl>callEx.target).isInlineCallLiteral = true;\n            }\n\n            var prevInSuperCall = this.inSuperCall;\n\n            if (callEx.target.nodeType == NodeType.Super) {\n                this.inSuperCall = true;\n            }\n\n            callEx.target = this.typeCheck(callEx.target);\n            this.preTypeCheckCallArgs(callEx.arguments);\n\n            var target = callEx.target;\n\n            if ((target.type == null) || (target.type == this.anyType) || (this.functionInterfaceType && target.type == this.functionInterfaceType)) {\n                callEx.type = this.anyType;\n            }\n            else {\n                var fnType = target.type;\n                if (fnType.call) {\n                    var signature = this.resolveOverload(callEx, fnType.call);\n                    if (signature == null) {\n                        callEx.type = this.anyType;\n                    }\n                    else {\n                        callEx.type = signature.returnType.type;\n                        callEx.signature = signature;\n                    }\n                }\n                else {\n                    // track calls to class base class\n                    if (callEx.target.nodeType == NodeType.Super &&\n                        this.thisFnc &&\n                        this.thisFnc.isConstructor &&\n                        hasFlag(this.thisFnc.fncFlags, FncFlags.ClassMethod)) {\n\n                            // Need to use the class type for the construct signature, not the instance type\n                        var signature = fnType.symbol.type.construct ? this.resolveOverload(callEx, fnType.symbol.type.construct) : null;\n\n                        if (signature == null) {\n                            callEx.type = this.anyType;\n                        }\n                        else {\n                            callEx.flags |= ASTFlags.ClassBaseConstructorCall;\n                            callEx.type = signature.returnType.type;\n                            callEx.signature = signature;\n                        }\n                    }\n                    else {\n                        callEx.type = this.anyType;\n                        this.checker.errorReporter.invalidCall(callEx, callEx.nodeType, this.scope);\n                    }\n                }\n            }\n            this.postTypeCheckCallArgs(callEx);\n\n            this.inSuperCall = prevInSuperCall;\n\n            return callEx;\n        }\n\n        public assignScopes(ast: AST) {\n            var script = <Script>ast;\n            this.checker.locationInfo = script.locationInfo;\n            var globalChain = new ScopeChain(this.checker.gloMod, null, this.globalScope);\n            var context = new AssignScopeContext(globalChain, this, [this.checker.currentModDecl]);\n            getAstWalkerFactory().walk(ast, preAssignScopes, postAssignScopes, null, context);\n        }\n\n        public findMemberScope(enclosingScopeContext: EnclosingScopeContext, matchFlag: ASTFlags) {\n            var enclosingScope = enclosingScopeContext.getScope();\n            var pos = enclosingScopeContext.pos - enclosingScopeContext.getScriptFragmentPosition();\n            var scriptFragment = enclosingScopeContext.getScriptFragment();\n\n            var memContext = new MemberScopeContext(this, pos, matchFlag);\n            memContext.scope = enclosingScope;\n            if (scriptFragment.nodeType == NodeType.Name) {\n                return scriptFragment.type.getMemberScope(this);\n            }\n            else {\n                getAstWalkerFactory().walk(scriptFragment, preFindMemberScope, null, null, memContext);\n                if (memContext.ast && enclosingScopeContext.enclosingClassDecl && memContext.ast.type == enclosingScopeContext.enclosingClassDecl.type.instanceType) {\n                    enclosingScopeContext.publicsOnly = false;\n                }\n                if (memContext.type) {\n                    return memContext.type.getMemberScope(this);\n                }\n                else {\n                    return null;\n                }\n            }\n        }\n\n        public findMemberScopeAt(enclosingScopeContext: EnclosingScopeContext) {\n            return this.findMemberScope(enclosingScopeContext, ASTFlags.DotLHS);\n        }\n\n        public findMemberScopeAtFullAst(enclosingScopeContext: EnclosingScopeContext) {\n            var matchFlag = ASTFlags.DotLHS;\n            var pos = enclosingScopeContext.pos;\n            var astResult: AST = null;\n\n            var preFindMemberScopeFullAst = function (ast: AST, parent: AST, walker: IAstWalker) {\n                if (isValidAstNode(ast)) {\n                    // Note: pos == ast.limChar       in case of incomplete code (e.g. \"foo.\")\n                    // Note: (pos - 1) == ast.limChar in case of complete code (e.g. \"foo.bar\")\n                    if (hasFlag(ast.flags, matchFlag) && (pos == ast.limChar || (pos - 1) == ast.limChar)) {\n                        astResult = ast;\n                        walker.options.stopWalk();\n                    }\n\n                    // Stop traversal if range does not contain position\n                    walker.options.goChildren = (ast.minChar <= pos) && (pos <= ast.limChar);\n                }\n                return ast;\n            }\n\n            var preFindMemberScopeFullAstFuzy = function (ast: AST, parent: AST, walker: IAstWalker) {\n                if (isValidAstNode(ast)) {\n                    if (hasFlag(ast.flags, matchFlag) && ((ast.minChar < pos) && (pos <= ast.limChar))) {\n                        astResult = ast;\n                    }\n\n                    // Stop traversal if range does not contain position\n                    walker.options.goChildren = (ast.minChar <= pos) && (pos <= ast.limChar);\n                }\n                return ast;\n            }\n\n            getAstWalkerFactory().walk(enclosingScopeContext.script, preFindMemberScopeFullAst);\n\n            if (astResult == null) {\n                // Perform a more \"fusy\" match. This is because the limChar of AST nodes is sometimes\n                // not what we expect, for example:\n                //   foo./*comment*/;\n                // In this case, limChar points to \";\" instead of \".\" (because of the trailing comment).\n                getAstWalkerFactory().walk(enclosingScopeContext.script, preFindMemberScopeFullAstFuzy);\n            }\n\n            if (astResult &&\n                enclosingScopeContext.enclosingClassDecl &&\n                astResult.type == enclosingScopeContext.enclosingClassDecl.type.instanceType) {\n                enclosingScopeContext.publicsOnly = false;\n            }\n\n            if (astResult && astResult.type) {\n                return astResult.type.getMemberScope(this);\n            }\n            else {\n                return null;\n            }\n        }\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='diagnostics.ts' />\n///<reference path='flags.ts' />\n///<reference path='nodeTypes.ts' />\n///<reference path='hashTable.ts' />\n///<reference path='ast.ts' />\n///<reference path='astWalker.ts' />\n///<reference path='astWalkerCallback.ts' />\n///<reference path='astPath.ts' />\n///<reference path='astLogger.ts' />\n///<reference path='binder.ts' />\n///<reference path='base64.ts' />\n///<reference path='sourceMapping.ts' />\n///<reference path='emitter.ts' />\n///<reference path='errorReporter.ts' />\n///<reference path='parser.ts' />\n///<reference path='printContext.ts' />\n///<reference path='scanner.ts' />\n///<reference path='scopeAssignment.ts' />\n///<reference path='scopeWalk.ts' />\n///<reference path='signatures.ts' />\n///<reference path='symbols.ts' />\n///<reference path='symbolScope.ts' />\n///<reference path='tokens.ts' />\n///<reference path='typeChecker.ts' />\n///<reference path='typeCollection.ts' />\n///<reference path='typeFlow.ts' />\n///<reference path='types.ts' />\n///<reference path='pathUtils.ts' />\n///<reference path='referenceResolution.ts' />\n///<reference path='precompile.ts' />\n///<reference path='incrementalParser.ts' />\n///<reference path='declarationEmitter.ts' />\n\nmodule TypeScript {\n\n    export enum UpdateUnitKind {\n        Unknown,\n        NoEdits,\n        EditsInsideSingleScope,\n    }\n\n    export class ScriptEditRange {\n        constructor (public minChar: number,\n                     public limChar: number,\n                     public delta: number) { }\n\n        static unknown(): ScriptEditRange {\n            return new ScriptEditRange(-1, -1, -1);\n        }\n\n        public isUnknown() {\n            return this.minChar === -1 && this.limChar === -1 && this.delta === -1;\n        }\n\n        public containsPosition(pos: number) {\n            return (this.minChar <= pos && pos < this.limChar)\n                || (this.minChar <= pos && pos < this.limChar + this.delta);\n        }\n\n        public toString(): string {\n            return \"editRange(minChar=\" + this.minChar + \", limChar=\" + this.limChar + \", delta=\" + this.delta + \")\";\n        }\n    }\n\n    export class UpdateUnitResult {\n\n        constructor (public kind: UpdateUnitKind, public unitIndex: number, public script1: Script, public script2: Script) { }\n\n        public scope1: AST = null;\n        public scope2: AST = null;\n        public editRange: ScriptEditRange = null;\n        public parseErrors: ErrorEntry[] = [];\n\n        static noEdits(unitIndex: number) {\n            return new UpdateUnitResult(UpdateUnitKind.NoEdits, unitIndex, null, null);\n        }\n\n        static unknownEdits(script1: Script, script2: Script, parseErrors: ErrorEntry[]) {\n            var result = new UpdateUnitResult(UpdateUnitKind.Unknown, script1.locationInfo.unitIndex, script1, script2);\n            result.parseErrors = parseErrors;\n            return result;\n        }\n\n        static singleScopeEdits(script1: Script, script2: Script, scope1: AST, scope2: AST, editRange: ScriptEditRange, parseErrors: ErrorEntry[]) {\n            var result = new UpdateUnitResult(UpdateUnitKind.EditsInsideSingleScope, script1.locationInfo.unitIndex, script1, script2);\n            result.scope1 = scope1;\n            result.scope2 = scope2;\n            result.editRange = editRange;\n            result.parseErrors = parseErrors;\n            return result;\n        }\n    }\n\n    export class ErrorEntry {\n        constructor (public unitIndex: number,\n                    public minChar: number,\n                    public limChar: number,\n                    public message: string) { }\n    }\n\n    export var defaultSettings = new CompilationSettings();\n\n    export interface EmitterIOHost {\n        // function that can even create a folder structure if needed\n        createFile(path: string, useUTF8?: bool): ITextWriter;\n\n        // function to check if file exists on the disk\n        fileExists(path: string): bool;\n\n        // Function to check if the directory exists on the disk\n        directoryExists(path: string): bool;\n\n        // Resolves the path\n        resolvePath(path: string): string;\n    }\n\n    export class TypeScriptCompiler {\n        public parser = new Parser();\n        public typeChecker: TypeChecker;\n        public typeFlow: TypeFlow = null;\n        public scripts = new ASTList();\n        public units: LocationInfo[] = new LocationInfo[];\n        public errorReporter: ErrorReporter;\n\n        public persistentTypeState: PersistentGlobalTypeState;\n\n\n        public emitSettings: EmitOptions;\n\n        constructor (public errorOutput: ITextWriter, public logger: ILogger = new NullLogger(), public settings: CompilationSettings = defaultSettings) {\n            this.errorReporter = new ErrorReporter(this.errorOutput);\n            this.persistentTypeState = new PersistentGlobalTypeState(this.errorReporter);\n            this.errorReporter.parser = this.parser;\n            this.initTypeChecker(this.errorOutput);\n\n            this.parser.style_requireSemi = this.settings.styleSettings.requireSemi;\n            this.parser.style_funcInLoop = this.settings.styleSettings.funcInLoop;\n            this.parser.inferPropertiesFromThisAssignment = this.settings.inferPropertiesFromThisAssignment;\n            this.emitSettings = new EmitOptions(this.settings);\n            codeGenTarget = settings.codeGenTarget;\n        }\n\n        public timeFunction(funcDescription: string, func: () => any): any {\n            return TypeScript.timeFunction(this.logger, funcDescription, func);\n        }\n\n        public initTypeChecker(errorOutput: ITextWriter) {\n            // The initial \"refresh\" initializes the persistent type state\n            this.persistentTypeState.refreshPersistentState();\n            this.typeChecker = new TypeChecker(this.persistentTypeState);\n            this.typeChecker.errorReporter = this.errorReporter;\n\n            // REVIEW: These properties should be moved out of the typeCheck object\n            // ideally, CF should be a separate pass, independent of control flow\n            this.typeChecker.checkControlFlow = this.settings.controlFlow;\n            this.typeChecker.checkControlFlowUseDef = this.settings.controlFlowUseDef;\n            this.typeChecker.printControlFlowGraph = this.settings.printControlFlow;\n\n            this.typeChecker.errorsOnWith = this.settings.errorOnWith;\n            this.typeChecker.styleSettings = this.settings.styleSettings;\n            this.typeChecker.canCallDefinitionSignature = this.settings.canCallDefinitionSignature;\n\n            this.errorReporter.checker = this.typeChecker;\n            this.setErrorOutput(this.errorOutput);\n        }\n\n        public setErrorOutput(outerr) {\n            this.errorOutput = outerr;\n            this.errorReporter.setErrOut(outerr);\n            this.parser.outfile = outerr;\n        }\n\n        public emitCommentsToOutput() {\n            this.emitSettings = new EmitOptions(this.settings);\n        }\n\n        public setErrorCallback(fn: (minChar: number, charLen: number, message: string,\n            unitIndex: number) =>void ) {\n            this.parser.errorCallback = fn;\n        }\n\n        public updateUnit(prog: string, filename: string, setRecovery: bool) {\n            return this.updateSourceUnit(new StringSourceText(prog), filename, setRecovery);\n        }\n\n        public updateSourceUnit(sourceText: ISourceText, filename: string, setRecovery: bool): bool {\n            return this.timeFunction(\"updateSourceUnit(\" + filename + \")\", () => {\n                var updateResult = this.partialUpdateUnit(sourceText, filename, setRecovery);\n                return this.applyUpdateResult(updateResult);\n            });\n        }\n\n        // Apply changes to compiler state.\n        // Return \"false\" if the change is empty and nothing was updated.\n        public applyUpdateResult(updateResult: UpdateUnitResult): bool {\n            switch (updateResult.kind) {\n                case UpdateUnitKind.NoEdits:\n                    return false;\n\n                case UpdateUnitKind.Unknown:\n                    this.scripts.members[updateResult.unitIndex] = updateResult.script2;\n                    this.units[updateResult.unitIndex] = updateResult.script2.locationInfo;\n                    for (var i = 0, len = updateResult.parseErrors.length; i < len; i++) {\n                        var e = updateResult.parseErrors[i];\n                        if (this.parser.errorCallback) {\n                            this.parser.errorCallback(e.minChar, e.limChar - e.minChar, e.message, e.unitIndex);\n                        }\n                    }\n                    return true;\n\n                case UpdateUnitKind.EditsInsideSingleScope:\n                    new IncrementalParser(this.logger).mergeTrees(updateResult);\n                    return true;\n            }\n        }\n\n        public partialUpdateUnit(sourceText: ISourceText, filename: string, setRecovery: bool): UpdateUnitResult {\n            return this.timeFunction(\"partialUpdateUnit(\" + filename + \")\", () => {\n                for (var i = 0, len = this.units.length; i < len; i++) {\n                    if (this.units[i].filename == filename) {\n                        if ((<Script>this.scripts.members[i]).isResident) {\n                            return UpdateUnitResult.noEdits(i);\n                        }\n\n                        if (setRecovery) {\n                            this.parser.setErrorRecovery(null);\n                        }\n\n                        var updateResult: UpdateUnitResult;\n\n                        // Capture parsing errors so that they are part of \"updateResult\"\n                        var parseErrors: ErrorEntry[] = [];\n                        var errorCapture = (minChar: number, charLen: number, message: string, unitIndex: number): void => {\n                            parseErrors.push(new ErrorEntry(unitIndex, minChar, minChar + charLen, message));\n                        };\n                        var svErrorCallback = this.parser.errorCallback;\n                        if (svErrorCallback)\n                            this.parser.errorCallback = errorCapture;\n\n                        var oldScript = <Script>this.scripts.members[i];\n                        var newScript = this.parser.parse(sourceText, filename, i);\n\n                        if (svErrorCallback)\n                            this.parser.errorCallback = svErrorCallback;\n\n                        updateResult = UpdateUnitResult.unknownEdits(oldScript, newScript, parseErrors);\n\n                        return updateResult;\n                    }\n                }\n                throw new Error(\"Unknown file \\\"\" + filename + \"\\\"\");\n            });\n        }\n\n        public addUnit(prog: string, filename: string, keepResident? = false, referencedFiles?: IFileReference[] = []): Script {\n            return this.addSourceUnit(new StringSourceText(prog), filename, keepResident, referencedFiles);\n        }\n\n        public addSourceUnit(sourceText: ISourceText, filename: string, keepResident:bool, referencedFiles?: IFileReference[] = []): Script {\n            return this.timeFunction(\"addSourceUnit(\" + filename + \", \" + keepResident + \")\", () => {\n                var script: Script = this.parser.parse(sourceText, filename, this.units.length, AllowedElements.Global);\n                script.referencedFiles = referencedFiles;\n                script.isResident = keepResident;\n                this.persistentTypeState.setCollectionMode(keepResident ? TypeCheckCollectionMode.Resident : TypeCheckCollectionMode.Transient);\n                var index = this.units.length;\n                this.units[index] = script.locationInfo;\n                this.typeChecker.collectTypes(script);\n                this.scripts.append(script);\n                return script\n            });\n        }\n\n        public parseUnit(prog: string, filename: string) {\n            return this.parseSourceUnit(new StringSourceText(prog), filename);\n        }\n\n        public parseSourceUnit(sourceText: ISourceText, filename: string) {\n            this.parser.setErrorRecovery(this.errorOutput);\n            var script: Script = this.parser.parse(sourceText, filename, 0);\n\n            var index = this.units.length;\n            this.units[index] = script.locationInfo;\n            this.typeChecker.collectTypes(script);\n            this.scripts.append(script);\n        }\n\n        public typeCheck() {\n            return this.timeFunction(\"typeCheck()\", () => {\n                var binder = new Binder(this.typeChecker);\n                this.typeChecker.units = this.units;\n                binder.bind(this.typeChecker.globalScope, this.typeChecker.globals);\n                binder.bind(this.typeChecker.globalScope, this.typeChecker.ambientGlobals);\n                binder.bind(this.typeChecker.globalScope, this.typeChecker.globalTypes);\n                binder.bind(this.typeChecker.globalScope, this.typeChecker.ambientGlobalTypes);\n                this.typeFlow = new TypeFlow(this.logger, this.typeChecker.globalScope, this.parser, this.typeChecker);\n                var i = 0;\n                var script: Script = null;\n                var len = this.scripts.members.length;\n\n\n                this.persistentTypeState.setCollectionMode(TypeCheckCollectionMode.Resident);\n                // first, typecheck resident \"lib\" scripts, if necessary\n                for (i = 0; i < len; i++) {\n                    script = <Script>this.scripts.members[i];\n                    if (!script.isResident || script.hasBeenTypeChecked) { continue; }\n\n                    this.typeFlow.assignScopes(script);\n                    this.typeFlow.initLibs();\n                }\n                for (i = 0; i < len; i++) {\n                    script = <Script>this.scripts.members[i];\n                    if (!script.isResident || script.hasBeenTypeChecked) { continue; }\n\n                    this.typeFlow.typeCheck(script);\n                    script.hasBeenTypeChecked = true;\n                }\n\n                // next typecheck scripts that may change\n                this.persistentTypeState.setCollectionMode(TypeCheckCollectionMode.Transient);\n                len = this.scripts.members.length;\n                for (i = 0; i < len; i++) {\n                    script = <Script>this.scripts.members[i];\n                    if (script.isResident) { continue; }\n                    this.typeFlow.assignScopes(script);\n                    this.typeFlow.initLibs();\n                }\n                for (i = 0; i < len; i++) {\n                    script = <Script>this.scripts.members[i];\n                    if (script.isResident) { continue; }\n                    this.typeFlow.typeCheck(script);\n                }\n\n                return null;\n            });\n        }\n\n        public cleanASTTypesForReTypeCheck(ast: AST) {\n            function cleanASTType(ast: AST, parent: AST): AST {\n                ast.type = null;\n                if (ast.nodeType == NodeType.VarDecl) {\n                    var vardecl = <VarDecl>ast;\n                    vardecl.sym = null;\n                }\n                else if (ast.nodeType == NodeType.ArgDecl) {\n                    var argdecl = <ArgDecl>ast;\n                    argdecl.sym = null;\n                }\n                else if (ast.nodeType == NodeType.Name) {\n                    var name = <Identifier>ast;\n                    name.sym = null;\n                }\n                else if (ast.nodeType == NodeType.FuncDecl) {\n                    var funcdecl = <FuncDecl>ast;\n                    funcdecl.signature = null;\n                    funcdecl.freeVariables = new Symbol[]\n                    funcdecl.symbols = null;\n                    funcdecl.accessorSymbol = null;\n                    funcdecl.scopeType = null;\n                }\n                else if (ast.nodeType == NodeType.ModuleDeclaration) {\n                    var modDecl = <ModuleDeclaration>ast;\n                    modDecl.mod = null;\n                }\n                else if (ast.nodeType == NodeType.With) {\n                    (<WithStatement>ast).withSym = null;\n                }\n                else if (ast.nodeType == NodeType.Catch) {\n                    (<Catch>ast).containedScope = null;\n                }\n                return ast;\n            }\n            TypeScript.getAstWalkerFactory().walk(ast, cleanASTType);\n        }\n\n        public cleanTypesForReTypeCheck() {\n            return this.timeFunction(\"cleanTypesForReTypeCheck()\", () => {\n                for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n                    var script = this.scripts.members[i];\n                    if ((<Script>script).isResident) {\n                        continue;\n                    }\n                    this.cleanASTTypesForReTypeCheck(script);\n                    this.typeChecker.collectTypes(script);\n                }\n\n                return null;\n            });\n        }\n\n        // Return \"true\" if the incremental typecheck was successful\n        // Return \"false\" if incremental typecheck failed, requiring a full typecheck\n        public attemptIncrementalTypeCheck(updateResult: TypeScript.UpdateUnitResult): bool {\n            return this.timeFunction(\"attemptIncrementalTypeCheck()\", () => {\n                // updateResult.kind == editsInsideFunction\n                // updateResult.scope1 == old function\n                // updateResult.scope2 == new function\n                //REVIEW: What about typecheck errors? How do we replace the old ones with the new ones?\n                return false;\n            });\n        }\n\n        public reTypeCheck() {\n            return this.timeFunction(\"reTypeCheck()\", () => {\n                CompilerDiagnostics.analysisPass++;\n                this.initTypeChecker(this.errorOutput);\n                this.persistentTypeState.setCollectionMode(TypeCheckCollectionMode.Transient);\n                this.cleanTypesForReTypeCheck();\n                return this.typeCheck();\n            });\n        }\n\n        private isDynamicModuleCompilation() {\n            for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n                var script = <Script>this.scripts.members[i];\n                if (!script.isDeclareFile && script.topLevelMod != null) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private updateCommonDirectoryPath() {\n            var commonComponents: string[] = [];\n            var commonComponentsLength = -1;\n            for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n                var script = <Script>this.scripts.members[i];\n                if (script.emitRequired(this.emitSettings)) {\n                    var fileName = script.locationInfo.filename;\n                    var fileComponents = filePathComponents(fileName);\n                    if (commonComponentsLength == -1) {\n                        // First time at finding common path\n                        // So common path = directory of file\n                        commonComponents = fileComponents;\n                        commonComponentsLength = commonComponents.length;\n                    } else {\n                        var updatedPath = false;\n                        for (var j = 0; j < commonComponentsLength && j < fileComponents.length; j++) {\n                            if (commonComponents[j] != fileComponents[j]) {\n                                // The new components = 0 ... j -1\n                                commonComponentsLength = j;\n                                updatedPath = true;\n\n                                if (j == 0) {\n                                    // Its error to not have common path\n                                    this.errorReporter.emitterError(null, \"Cannot find the common subdirectory path for the input files\");\n                                    return;\n                                }\n\n                                break;\n                            }\n                        }\n\n                        // If the fileComponent path completely matched and less than already found update the length\n                        if (!updatedPath && fileComponents.length < commonComponentsLength) {\n                            commonComponentsLength = fileComponents.length;\n                        }\n                    }\n                }\n            }\n\n            this.emitSettings.commonDirectoryPath = commonComponents.slice(0, commonComponentsLength).join(\"/\") + \"/\";\n            if (this.emitSettings.outputOption.charAt(this.emitSettings.outputOption.length - 1) != \"/\") {\n                this.emitSettings.outputOption += \"/\";\n            }\n        }\n\n        public parseEmitOption(ioHost: EmitterIOHost) {\n            this.emitSettings.ioHost = ioHost;\n            if (this.emitSettings.outputOption == \"\") {\n                this.emitSettings.outputMany = true;\n                this.emitSettings.commonDirectoryPath = \"\";\n                return;\n            }\n\n            this.emitSettings.outputOption = switchToForwardSlashes(this.emitSettings.ioHost.resolvePath(this.emitSettings.outputOption));\n\n            // Determine if output options is directory or file\n            if (this.emitSettings.ioHost.directoryExists(this.emitSettings.outputOption)) {\n                // Existing directory\n                this.emitSettings.outputMany = true;\n            } else if (this.emitSettings.ioHost.fileExists(this.emitSettings.outputOption)) {\n                // Existing file\n                this.emitSettings.outputMany = false;\n            }\n            else {\n                // New File/directory\n                this.emitSettings.outputMany = !isJSFile(this.emitSettings.outputOption);\n            }\n\n            // Verify if options are correct\n            if (this.isDynamicModuleCompilation() && !this.emitSettings.outputMany) {\n                this.errorReporter.emitterError(null, \"Cannot compile dynamic modules when emitting into single file\");\n            }\n\n            // Parse the directory structure\n            if (this.emitSettings.outputMany) {\n                this.updateCommonDirectoryPath();\n            }\n        }\n\n        public useUTF8ForFile(script: Script) {\n            if (this.emitSettings.outputMany) {\n                return this.outputScriptToUTF8(script);\n            } else {\n                return this.outputScriptsToUTF8(<Script[]>(this.scripts.members));\n            }\n        }\n\n        static mapToDTSFileName(fileName: string, wholeFileNameReplaced: bool) {\n            return getDeclareFilePath(fileName);\n        }\n\n        private canEmitDeclarations(script?: Script) {\n            if (!this.settings.generateDeclarationFiles) {\n                return false;\n            }\n\n            // If its already a declare file or is resident or does not contain body \n            if (!!script && (script.isDeclareFile || script.isResident || script.bod == null)) {\n                return false;\n            }\n\n            return true;\n        }\n\n        public emitDeclarationsUnit(script: Script, reuseEmitter?: bool, declarationEmitter?: DeclarationEmitter) {\n            if (!this.canEmitDeclarations(script)) {\n                return null;\n            }\n\n            if (!declarationEmitter) {\n                var declareFileName = this.emitSettings.mapOutputFileName(script.locationInfo.filename, TypeScriptCompiler.mapToDTSFileName);\n                var declareFile = this.createFile(declareFileName, this.useUTF8ForFile(script));\n                declarationEmitter = new DeclarationEmitter(this.typeChecker, this.emitSettings, this.errorReporter);\n                declarationEmitter.setDeclarationFile(declareFile);\n            }\n\n            declarationEmitter.emitDeclarations(script);\n\n            if (!reuseEmitter) {\n                declarationEmitter.Close();\n                return null;\n            } else {\n                return declarationEmitter;\n            }\n        }\n\n        public emitDeclarations() {\n            if (!this.canEmitDeclarations()) {\n                return;\n            }\n\n            if (this.errorReporter.hasErrors) {\n                // There were errors reported, do not generate declaration file\n                return;\n            }\n\n            if (this.scripts.members.length == 0) {\n                return;\n            }\n\n            var declarationEmitter: DeclarationEmitter = null;\n            for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n                var script = <Script>this.scripts.members[i];\n                if (this.emitSettings.outputMany || declarationEmitter == null) {\n                    // Create or reuse file\n                    declarationEmitter = this.emitDeclarationsUnit(script, !this.emitSettings.outputMany);\n                } else {\n                    // Emit in existing emitter\n                    this.emitDeclarationsUnit(script, true, declarationEmitter);\n                }\n            }\n\n            if (declarationEmitter) {\n                declarationEmitter.Close();\n            }\n        }\n\n        static mapToFileNameExtension(extension: string, fileName: string, wholeFileNameReplaced: bool) {\n            if (wholeFileNameReplaced) {\n                // The complete output is redirected in this file so do not change extension\n                return fileName;\n            } else {\n                // Change the extension of the file\n                var splitFname = fileName.split(\".\");\n                splitFname.pop();\n                return splitFname.join(\".\") + extension;\n            }\n        }\n\n        static mapToJSFileName(fileName: string, wholeFileNameReplaced: bool) {\n            return TypeScriptCompiler.mapToFileNameExtension(\".js\", fileName, wholeFileNameReplaced);\n        }\n\n        public emitUnit(script: Script, reuseEmitter?: bool, emitter?: Emitter) {\n            if (!script.emitRequired(this.emitSettings)) {\n                return null;\n            }\n\n            var fname = script.locationInfo.filename;\n            if (!emitter) {\n                var outFname = this.emitSettings.mapOutputFileName(fname, TypeScriptCompiler.mapToJSFileName);\n                var outFile = this.createFile(outFname, this.useUTF8ForFile(script));\n                emitter = new Emitter(this.typeChecker, outFname, outFile, this.emitSettings, this.errorReporter);\n                if (this.settings.mapSourceFiles) {\n                    emitter.setSourceMappings(new TypeScript.SourceMapper(fname, outFname, outFile, this.createFile(outFname + SourceMapper.MapFileExtension, false), this.errorReporter));\n                }\n            } else if (this.settings.mapSourceFiles) {\n                emitter.setSourceMappings(new TypeScript.SourceMapper(fname, emitter.emittingFileName, emitter.outfile, emitter.sourceMapper.sourceMapOut, this.errorReporter));\n            }\n\n            this.typeChecker.locationInfo = script.locationInfo;\n            emitter.emitJavascript(script, TokenID.Comma, false);\n            if (!reuseEmitter) {\n                emitter.Close();\n                return null;\n            } else {\n                return emitter;\n            }\n        }\n\n        public emit(ioHost: EmitterIOHost) {\n            this.parseEmitOption(ioHost);\n\n            var emitter: Emitter = null;\n            for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n                var script = <Script>this.scripts.members[i];\n                if (this.emitSettings.outputMany || emitter == null) {\n                    emitter = this.emitUnit(script, !this.emitSettings.outputMany);\n                } else {\n                    this.emitUnit(script, true, emitter);\n                }\n            }\n\n            if (emitter) {\n                emitter.Close();\n            }\n        }\n\n        public emitToOutfile(outputFile: ITextWriter) {\n            if (this.settings.mapSourceFiles) {\n                throw Error(\"Cannot generate source map\");\n            }\n\n            if (this.settings.generateDeclarationFiles) {\n                throw Error(\"Cannot generate declaration files\");\n            }\n\n            if (this.settings.outputOption != \"\") {\n                throw Error(\"Cannot parse output option\");\n            }\n\n            var emitter: Emitter = emitter = new Emitter(this.typeChecker, \"stdout\", outputFile, this.emitSettings, this.errorReporter);;\n            for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n                var script = <Script>this.scripts.members[i];\n                this.typeChecker.locationInfo = script.locationInfo;\n                emitter.emitJavascript(script, TokenID.Comma, false);\n            }\n        }\n\n        public emitAST(ioHost: EmitterIOHost) {\n            this.parseEmitOption(ioHost);\n\n            var outFile: ITextWriter = null;\n            var context: PrintContext = null;\n\n            for (var i = 0, len = this.scripts.members.length; i < len; i++) {\n                var script = <Script>this.scripts.members[i];\n                if (this.emitSettings.outputMany || context == null) {\n                    var fname = this.units[i].filename;\n                    var mapToTxtFileName = (fileName: string, wholeFileNameReplaced: bool) => {\n                        return TypeScriptCompiler.mapToFileNameExtension(\".txt\", fileName, wholeFileNameReplaced);\n                    };\n                    var outFname = this.emitSettings.mapOutputFileName(fname, mapToTxtFileName);\n                    outFile = this.createFile(outFname, this.useUTF8ForFile(script));\n                    context = new PrintContext(outFile, this.parser);\n                }\n                getAstWalkerFactory().walk(script, prePrintAST, postPrintAST, null, context);\n                if (this.emitSettings.outputMany) {\n                    try {\n                        outFile.Close();\n                    } catch (e) {\n                        this.errorReporter.emitterError(null, e.message);\n                    }\n                }\n            }\n\n            if (!this.emitSettings.outputMany) {\n                try {\n                    outFile.Close();\n                } catch (e) {\n                    this.errorReporter.emitterError(null, e.message);\n                }\n            }\n        }\n\n        private outputScriptToUTF8(script: Script): bool {\n            return script.containsUnicodeChar || (this.emitSettings.emitComments && script.containsUnicodeCharInComment);\n        }\n\n        private outputScriptsToUTF8(scripts: Script[]): bool {\n            for (var i = 0, len = scripts.length; i < len; i++) {\n                var script = scripts[i];\n                if (this.outputScriptToUTF8(script)) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        private createFile(fileName: string, useUTF8: bool): ITextWriter {\n            try {\n                // Creating files can cause exceptions, report them.   \n                return this.emitSettings.ioHost.createFile(fileName, useUTF8);\n            } catch (ex) {\n                this.errorReporter.emitterError(null, ex.message);\n            }\n        }\n    }\n\n    export class ScopeEntry {\n        constructor (\n            public name: string,\n            public type: string,\n            public sym: Symbol) {\n        }\n    }\n\n    export class ScopeTraversal {\n        constructor (private compiler: TypeScriptCompiler) {\n        }\n\n        public getScope(enclosingScopeContext: EnclosingScopeContext): SymbolScope {\n            if (enclosingScopeContext.enclosingObjectLit && enclosingScopeContext.isMemberCompletion) {\n                return enclosingScopeContext.getObjectLiteralScope();\n            }\n            else if (enclosingScopeContext.isMemberCompletion) {\n                if (enclosingScopeContext.useFullAst) {\n                    return this.compiler.typeFlow.findMemberScopeAtFullAst(enclosingScopeContext)\n                }\n                else {\n                    return this.compiler.typeFlow.findMemberScopeAt(enclosingScopeContext)\n                }\n            }\n            else {\n                return enclosingScopeContext.getScope();\n            }\n        }\n\n        public getScopeEntries(enclosingScopeContext: EnclosingScopeContext): ScopeEntry[] {\n            var scope = this.getScope(enclosingScopeContext);\n            if (scope == null) {\n                return [];\n            }\n\n            var inScopeNames: IHashTable = new StringHashTable();\n            var allSymbolNames: string[] = scope.getAllSymbolNames(enclosingScopeContext.isMemberCompletion);\n\n            // there may be duplicates between the type and value tables, so batch the symbols\n            // getTypeNamesForNames will prefer the entry in the value table\n            for (var i = 0; i < allSymbolNames.length; i++) {\n                var name = allSymbolNames[i];\n\n                // Skip global/internal symbols that won't compile in user code\n                if (name == globalId || name == \"_Core\" || name == \"_element\") {\n                    continue;\n                }\n\n                inScopeNames.add(name, \"\");\n            }\n\n            var svModuleDecl = this.compiler.typeChecker.currentModDecl;\n            this.compiler.typeChecker.currentModDecl = enclosingScopeContext.deepestModuleDecl;\n\n            var result = this.getTypeNamesForNames(enclosingScopeContext, inScopeNames.getAllKeys(), scope);\n\n            this.compiler.typeChecker.currentModDecl = svModuleDecl;\n            return result;\n        }\n\n        private getTypeNamesForNames(enclosingScopeContext: EnclosingScopeContext, allNames: string[], scope: SymbolScope): ScopeEntry[] {\n            var result: ScopeEntry[] = [];\n\n            var enclosingScope = enclosingScopeContext.getScope();\n            for (var i = 0; i < allNames.length; i++) {\n                var name = allNames[i];\n                // Search for the id in the value space first\n                // if we don't find it, search in the type space.\n                // We don't want to search twice, because the first\n                // search may insert the name in the symbol value table\n                // if the scope is aggregate\n                var publicsOnly = enclosingScopeContext.publicsOnly && enclosingScopeContext.isMemberCompletion;\n                var symbol = scope.find(name, publicsOnly, false/*typespace*/);  // REVIEW: Should search public members only?\n                if (symbol == null) {\n                    symbol = scope.find(name, publicsOnly, true/*typespace*/);\n                }\n\n                var displayThisMember = symbol && symbol.flags & SymbolFlags.Private ? symbol.container == scope.container : true;\n\n                if (symbol) {\n                    // Do not add dynamic module names to the list, since they're not legal as identifiers\n                    if (displayThisMember && !isQuoted(symbol.name) && !isRelative(symbol.name)) {\n                        var typeName = symbol.getType().getScopedTypeName(enclosingScope);\n                        result.push(new ScopeEntry(name, typeName, symbol));\n                    }\n                }\n                else {\n                    // Special case for \"true\" and \"false\"\n                    // REVIEW: This may no longer be necessary?\n                    if (name == \"true\" || name == \"false\") {\n                        result.push(new ScopeEntry(name, \"bool\", this.compiler.typeChecker.booleanType.symbol));\n                    }\n                }\n            }\n\n            return result;\n        }\n    }\n}\n//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule TypeScript {\n\n    export enum Primitive {\n        None = 0,\n        Void = 1,\n        Double = 2,\n        String = 4,\n        Boolean = 8,\n        Any = 16,\n        Null = 32,\n        Undefined = 64,\n    }\n\n    export class MemberName {\n        public prefix: string = \"\";\n        public suffix: string = \"\";\n\n        public isString() { return false; }\n        public isArray() { return false; }\n\n        public toString(): string {\n            return MemberName.memberNameToString(this);\n        }\n\n        static memberNameToString(memberName: MemberName): string {\n            var result = memberName.prefix;\n\n            if (memberName.isString()) {\n                result += (<MemberNameString>memberName).text;\n            }\n            else {\n                var ar = <MemberNameArray>memberName;\n                for (var index = 0; index < ar.entries.length; index++) {\n                    result += memberNameToString(ar.entries[index]);\n                    result += ar.delim;\n                }\n            }\n\n            result += memberName.suffix;\n            return result;\n        }\n\n        static create(text: string): MemberName;\n        static create(entry: MemberName, prefix: string, suffix: string): MemberName;\n        static create(arg1: any, arg2?: any, arg3?: any): MemberName {\n            if (typeof arg1 == \"string\") {\n                return new MemberNameString(arg1);\n            }\n            else {\n                var result = new MemberNameArray();\n                if (arg2)\n                    result.prefix = arg2;\n                if (arg3)\n                    result.suffix = arg3;\n                result.entries.push(arg1);\n                return result;\n            }\n        }\n    }\n\n    export class MemberNameString extends MemberName {\n        constructor (public text: string) {\n            super()\n        }\n\n        public isString() { return true; }\n    }\n\n    export class MemberNameArray extends MemberName {\n        public delim: string = \"\";\n        public entries: MemberName[] = [];\n\n        public isArray() { return true; }\n\n        public add(entry: MemberName) {\n            this.entries.push(entry);\n        }\n\n        public addAll(entries: MemberName[]) {\n            for (var i = 0 ; i < entries.length; i++) {\n                this.entries.push(entries[i]);\n            }\n        }\n    }\n\n    var currentTypeID = -1;\n\n    export class Type {\n        public typeID = currentTypeID++;\n\n        public members: ScopedMembers;\n        public ambientMembers: ScopedMembers;\n\n        public construct: SignatureGroup = null;\n        public call: SignatureGroup = null;\n        public index: SignatureGroup = null;\n\n        // REVIEW: for either of the below, why do we have lists of types and lists of type links?\n        // interface can only extend\n        public extendsList: Type[];\n        public extendsTypeLinks: TypeLink[];\n\n        // class can also implement\n        public implementsList: Type[];\n        public implementsTypeLinks: TypeLink[];\n\n        public passTypeCreated: number = CompilerDiagnostics.analysisPass;\n\n        public baseClass(): Type {\n            if (this.extendsList && (this.extendsList.length > 0)) {\n                return this.extendsList[0];\n            }\n            else {\n                return null;\n            }\n        }\n\n        public elementType: Type;\n\n        public getArrayBase(arrInstType: Type, checker: TypeChecker): Type {\n            return this.arrayCache.specialize(arrInstType, checker);\n        }\n\n        public primitiveTypeClass: number = Primitive.None;\n\n        // REVIEW: Prune constructorScope\n        public constructorScope: SymbolScope;\n        public containedScope: SymbolScope;\n        public memberScope: SymbolScope;\n\n        public arrayCache: ArrayCache;\n\n        public typeFlags = TypeFlags.None;\n\n        public symbol: TypeSymbol;\n\n        public enclosingType: Type;\n        public instanceType: Type;\n\n        // REVIEW: Prune\n        public isClass() { return this.instanceType != null; }\n        public isArray() { return this.elementType != null; }\n        public isClassInstance() {\n            return this.symbol && !this.elementType && (<TypeSymbol>this.symbol).type.isClass();\n        }\n\n        public getInstanceType() {\n            if (this.isClass()) {\n                return this.instanceType;\n            }\n            else {\n                return this;\n            }\n        }\n\n        public hasImplementation() { return hasFlag(this.typeFlags, TypeFlags.HasImplementation); }\n        public setHasImplementation() { this.typeFlags |= TypeFlags.HasImplementation; }\n\n        public isDouble() { return hasFlag(this.primitiveTypeClass, Primitive.Double); }\n        public isString() { return hasFlag(this.primitiveTypeClass, Primitive.String); }\n        public isBoolean() { return hasFlag(this.primitiveTypeClass, Primitive.Boolean); }\n        public isNull() { return hasFlag(this.primitiveTypeClass, Primitive.Null); }\n\n        // REVIEW: No need for this to be a method\n        public getTypeName(): string {\n            return this.getMemberTypeName(\"\", true, false, null);\n        }\n\n        public getScopedTypeName(scope: SymbolScope) {\n            return this.getMemberTypeName(\"\", true, false, scope);\n        }\n\n        public getScopedTypeNameEx(scope: SymbolScope) {\n            return this.getMemberTypeNameEx(\"\", true, false, scope);\n        }\n\n        // REVIEW: No need for this to be a method\n        public callCount() {\n            var total = 0;\n            if (this.call) {\n                total += this.call.signatures.length;\n            }\n            if (this.construct) {\n                total += this.construct.signatures.length;\n            }\n            if (this.index) {\n                total += this.index.signatures.length;\n            }\n            return total;\n        }\n\n        // REVIEW: No need for this to be a method\n        public getMemberTypeName(prefix: string, topLevel: bool, isElementType: bool, scope: SymbolScope): string {\n            var memberName = this.getMemberTypeNameEx(prefix, topLevel, isElementType, scope);\n            return memberName.toString();\n        }\n\n        // REVIEW: No need for this to be a method\n        public getMemberTypeNameEx(prefix: string, topLevel: bool, isElementType: bool, scope: SymbolScope): MemberName {\n            if (this.elementType) {\n                return MemberName.create(this.elementType.getMemberTypeNameEx(prefix, false, true, scope), \"\", \"[]\");\n            }\n            else if (this.symbol && this.symbol.name && this.symbol.name != \"_anonymous\" &&\n                     (((this.call == null) && (this.construct == null) && (this.index == null)) ||\n                      (hasFlag(this.typeFlags, TypeFlags.BuildingName)) ||\n                      (this.members && (!this.isClass())))) {\n                var tn = this.symbol.scopeRelativeName(scope);\n                return MemberName.create(tn == \"null\" ? \"any\" : tn); // REVIEW: GROSS!!!\n            }\n            else {\n                if (this.members || this.call || this.construct) {\n                    if (hasFlag(this.typeFlags, TypeFlags.BuildingName)) {\n                        return MemberName.create(\"this\");\n                    }\n                    this.typeFlags |= TypeFlags.BuildingName;\n                    var builder = \"\";\n                    var allMemberNames = new MemberNameArray();\n                    var curlies = isElementType || this.index != null;\n                    var memCount = 0;\n                    var delim = \"; \";\n                    if (this.members) {\n                        this.members.allMembers.map((key, s, unused) => {\n                            var sym = <Symbol>s;\n                            if (!hasFlag(sym.flags, SymbolFlags.BuiltIn)) {\n                                // Remove the delimiter character from the generated type name, since\n                                // our \"allMemberNames\" array takes care of storing delimiters\n                                var typeNameMember = sym.getTypeNameEx(scope);\n                                if (typeNameMember.isArray() && (<MemberNameArray>typeNameMember).delim == delim) {\n                                    allMemberNames.addAll((<MemberNameArray>typeNameMember).entries);\n                                } else {\n                                    allMemberNames.add(typeNameMember);\n                                }\n                                memCount++;\n                                curlies = true;\n                            }\n                        }, null);\n                    }\n\n                    var signatureCount = this.callCount();\n                    var j: number;\n                    var len = 0;\n                    var shortform = !curlies && signatureCount == 1 && topLevel;\n                    if (this.call) {\n                        allMemberNames.addAll(this.call.toStrings(prefix, shortform, scope));\n                    }\n\n                    if (this.construct) {\n                        allMemberNames.addAll(this.construct.toStrings(\"new\", shortform, scope));\n                    }\n\n                    if (this.index) {\n                        allMemberNames.addAll(this.index.toStrings(\"\", shortform, scope));\n                    }\n\n                    if ((curlies) || ((signatureCount > 1) && topLevel)) {\n                        allMemberNames.prefix = \"{ \";\n                        allMemberNames.suffix = \"}\";\n                        allMemberNames.delim = delim;\n                    } else if (allMemberNames.entries.length > 1) {\n                        allMemberNames.delim = delim;\n                    }\n\n                    this.typeFlags &= (~TypeFlags.BuildingName);\n                    if ((signatureCount == 0) && (memCount == 0)) {\n                        return MemberName.create(\"{}\");\n                    }\n                    else {\n                        return allMemberNames;\n                    }\n                }\n                else {\n                    return MemberName.create(\"{}\");\n                }\n            }\n        }\n\n        public checkDecl(checker: TypeChecker) {\n            if (this.isClassInstance() || this.isClass()) {\n                if (this.symbol.declAST) {\n                    checker.typeFlow.inScopeTypeCheckDecl(this.symbol.declAST);\n                }\n            }\n        }\n\n        public getMemberScope(flow: TypeFlow) {\n            if (this == flow.anyType) {\n                return null;\n            }\n            else if (this.isDouble()) {\n                if (flow.numberInterfaceType) {\n                    return flow.numberInterfaceType.memberScope;\n                }\n                else {\n                    return null;\n                }\n            }\n            else if (this.isBoolean()) {\n                if (flow.booleanInterfaceType) {\n                    return flow.booleanInterfaceType.memberScope;\n                }\n                else {\n                    return null;\n                }\n            }\n            else if (this == flow.stringType) {\n                if (flow.stringInterfaceType) {\n                    return flow.stringInterfaceType.memberScope;\n                }\n                else {\n                    return null;\n                }\n            }\n            else if (this.elementType) {\n                if (flow.arrayInterfaceType) {\n                    var arrInstType = this.elementType.getArrayBase(flow.arrayInterfaceType, flow.checker);\n                    return arrInstType.memberScope;\n                }\n                else {\n                    return null;\n                }\n            }\n            else {\n                return this.memberScope;\n            }\n        }\n\n        public isReferenceType() {\n            return this.members || this.extendsList ||\n                this.construct || this.call || this.index ||\n                this.elementType;\n        }\n\n        public specializeType(pattern: Type, replacement: Type, checker: TypeChecker, membersOnly: bool): Type {\n            if (pattern == this) {\n                return replacement;\n            }\n            var result = this;\n            if (membersOnly) {\n                // assume interface type without bases\n                if (this.isReferenceType()) {\n                    result = new Type();\n                    if (this.members) {\n                        result.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n\n                        this.members.publicMembers.map((key, s, unused) => {\n                            var sym = <Symbol>s;\n                            var bSym = sym.specializeType(pattern, replacement, checker);\n                            result.members.addPublicMember(bSym.name, bSym);\n                        }, null);\n\n                        this.members.privateMembers.map((key, s, unused) => {\n                            var sym = <Symbol>s;\n                            var bSym = sym.specializeType(pattern, replacement, checker);\n                            result.members.addPrivateMember(bSym.name, bSym);\n                        }, null);\n                    }\n                    if (this.ambientMembers) {\n                        result.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));\n                        this.ambientMembers.publicMembers.map((key, s, unused) => {\n                            var sym = <Symbol>s;\n                            var bSym = sym.specializeType(pattern, replacement, checker);\n                            result.ambientMembers.addPublicMember(bSym.name, bSym);\n                        }, null);\n\n                        this.ambientMembers.privateMembers.map((key, s, unused) => {\n                            var sym = <Symbol>s;\n                            var bSym = sym.specializeType(pattern, replacement, checker);\n                            result.ambientMembers.addPrivateMember(bSym.name, bSym);\n                        }, null);\n                    }\n                    result.containedScope = checker.scopeOf(result);\n                    result.memberScope = result.containedScope;\n                }\n            }\n            else {\n                if (this.elementType) {\n                    if (this.elementType == pattern) {\n                        result = checker.makeArrayType(replacement);\n                    }\n                    else {\n                        if (this.elementType.elementType == pattern) {\n                            result = checker.makeArrayType(checker.makeArrayType(replacement));\n                        }\n                    }\n                }\n                else if (this.call) {\n                    result = new Type();\n                    result.call = this.call.specializeType(pattern, replacement, checker);\n                }\n            }\n            return result;\n        }\n\n        public hasBase(baseType: Type): bool {\n            if (baseType == this) {\n                return true;\n            }\n            else {\n                if (this.extendsList) {\n                    for (var i = 0, len = this.extendsList.length; i < len; i++) {\n                        if (this.extendsList[i].hasBase(baseType)) {\n                            return true;\n                        }\n                    }\n                }\n            }\n            return false;\n        }\n\n        public mergeOrdered(b: Type, checker: TypeChecker, acceptVoid: bool, comparisonInfo?: TypeComparisonInfo): Type {\n            if ((this == checker.anyType) || (b == checker.anyType)) {\n                return checker.anyType;\n            }\n            else if (this == b) {\n                return this;\n            }\n            else if ((b == checker.nullType) && this != checker.nullType) {\n                return this;\n            }\n            else if ((this == checker.nullType) && (b != checker.nullType)) {\n                return b;\n            }\n            else if (acceptVoid && (b == checker.voidType) && this != checker.voidType) {\n                return this;\n            }\n            else if (acceptVoid && (this == checker.voidType) && (b != checker.voidType)) {\n                return b;\n            }\n            else if ((b == checker.undefinedType) && this != checker.undefinedType) {\n                return this;\n            }\n            else if ((this == checker.undefinedType) && (b != checker.undefinedType)) {\n                return b;\n            }\n            else if (this.elementType && b.elementType) {\n                if (this.elementType == b.elementType) {\n                    return this;\n                }\n                else {\n                    var mergedET = this.elementType.mergeOrdered(b.elementType, checker, acceptVoid, comparisonInfo);\n                    if (mergedET == null) {\n                        return checker.makeArrayType(checker.anyType);\n                    }\n                    else {\n                        return checker.makeArrayType(mergedET);\n                    }\n                }\n            }\n            else if (checker.sourceIsSubtypeOfTarget(this, b, comparisonInfo)) {\n                return b;\n            }\n            else if (checker.sourceIsSubtypeOfTarget(b, this, comparisonInfo)) {\n                return this;\n            }\n            else {\n                return null;\n            }\n        }\n\n        public isModuleType() { return false; }\n        public hasMembers() { return this.members != null; }\n        public getAllEnclosedTypes(): ScopedMembers { return null; }\n        public getAllAmbientEnclosedTypes(): ScopedMembers { return null; }\n        public getPublicEnclosedTypes(): ScopedMembers { return null; }\n        public getpublicAmbientEnclosedTypes(): ScopedMembers { return null; }\n\n        public getDocComments(): Comment[]{\n            if (this.elementType || !this.symbol) {\n                return [];\n            }\n\n            if (this.isClassInstance() || this.isClass()) {\n                if (this.symbol.declAST.nodeType == NodeType.FuncDecl) {\n                    // Its a constructor - use the class declaration instead\n                    return (<FuncDecl>this.symbol.declAST).classDecl.getDocComments();\n                } else {\n                    // Its a class without constructor\n                    return this.symbol.getDocComments();\n                }\n            }\n\n            if (this.symbol.name && this.symbol.name != \"_anonymous\" &&\n                (((this.call == null) && (this.construct == null) && (this.index == null))\n                  || this.members)) {\n                return this.symbol.getDocComments();\n            }\n\n            return [];\n        }\n    }\n\n    export interface ITypeCollection {\n        // returns null when types are exhausted\n        getLength(): number;\n        setTypeAtIndex(index: number, type: Type): void;\n        getTypeAtIndex(index: number): Type;\n    }\n\n    export class ModuleType extends Type {\n\n        constructor (public enclosedTypes: ScopedMembers, public ambientEnclosedTypes: ScopedMembers) {\n            super();\n        }\n\n        public isModuleType() { return true; }\n        public hasMembers() { return this.members != null || this.enclosedTypes != null; }\n        public getAllEnclosedTypes() { return this.enclosedTypes; }\n        public getAllAmbientEnclosedTypes() { return this.ambientEnclosedTypes; }\n        public getPublicEnclosedTypes(): ScopedMembers { return null; }\n        public getpublicAmbientEnclosedTypes(): ScopedMembers { return null; }\n        public importedModules: ImportDeclaration[] = [];\n\n        // Finds the dynamic module name of moduleType in the members\n        // ignoreSymbols define list of symbols already visited - to avoid recursion\n        static findDynamicModuleNameInHashTable(moduleType: Type, members: IHashTable) {\n            var moduleName: { name: string; symbol: Symbol; } = null;\n            members.map((key, s, c) => {\n                if (moduleName == null && !isQuoted(key)) {\n                    var symbol = <Symbol>s;\n                    var type = symbol.getType();\n                    if (type == moduleType) {\n                        // If this is the module type we were looking for\n                        moduleName = { name: key, symbol: symbol };\n                    }\n                }\n            }, null);\n\n            return moduleName;\n        }\n\n        // Finds the Dynamic module name of the moduleType in this moduleType\n        // onlyPublic tells if we are looking for module name in public members only\n        public findDynamicModuleName(moduleType: Type): { name: string; symbol: Symbol; } {\n            var moduleName: { name: string; symbol: Symbol; } = null;\n            // Not cached, so seach and add to the cache\n            moduleName = ModuleType.findDynamicModuleNameInHashTable(moduleType, this.members.allMembers);\n            if (moduleName == null) {\n                moduleName = ModuleType.findDynamicModuleNameInHashTable(moduleType, this.ambientMembers.allMembers);\n            }\n            return moduleName;\n        }\n    }\n\n    export class TypeLink {\n        public type: Type = null;\n        public ast: AST = null;\n    }\n\n    export function getTypeLink(ast: AST, checker: TypeChecker, autoVar: bool): TypeLink {\n        var result = new TypeLink();\n\n        result.ast = ast;\n\n        if ((ast == null) && (autoVar)) {\n            result.type = checker.anyType;\n        }\n        else {\n            result.type = null;\n        }\n\n        return result;\n    }\n\n}//\n// Copyright (c) Microsoft Corporation.  All rights reserved.\n// \n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//   http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n//\n\n///<reference path='typescript.ts' />\n\nmodule Tools {\n    export interface IWalkContext {\n        goChildren: bool;\n        goNextSibling: bool;\n        // visit siblings in reverse execution order\n        reverseSiblings: bool;\n    }\n\n    export class BaseWalkContext implements IWalkContext {\n        public goChildren = true;\n        public goNextSibling = true;\n        public reverseSiblings = false;\n    }\n}"

////////////////////////////////////////////////////////////////////////////////
// Runner
////////////////////////////////////////////////////////////////////////////////

var success = true;

function NotifyStart(name) {
}

function NotifyError(name, error) {
  WScript.Echo(name + " : ERROR : " +error.stack);
  success = false;
}

function NotifyResult(name, score) {
  if (success) {
    WScript.Echo("### SCORE:", score);
  }
}

function NotifyScore(score) {
}

BenchmarkSuite.RunSuites({
	NotifyStart : NotifyStart,
    NotifyError : NotifyError,
    NotifyResult : NotifyResult,
    NotifyScore : NotifyScore
});

