diff --git a/cli/asc.js b/cli/asc.js
index 7f43685d74..1ca90e8fbe 100644
--- a/cli/asc.js
+++ b/cli/asc.js
@@ -583,12 +583,14 @@ exports.main = function main(argv, options, callback) {
       assemblyscript.enableFeature(compilerOptions, flag);
     }
   }
-
+  
+  var compiler
   var module;
   stats.compileCount++;
   try {
     stats.compileTime += measure(() => {
-      module = assemblyscript.compileProgram(program, compilerOptions);
+      compiler = assemblyscript.initializeCompiler(program, compilerOptions);
+      module = compiler.compile();
     });
   } catch (e) {
     return callback(e);
@@ -598,6 +600,24 @@ exports.main = function main(argv, options, callback) {
     return callback(Error("Compile error"));
   }
 
+  // Call each visitor
+  if (args.postCompile) {
+    let visitors = []
+    try {
+      for (let filename of args.postCompile) {
+        let _filename = path.isAbsolute(filename = filename.trim())
+        ? filename
+        : path.join(process.cwd(), filename)
+        visitors.push(require(_filename).default);
+      }
+      visitors.forEach(visitor => {
+        (new visitor(parser, compiler, stderr)).start();
+      });
+    } catch (e) {
+      return callback(e);
+    }
+  }
+
   // Validate the module if requested
   if (args.validate) {
     stats.validateCount++;
diff --git a/cli/asc.json b/cli/asc.json
index a6e5fa6338..fd5f916a8e 100644
--- a/cli/asc.json
+++ b/cli/asc.json
@@ -242,5 +242,26 @@
   "-O0z": { "value": { "optimizeLevel": 0, "shrinkLevel": 2 } },
   "-O1z": { "value": { "optimizeLevel": 1, "shrinkLevel": 2 } },
   "-O2z": { "value": { "optimizeLevel": 2, "shrinkLevel": 2 } },
-  "-O3z": { "value": { "optimizeLevel": 3, "shrinkLevel": 2 } }
+  "-O3z": { "value": { "optimizeLevel": 3, "shrinkLevel": 2 } },
+  "path": {
+    "description": [
+      "Comma separated paths to look for dependencies.",
+      "Looks for folders with package.json that includes a 'ascMain' field",
+      "or defaults to having an '/assembly' folder."],
+    "type": "S"
+  },
+  "traceResolution": {
+    "description": "Enable tracing of package resolution.",
+    "type": "b",
+    "default": false
+  },
+  "listFiles": {
+    "description": "List files to be compiled and exit.",
+    "type": "b",
+    "default": false
+  },
+  "postCompile": {
+    "description": "A pass over the program after compiling to Binaryen IR",
+    "type": "S"
+  }
 }
diff --git a/cli/postCompile.d.ts b/cli/postCompile.d.ts
new file mode 100644
index 0000000000..b228a99943
--- /dev/null
+++ b/cli/postCompile.d.ts
@@ -0,0 +1,16 @@
+/**
+ * Definitions for custom compiler transforms that can be applied with the `--postCompile` option.
+ * @module cli/postTransform
+ *//***/
+
+import { Parser } from "../src/parser";
+import { Compiler } from "../src/compiler";
+
+interface stderr {
+    write: (str: string)=> void;
+}
+export interface Vistor {
+    new(parser: Parser, compiler: Compiler, writer: stderr);
+    start(): void;
+}   
+ 
\ No newline at end of file
diff --git a/lib/visitor/as-pect.config.js b/lib/visitor/as-pect.config.js
new file mode 100644
index 0000000000..d311edfd0a
--- /dev/null
+++ b/lib/visitor/as-pect.config.js
@@ -0,0 +1,76 @@
+module.exports = {
+  /**
+   * A set of globs passed to the glob package that qualify typescript files for testing.
+   */
+  include: ["assembly/__tests__/**/*.spec.ts"],
+  /**
+   * A set of globs passed to the glob package that quality files to be added to each test.
+   */
+  add: ["assembly/__tests__/**/*.include.ts"],
+  /**
+   * All the compiler flags needed for this test suite. Make sure that a binary file is output.
+   */
+  flags: {
+    "--validate": [],
+    "--debug": [],
+    /** This is required. Do not change this. The filename is ignored, but required by the compiler. */
+    "--binaryFile": ["output.wasm"],
+    /** To enable wat file output, use the following flag. The filename is ignored, but required by the compiler. */
+    "--textFile": ["output.wat"],
+    /** To select an appropriate runtime, use the --runtime compiler flag. */
+    "--runtime": ["stub"], // Acceptable values are: full, half, stub (arena), and none,
+    "--baseDir": process.cwd(),
+    "--postCompile": "dist/instances/virtual.js",
+  },
+  /**
+   * A set of regexp that will disclude source files from testing.
+   */
+  disclude: [/node_modules/],
+  /**
+   * Add your required AssemblyScript imports here.
+   */
+  imports: {},
+  /**
+   * All performance statistics reporting can be configured here.
+   */
+  performance: {
+    /** Enable performance statistics gathering for every test. */
+    enabled: false,
+    /** Set the maximum number of samples to run for every test. */
+    maxSamples: 10000,
+    /** Set the maximum test run time in milliseconds for every test. */
+    maxTestRunTime: 5000,
+    /** Report the median time in the default reporter for every test. */
+    reportMedian: true,
+    /** Report the average time in milliseconds for every test. */
+    reportAverage: true,
+    /** Report the standard deviation for every test. */
+    reportStandardDeviation: false,
+    /** Report the maximum run time in milliseconds for every test. */
+    reportMax: false,
+    /** Report the minimum run time in milliseconds for every test. */
+    reportMin: false,
+  },
+  /**
+   * Add a custom reporter here if you want one. The following example is in typescript.
+   *
+   * @example
+   * import { TestReporter, TestGroup, TestResult, TestContext } from "as-pect";
+   *
+   * export class CustomReporter extends TestReporter {
+   *   // implement each abstract method here
+   *   public abstract onStart(suite: TestContext): void;
+   *   public abstract onGroupStart(group: TestGroup): void;
+   *   public abstract onGroupFinish(group: TestGroup): void;
+   *   public abstract onTestStart(group: TestGroup, result: TestResult): void;
+   *   public abstract onTestFinish(group: TestGroup, result: TestResult): void;
+   *   public abstract onFinish(suite: TestContext): void;
+   * }
+   */
+  // reporter: new CustomReporter(),
+  /**
+   * Specify if the binary wasm file should be written to the file system.
+   */
+  outputBinary: false,
+  compiler: "../.."
+};
diff --git a/lib/visitor/assembly/__tests__/as-pect.d.ts b/lib/visitor/assembly/__tests__/as-pect.d.ts
new file mode 100644
index 0000000000..332464ac88
--- /dev/null
+++ b/lib/visitor/assembly/__tests__/as-pect.d.ts
@@ -0,0 +1,691 @@
+/**
+ * This function creates a test group in the test loader.
+ *
+ * @param {string} description  - This is the name of the test group.
+ * @param {() => void} callback - A function that contains all of the closures for this test group.
+ *
+ * @example
+ * describe("my test suite", (): void => {
+ *   // put your tests here
+ * });
+ */
+declare function describe(description: string, callback: () => void): void;
+
+/**
+ * This function creates a test inside the given test group. It must be placed inside a describe
+ * block.
+ *
+ * @param {string} description - This is the name of the test, and should describe a behavior.
+ * @param {() => void} callback - A function that contains a set of expectations for this test.
+ *
+ * @example
+ * describe("the meaning of life", (): void => {
+ *   it("should be 42", (): void => {
+ *     // put your expectations here
+ *     expect<i32>(29 + 13).toBe(42);
+ *   });
+ * });
+ */
+declare function it(description: string, callback: () => void): void;
+
+/**
+ * A test that does not run, and is longhand equivalent to using todo function without a
+ * callback. This test does not get run and is reported like a todo.
+ *
+ * @param {string} description - This is the name of the test, and should describe a behavior.
+ * @param {() => void} callback - A function that contains a set of expectations for this test.
+ */
+declare function xit(description: string, callback: () => void): void;
+
+/**
+ * A test that does not run, and is longhand equivalent to using todo function without a
+ * callback. This test does not get run and is reported like a todo.
+ *
+ * @param {string} description - This is the name of the test, and should describe a behavior.
+ * @param {() => void} callback - A function that contains a set of expectations for this test.
+ */
+declare function xtest(description: string, callback: () => void): void;
+
+/**
+ * This function creates a test inside the given test group. It must be placed inside a describe
+ * block.
+ *
+ * @param {string} description - This is the name of the test, and should describe a behavior.
+ * @param {() => void} callback - A function that contains a set of expectations for this test.
+ *
+ * @example
+ * describe("the meaning of life", (): void => {
+ *   test("the value should be 42", (): void => {
+ *     // put your expectations here
+ *     expect<i32>(29 + 13).toBe(42);
+ *   });
+ * });
+ */
+declare function test(description: string, callback: () => void): void;
+
+/**
+ * This function creates a test that is expected to fail. This is useful to verify if a given
+ * behavior is expected to throw.
+ *
+ * @param {string} description - This is the name of the test, and should describe a behavior.
+ * @param {() => void} callback - A function that contains a set of expectations for this test.
+ * @param {string?} message - A message that describes why the test should fail.
+ * @example
+ * describe("the meaning of life", (): void => {
+ *   throws("the value should be 42", (): void => {
+ *     // put your expectations here
+ *     expect<i32>(29 + 13).toBe(42);
+ *   });
+ * });
+ */
+declare function throws(description: string, callback: () => void, message?: string): void;
+
+
+/**
+ * This function creates a test that is expected to fail. This is useful to verify if a given
+ * behavior is expected to throw.
+ *
+ * @param {string} description - This is the name of the test, and should describe a behavior.
+ * @param {() => void} callback - A function that contains a set of expectations for this test.
+ * @param {string?} message - A message that describes why the test should fail.
+ * @example
+ * describe("the meaning of life", (): void => {
+ *   itThrows("when the value should be 42", (): void => {
+ *     // put your expectations here
+ *     expect<i32>(29 + 13).not.toBe(42);
+ *   }, "The value is actually 42.");
+ * });
+ */
+declare function itThrows(description: string, callback: () => void, message?: string): void;
+
+/**
+ * This function creates a callback that is called before each individual test is run in this test
+ * group.
+ *
+ * @param {function} callback - The function to be run before each test in the current test group.
+ *
+ * @example
+ * // create a global
+ * var cat: Cat = new Cat();
+ *
+ * describe("cats", (): void => {
+ *   beforeEach((): void => {
+ *     cat.meow(1); // meow once per test
+ *   });
+ * });
+ */
+declare function beforeEach(callback: () => void): void;
+
+/**
+ * This function creates a callback that is called before the whole test group is run, and only
+ * once.
+ *
+ * @param {function} callback - The function to be run before each test in the current test group.
+ *
+ * @example
+ * // create a global
+ * var dog: Dog = null;
+ * describe("dogs", (): void => {
+ *   beforeAll((): void => {
+ *     dog = new Dog(); // create a single dog once before the tests start
+ *   });
+ * });
+ */
+declare function beforeAll(callback: () => void): void;
+
+/**
+ * This function creates a callback that is called after each individual test is run in this test
+ * group.
+ *
+ * @param {function} callback - The function to be run after each test in the current test group.
+ *
+ * @example
+ * // create a global
+ * var cat: Cat = new Cat();
+ *
+ * describe("cats", (): void => {
+ *   afterEach((): void => {
+ *     cat.sleep(12); // cats sleep a lot
+ *   });
+ * });
+ */
+declare function afterEach(callback: () => void): void;
+
+/**
+ * This function creates a callback that is called after the whole test group is run, and only
+ * once.
+ *
+ * @param {function} callback - The function to be run after each test in the current test group.
+ *
+ * @example
+ * // create a global
+ * var dog: Dog = null;
+ * describe("dogs", (): void => {
+ *   afterAll((): void => {
+ *     memory.free(changetype<usize>(dog)); // free some memory
+ *   });
+ * });
+ */
+declare function afterAll(callback: () => void): void;
+
+/**
+ * Describes a value and returns an expectation to test the value.
+ *
+ * @type {T} - The test's type
+ * @param {T} actual - The value being tested.
+ *
+ * @example
+ * expect<i32>(42).not.toBe(-1, "42 should not be -1");
+ * expect<i32>(19 + 23).toBe(42, "19 + 23 should equal 42");
+ */
+declare function expect<T>(actual: T | null): Expectation<T>;
+
+/**
+ * Describes a function and returns an expectation to test the function.
+ *
+ * @param {() => void} callback - The callback being tested.
+ *
+ * @example
+ * expectFn((): void => unreachable()).toThrow("unreachables do not throw");
+ * expectFn((): void => {
+ *   cat.meow();
+ * }).not.toThrow("Uhoh, cats can't meow!");;
+ */
+declare function expectFn(cb: () => void): Expectation<() => void>;
+
+/**
+ * Describes a test that needs to be written.
+ *
+ * @param {string} description - The description of the test that needs to be written.
+ */
+declare function todo(description: string): void;
+
+/**
+ * Logs a single value to the logger, and is stringified. It works for references, values, and
+ * strings.
+ *
+ * @type {T} - The type to be logged.
+ * @param {T | null} value - The value to be logged.
+ * @example
+ * log<string>("This is a logged value.");
+ * log<i32>(42);
+ * log<Vec3>(new Vec(1, 2, 3));
+ * log<Vec3>(null);
+ */
+declare function log<T>(value: T | null): void;
+
+/**
+ * An expectation for a value.
+ */
+declare class Expectation<T> {
+
+  /**
+   * Create a new expectation.
+   *
+   * @param {T | null} actual - The actual value of the expectation.
+   */
+  constructor(actual: T | null);
+
+  /**
+   * This expectation performs a strict equality on value types and reference types.
+   *
+   * @param {T | null} expected - The value to be compared.
+   * @param {string} message - The optional message that describes the expectation.
+   *
+   * @example
+   * expect<i32>(42).not.toBe(-1, "42 should not be -1");
+   * expect<i32>(19 + 23).toBe(42, "19 + 23 should equal 42");
+   */
+  toBe(expected: T | null, message?: string): void;
+
+  /**
+   * This expectation performs a strict equality on value types and performs a memcompare on
+   * reference types. If the reference type `T` has reference types as properties, the comparison does
+   * not perform property traversal. It will only compare the pointer values in the memory block, and
+   * only compare `offsetof<T>()` bytes, regardless of the allocated block size.
+   *
+   * @param {T | null} expected - The value to be compared.
+   * @param {string} message - The optional message that describes the expectation.
+   *
+   * @example
+   * expect<Vec3>(new Vec3(1, 2, 3)).toStrictEqual(new Vec(1, 2, 3), "Vectors of the same shape should be equal");
+   */
+  toStrictEqual(expected: T | null, message?: string): void;
+
+  /**
+   * This expectation performs a strict memory block equality based on the allocated block sizes.
+   *
+   * @param {T | null} expected - The value to be compared.
+   * @param {string} message - The optional message that describes the expectation.
+   *
+   * @example
+   * expect<Vec3>(new Vec3(1, 2, 3)).toBlockEqual(new Vec(1, 2, 3), "Vectors of the same shape should be equal");
+   */
+  toBlockEqual(expected: T | null, message?: string): void;
+
+  /**
+   * If the value is callable, it calls the function, and fails the expectation if it throws, or hits
+   * an unreachable().
+   *
+   * @param {string} message - The optional message that describes the expectation.
+   *
+   * @example
+   * expectFn((): void => unreachable()).toThrow("unreachable() should throw.");
+   * expectFn((): void => {
+   *   cat.sleep(100); // cats can sleep quite a lot
+   * }).not.toThrow("cats should sleep, not throw");
+   */
+  toThrow(message?: string): void;
+
+  /**
+   * This expecation asserts that the value is truthy, like in javascript. If the value is a string,
+   * then strings of length 0 are not truthy.
+   *
+   * @param {string} message - The optional message that describes the expectation.
+   *
+   * @example
+   * expect<bool>(true).toBeTruthy("true is truthy.");
+   * expect<i32>(1).toBeTruthy("numeric values that are not 0 are truthy.");
+   * expect<Vec3>(new Vec3(1, 2, 3)).toBeTruthy("reference types that aren't null are truthy.");
+   * expect<bool>(false).not.toBeTruthy("false is not truthy.");
+   * expect<i32>(0).not.toBeTruthy("0 is not truthy.");
+   * expect<Vec3>(null).not.toBeTruthy("null is not truthy.");
+   */
+  toBeTruthy(message?: string): void;
+
+  /**
+   * This expectation tests the value to see if it is null. If the value is a value type, it is
+   * never null. If the value is a reference type, it performs a strict null comparison.
+   *
+   * @param {string} message - The optional message that describes the expectation.
+   *
+   * @example
+   * expect<i32>(0).not.toBeNull("numbers are never null");
+   * expect<Vec3>(null).toBeNull("null reference types are null.");
+   */
+  toBeNull(message?: string): void;
+
+  /**
+   * This expecation assert that the value is falsy, like in javascript. If the value is a string,
+   * then strings of length 0 are falsy.
+   *
+   * @param {string} message - The optional message that describes the expectation.
+   *
+   * @example
+   * expect<bool>(false).toBeFalsy("false is falsy.");
+   * expect<i32>(0).toBeFalsy("0 is falsy.");
+   * expect<Vec3>(null).toBeFalsy("null is falsy.");
+   * expect<bool>(true).not.toBeFalsy("true is not falsy.");
+   * expect<i32>(1).not.toBeFalsy("numeric values that are not 0 are not falsy.");
+   * expect<Vec3>(new Vec3(1, 2, 3)).not.toBeFalsy("reference types that aren't null are not falsy.");
+   */
+  toBeFalsy(message?: string): void;
+
+  /**
+   * This expectation asserts that the value is greater than the expected value. Since operators can
+   * be overloaded in assemblyscript, it's possible for this to work on reference types.
+   *
+   * @param {T | null} expected - The expected value that the actual value should be greater than.
+   * @param {string} message - The optional message that describes this expectation.
+   *
+   * @example
+   * expect<i32>(10).toBeGreaterThan(4);
+   * expect<i32>(12).not.toBeGreaterThan(42);
+   */
+  toBeGreaterThan(expected: T | null, message?: string): void;
+
+  /**
+   * This expectation asserts that the value is less than the expected value. Since operators can
+   * be overloaded in assemblyscript, it's possible for this to work on reference types.
+   *
+   * @param {T | null} value - The expected value that the actual value should be less than.
+   * @param {string} message - The optional message that describes this expectation.
+   *
+   * @example
+   * expect<i32>(10).not.toBeLessThan(4);
+   * expect<i32>(12).toBeLessThan(42);
+   */
+  toBeLessThan(expected: T | null, message?: string): void;
+
+  /**
+   * This expectation asserts that the value is greater than or equal to the expected value. Since
+   * operators can be overloaded in assemblyscript, it's possible for this to work on reference
+   * types.
+   *
+   * @param {T | null} value - The expected value that the actual value should be greater than or
+   * equal to.
+   * @param {string} message - The optional message that describes this expectation.
+   *
+   * @example
+   * expect<i32>(42).toBeGreaterThanOrEqual(42);
+   * expect<i32>(10).toBeGreaterThanOrEqual(4);
+   * expect<i32>(12).not.toBeGreaterThanOrEqual(42);
+   */
+  toBeGreaterThanOrEqual(expected: T | null, message?: string): void;
+
+  /**
+   * This expectation asserts that the value is less than or equal to the expected value. Since
+   * operators can be overloaded in assemblyscript, it's possible for this to work on reference
+   * types.
+   *
+   * @param {T | null} value - The expected value that the actual value should be less than or equal
+   * to.
+   * @param {string} message - The optional message that describes this expectation.
+   *
+   * @example
+   * expect<i32>(42).toBeLessThanOrEqual(42);
+   * expect<i32>(10).not.toBeLessThanOrEqual(4);
+   * expect<i32>(12).toBeLessThanOrEqual(42);
+   */
+  toBeLessThanOrEqual(expected: T | null, message?: string): void;
+
+  /**
+   * This expectation asserts that the value is close to another value. Both numbers must be finite,
+   * and T must extend f64 or f32.
+   *
+   * @param {T extends f64 | f32} value - The expected value to be close to.
+   * @param {i32} decimalPlaces - The number of decimal places used to calculate epsilon. Default is
+   * 2.
+   * @param {string} message - The optional message that describes this expectation.
+   */
+  toBeCloseTo(expected: T, decimalPlaces?: number, message?: string): void;
+
+  /**
+   * This function asserts the float type value is NaN.
+   *
+   * @param {string} message - The optional message the describes this expectation.
+   * @example
+   * expect<f64>(NaN).toBeNaN();
+   * expect<f32>(42).not.toBeNaN();
+   */
+  toBeNaN(message?: string): void;
+
+  /**
+   * This function asserts a float is finite.
+   *
+   * @param {string} message - The optional message the describes this expectation.
+   * @example
+   * expect<f32>(42).toBeFinite();
+   * expect<f64>(Infinity).not.toBeFinite();
+   */
+  toBeFinite(message?: string): void;
+
+  /**
+   * This method asserts the item has the expected length.
+   *
+   * @param {i32} expected - The expected length.
+   * @param {string} message - The optional message the describes this expectation.
+   */
+  toHaveLength(expected: i32, message?: string): void;
+
+  /**
+   * This method asserts that a given T that extends Array<U> has a value/reference included.
+   *
+   * @param {valueof<T>} expected - The expected item to be included in the Array.
+   * @param {string} message - The optional message the describes this expectation.
+   */
+  // @ts-ignore: expected value should be known at compile time
+  toInclude(expected: valueof<T>, message?: string): void;
+
+  /**
+   * This method asserts that a given T that extends Array<U> has a value/reference included.
+   *
+   * @param {valueof<T>} expected - The expected item to be included in the Array.
+   * @param {string} message - The optional message the describes this expectation.
+   */
+   // @ts-ignore: expected value should be known at compile time
+  toContain(expected: valueof<T>, message?: string): void;
+
+  /**
+   * This method asserts that a given T that extends Array<U> has a value/reference included and
+   * compared via memory.compare().
+   *
+   * @param {i32} expected - The expected item to be included in the Array.
+   * @param {string} message - The optional message the describes this expectation.
+   */
+  // @ts-ignore: expected value should be known at compile time
+  toIncludeEqual(expected: valueof<T>, message?: string): void;
+
+  /**
+   * This method asserts that a given T that extends Array<U> has a value/reference included and
+   * compared via memory.compare().
+   *
+   * @param {i32} expected - The expected item to be included in the Array.
+   * @param {string} message - The optional message the describes this expectation.
+   */
+  // @ts-ignore: expected value should be known at compile time
+  toContainEqual(expected: valueof<T>, message?: string): void;
+
+  /**
+   * This computed property is chainable, and negates the existing expectation. It returns itself.
+   */
+  not: Expectation<T>;
+
+  /**
+   * The actual value of the expectation.
+   */
+  actual: T | null;
+}
+
+/**
+ * This is called to stop the debugger.  e.g. `node --inspect-brk asp`.
+ */
+declare function debug(): void;
+
+/**
+ * This class contains a set of methods related to performance configuration.
+ */
+declare class Performance {
+  /**
+   * This function call enables performance statistics gathering for the following test.
+   *
+   * @param {bool} enabled - The bool to indicate if performance statistics should be gathered.
+   */
+  public static enabled(enabled: bool): void;
+
+  /**
+   * This function call sets the maximum number of samples to complete the following test.
+   *
+   * @param {f64} count - The maximum number of samples required.
+   */
+  public static maxSamples(count: f64): void;
+
+  /**
+   * This function call sets the number of decimal places to round to for the following test.
+   *
+   * @param {i32} deicmalPlaces - The number of decimal places to round to
+   */
+  public static roundDecimalPlaces(count: i32): void;
+
+  /**
+   * This function call will set the maximum amount of time that should pass before it can stop
+   * gathering samples for the following test.
+   *
+   * @param {f64} time - The ammount of time in milliseconds.
+   */
+  public static maxTestRunTime(time: f64): void;
+
+  /**
+   * This function call enables gathering the average/mean run time of each sample for the following
+   * test.
+   *
+   * @param {bool} enabled - The bool to indicate if the average/mean should be gathered.
+   */
+  public static reportAverage(enabled: bool): void;
+
+  /**
+   * This function call enables gathering the median run time of each sample for the following test.
+   *
+   * @param {bool} enabled - The bool to indicate if the median should be gathered.
+   */
+  public static reportMedian(value: bool): void;
+
+  /**
+   * This function call enables gathering the standard deviation of the run times of the samples
+   * collected for the following test.
+   *
+   * @param {bool} enabled - The bool to indicate if the standard deviation should be gathered.
+   */
+  public static reportStdDev(value: bool): void;
+
+  /**
+   * This function call enables gathering the largest run time of the samples collected for the
+   * following test.
+   *
+   * @param {bool} enabled - The bool to indicate if the max should be gathered.
+   */
+  public static reportMax(value: bool): void;
+
+  /**
+   * This function call enables gathering the smallest run time of the samples collected for the
+   * following test.
+   *
+   * @param {bool} enabled - The bool to indicate if the min should be gathered.
+   */
+  public static reportMin(value: bool): void;
+
+  /**
+   * This function call enables gathering the varaince of the samples collected for the following test.
+   *
+   * @param {bool} enabled - The bool to indicate if the variance should be calculated.
+   */
+  public static reportVariance(value: bool): void;
+}
+/**
+ * This static class contains a few conveince methods for developers to test the current number of
+ * blocks allocated on the heap.
+ */
+declare class RTrace {
+  /**
+   * This bool indicates if `RTrace` should call into JavaScript to obtain reference counts.
+   */
+  public static enabled: bool;
+
+  /**
+   * This method returns the current number of active references on the heap.
+   */
+  public static count(): i32;
+
+  /**
+   * This method starts a new refcounting group, and causes the next call to `RTrace.end(label)` to
+   * return a delta in reference counts on the heap.
+   *
+   * @param {i32} label - The numeric label for this refcounting group.
+   */
+  public static start(label: i32): void;
+
+  /**
+   * This method returns a delta of how many new (positive) or collected (negative) are on the heap.
+   *
+   * @param {i32} label - The numeric label for this refcounting group.
+   */
+  public static end(label: i32): i32;
+
+  /**
+   * This method returns the number of increments that have occurred over the course of a test
+   * file.
+   */
+  public static increments(): i32;
+
+  /**
+   * This method returns the number of decrements that have occurred over the course of a test
+   * file.
+   */
+  public static decrements(): i32;
+
+  /**
+   * This method returns the number of increments that have occurred over the course of a test
+   * group.
+   */
+  public static groupIncrements(): i32;
+
+  /**
+   * This method returns the number of decrements that have occurred over the course of a test
+   * group.
+   */
+  public static groupDecrements(): i32;
+
+  /**
+   * This method returns the number of increments that have occurred over the course of a test
+   * group.
+   */
+  public static testIncrements(): i32;
+
+  /**
+   * This method returns the number of decrements that have occurred over the course of a test
+   * group.
+   */
+  public static testDecrements(): i32;
+
+  /**
+   * This method returns the number of allocations that have occurred over the course of a test
+   * file.
+   */
+  public static allocations(): i32;
+
+  /**
+   * This method returns the number of frees that have occurred over the course of a test
+   * file.
+   */
+  public static frees(): i32;
+
+  /**
+   * This method returns the number of allocations that have occurred over the course of a test
+   * group.
+   */
+  public static groupAllocations(): i32;
+
+  /**
+   * This method returns the number of frees that have occurred over the course of a test
+   * group.
+   */
+  public static groupFrees(): i32;
+
+  /**
+   * This method returns the number of allocations that have occurred over the course of a test
+   * group.
+   */
+  public static testAllocations(): i32;
+
+  /**
+   * This method returns the number of frees that have occurred over the course of a test
+   * group.
+   */
+  public static testFrees(): i32;
+
+  /**
+   * This method triggers a garbage collection.
+   */
+  public static collect(): void;
+
+  /**
+   * Get the class id of the pointer.
+   *
+   * @param {usize} pointer - The pointer.
+   * @returns {u32} - The class id of the allocated block.
+   */
+  public static classIdOf(pointer: usize): u32;
+
+  /**
+   * Get the size of a block or buffer.
+   *
+   * @param {T} reference - The reference.
+   * @returns {u32} - The size of the allocated block.
+   */
+  public static sizeOf<T>(reference: T): u32;
+
+  /**
+   * Get the currently allocated blocks.
+   */
+  public static activeBlocks(): usize[];
+
+  /**
+   * Get the current groups allocated blocks.
+   */
+  public static activeGroupBlocks(): usize[];
+
+  /**
+   * Get the current tests allocated blocks.
+   */
+  public static activeTestBlocks(): usize[];
+}
diff --git a/lib/visitor/assembly/__tests__/example.spec.ts b/lib/visitor/assembly/__tests__/example.spec.ts
new file mode 100644
index 0000000000..d1840f3338
--- /dev/null
+++ b/lib/visitor/assembly/__tests__/example.spec.ts
@@ -0,0 +1,36 @@
+
+export class Foo implements Fu {
+  int: i32 = 0;
+  float: f32 = 1.2;
+
+  runTwo(i: i32, i2: i32): i32 {
+    return this.int + i + i2;
+  }
+
+  run(i: i32): void {
+    this.int += i;
+  }
+}
+interface Fu {
+  run(i: i32): void;
+  runTwo(i: i32, i2: i32): i32;
+}
+
+function testInterface(fu: Fu): void {
+  fu.run(10);
+}
+
+function testRun2(fu: Fu): i32 {
+  return fu.runTwo(5, 5);
+}
+
+const foo = new Foo();
+
+describe("interface", ():void => {
+  it("should handle foo", ():void => {
+    foo.run(0);
+    testInterface(foo);
+    expect<i32>(foo.int).toBe(10);
+    expect<i32>((<Fu>foo).runTwo(5, 5)).toBe(20);
+  });
+})
diff --git a/lib/visitor/assembly/__tests__/example.spec.wat b/lib/visitor/assembly/__tests__/example.spec.wat
new file mode 100644
index 0000000000..d3314eaaea
--- /dev/null
+++ b/lib/visitor/assembly/__tests__/example.spec.wat
@@ -0,0 +1,853 @@
+(module
+ (type $FUNCSIG$iii (func (param i32 i32) (result i32)))
+ (type $FUNCSIG$ii (func (param i32) (result i32)))
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$vii (func (param i32 i32)))
+ (type $FUNCSIG$viii (func (param i32 i32 i32)))
+ (type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$viiii (func (param i32 i32 i32 i32)))
+ (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
+ (type $FUNCSIG$vdii (func (param f64 i32 i32)))
+ (type $FUNCSIG$vdiii (func (param f64 i32 i32 i32)))
+ (type $FUNCSIG$fi (func (param i32) (result f32)))
+ (type $FUNCSIG$vif (func (param i32 f32)))
+ (import "__aspect" "getStackTrace" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/getStackTrace (result i32)))
+ (import "__aspect" "reportInvalidExpectCall" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportInvalidExpectCall))
+ (import "__aspect" "getStackTrace" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/getStackTrace (result i32)))
+ (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
+ (import "__aspect" "reportTest" (func $node_modules/@as-pect/assembly/assembly/internal/Test/reportTest (param i32 i32)))
+ (import "__aspect" "reportDescribe" (func $node_modules/@as-pect/assembly/assembly/internal/Describe/reportDescribe (param i32)))
+ (import "__aspect" "reportEndDescribe" (func $node_modules/@as-pect/assembly/assembly/internal/Describe/reportEndDescribe))
+ (import "__aspect" "reportActualArray" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualArray (param i32 i32)))
+ (import "__aspect" "reportActualValue" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualFloat (param f64 i32 i32)))
+ (import "__aspect" "reportActualValue" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualInteger (param i32 i32 i32)))
+ (import "__aspect" "reportActualNull" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualNull (param i32)))
+ (import "__aspect" "reportActualReference" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualReferenceExternal (param i32 i32 i32)))
+ (import "__aspect" "reportActualString" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualString (param i32 i32)))
+ (import "__aspect" "reportActualLong" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualLong (param i32 i32 i32)))
+ (import "__aspect" "reportActualBool" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualBool (param i32 i32)))
+ (import "__aspect" "reportExpectedArray" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedArray (param i32 i32 i32)))
+ (import "__aspect" "reportExpectedValue" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedFloat (param f64 i32 i32 i32)))
+ (import "__aspect" "reportExpectedValue" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedInteger (param i32 i32 i32 i32)))
+ (import "__aspect" "reportExpectedNull" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedNull (param i32 i32)))
+ (import "__aspect" "reportExpectedReference" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedReferenceExternal (param i32 i32 i32 i32)))
+ (import "__aspect" "reportExpectedString" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedString (param i32 i32 i32)))
+ (import "__aspect" "reportExpectedFalsy" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedFalsy (param i32 i32)))
+ (import "__aspect" "reportExpectedFinite" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedFinite (param i32 i32)))
+ (import "__aspect" "reportExpectedTruthy" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedTruthy (param i32 i32)))
+ (import "__aspect" "reportExpectedLong" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedLong (param i32 i32 i32 i32)))
+ (import "__aspect" "reportExpectedBool" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedBool (param i32 i32 i32)))
+ (memory $0 1)
+ (data (i32.const 8) "\12\00\00\00\01\00\00\00\01\00\00\00\12\00\00\00i\00n\00t\00e\00r\00f\00a\00c\00e\00")
+ (data (i32.const 48) "\"\00\00\00\01\00\00\00\01\00\00\00\"\00\00\00s\00h\00o\00u\00l\00d\00 \00h\00a\00n\00d\00l\00e\00 \00f\00o\00o\00")
+ (data (i32.const 104) "\8a\00\00\00\01\00\00\00\01\00\00\00\8a\00\00\00n\00o\00d\00e\00_\00m\00o\00d\00u\00l\00e\00s\00/\00@\00a\00s\00-\00p\00e\00c\00t\00/\00a\00s\00s\00e\00m\00b\00l\00y\00/\00a\00s\00s\00e\00m\00b\00l\00y\00/\00i\00n\00t\00e\00r\00n\00a\00l\00/\00c\00o\00m\00p\00a\00r\00i\00s\00o\00n\00/\00a\00s\00s\00e\00r\00t\00.\00t\00s\00")
+ (data (i32.const 264) "\00\00\00\00\01\00\00\00\01\00\00\00\00\00\00\00")
+ (data (i32.const 280) "\07\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\10\00\00\00\00\00\00\00\93\00\00\00\02\00\00\00")
+ (table $0 6 funcref)
+ (elem (i32.const 0) $null $start:assembly/__tests__/example.spec~anonymous|0~anonymous|0 $start:assembly/__tests__/example.spec~anonymous|0 $start:node_modules/@as-pect/assembly/assembly/internal/noOp~anonymous|0)
+ (elem (i32.const 0) $null $start:assembly/__tests__/example.spec~anonymous|0~anonymous|0 $start:assembly/__tests__/example.spec~anonymous|0 $start:node_modules/@as-pect/assembly/assembly/internal/noOp~anonymous|0 $assembly/__tests__/example.spec/Foo#runTwo $assembly/__tests__/example.spec/Foo#run)
+ (global $~lib/rt/stub/startOffset (mut i32) (i32.const 0))
+ (global $~lib/rt/stub/offset (mut i32) (i32.const 0))
+ (global $assembly/__tests__/example.spec/foo (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.type (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.signed (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.float (mut f64) (f64.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.integer (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.reference (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.offset (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace (mut i32) (i32.const -1))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.ready (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.type (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.signed (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.float (mut f64) (f64.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.integer (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.reference (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.offset (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/noOp/noOp i32 (i32.const 3))
+ (global $~lib/argc (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/log/ignoreLogs (mut i32) (i32.const 0))
+ (global $node_modules/@as-pect/assembly/assembly/internal/RTrace/RTrace.enabled (mut i32) (i32.const 1))
+ (global $~lib/started (mut i32) (i32.const 0))
+ (global $~lib/rt/__rtti_base i32 (i32.const 280))
+ (global $~lib/heap/__heap_base i32 (i32.const 340))
+ (global $assembly/__tests__/example.spec/Foo i32 (i32.const 3))
+ (export "__start" (func $start))
+ (export "memory" (memory $0))
+ (export "__alloc" (func $~lib/rt/stub/__alloc))
+ (export "__retain" (func $~lib/rt/stub/__retain))
+ (export "__release" (func $~lib/rt/stub/__release))
+ (export "__collect" (func $~lib/rt/stub/__collect))
+ (export "__rtti_base" (global $~lib/rt/__rtti_base))
+ (export "Foo" (global $assembly/__tests__/example.spec/Foo))
+ (export "Foo#get:int" (func $Foo#get:int))
+ (export "Foo#set:int" (func $Foo#set:int))
+ (export "Foo#get:float" (func $Foo#get:float))
+ (export "Foo#set:float" (func $Foo#set:float))
+ (export "Foo#runTwo" (func $assembly/__tests__/example.spec/Foo#runTwo))
+ (export "Foo#run" (func $assembly/__tests__/example.spec/Foo#run))
+ (export "__ready" (func $node_modules/@as-pect/assembly/assembly/index/__ready))
+ (export "__call" (func $node_modules/@as-pect/assembly/assembly/internal/call/__call))
+ (export "__sendActual" (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/__sendActual))
+ (export "__sendExpected" (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/__sendExpected))
+ (export "__ignoreLogs" (func $node_modules/@as-pect/assembly/assembly/internal/log/__ignoreLogs))
+ (export "__disableRTrace" (func $node_modules/@as-pect/assembly/assembly/internal/RTrace/__disableRTrace))
+ (export "__getUsizeArrayId" (func $node_modules/@as-pect/assembly/assembly/internal/RTrace/__getUsizeArrayId))
+ (export "__cleanup" (func $node_modules/@as-pect/assembly/assembly/internal/Expectation/__cleanup))
+ (func $~lib/rt/stub/__alloc (; 26 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
+  (local $2 i32)
+  (local $3 i32)
+  (local $4 i32)
+  (local $5 i32)
+  (local $6 i32)
+  (local $7 i32)
+  (local $8 i32)
+  local.get $0
+  i32.const 1073741808
+  i32.gt_u
+  if
+   unreachable
+  end
+  global.get $~lib/rt/stub/offset
+  i32.const 16
+  i32.add
+  local.set $2
+  local.get $2
+  local.get $0
+  local.tee $3
+  i32.const 1
+  local.tee $4
+  local.get $3
+  local.get $4
+  i32.gt_u
+  select
+  i32.add
+  i32.const 15
+  i32.add
+  i32.const 15
+  i32.const -1
+  i32.xor
+  i32.and
+  local.set $5
+  memory.size
+  local.set $6
+  local.get $5
+  local.get $6
+  i32.const 16
+  i32.shl
+  i32.gt_u
+  if
+   local.get $5
+   local.get $2
+   i32.sub
+   i32.const 65535
+   i32.add
+   i32.const 65535
+   i32.const -1
+   i32.xor
+   i32.and
+   i32.const 16
+   i32.shr_u
+   local.set $3
+   local.get $6
+   local.tee $4
+   local.get $3
+   local.tee $7
+   local.get $4
+   local.get $7
+   i32.gt_s
+   select
+   local.set $4
+   local.get $4
+   memory.grow
+   i32.const 0
+   i32.lt_s
+   if
+    local.get $3
+    memory.grow
+    i32.const 0
+    i32.lt_s
+    if
+     unreachable
+    end
+   end
+  end
+  local.get $5
+  global.set $~lib/rt/stub/offset
+  local.get $2
+  i32.const 16
+  i32.sub
+  local.set $8
+  local.get $8
+  local.get $1
+  i32.store offset=8
+  local.get $8
+  local.get $0
+  i32.store offset=12
+  local.get $2
+ )
+ (func $~lib/rt/stub/__retain (; 27 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
+  local.get $0
+ )
+ (func $~lib/rt/stub/__release (; 28 ;) (type $FUNCSIG$vi) (param $0 i32)
+  nop
+ )
+ (func $~lib/rt/stub/__collect (; 29 ;) (type $FUNCSIG$v)
+  nop
+ )
+ (func $assembly/__tests__/example.spec/Foo#constructor (; 30 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
+  local.get $0
+  i32.eqz
+  if
+   i32.const 8
+   i32.const 3
+   call $~lib/rt/stub/__alloc
+   call $~lib/rt/stub/__retain
+   local.set $0
+  end
+  local.get $0
+  i32.const 0
+  i32.store
+  local.get $0
+  f32.const 1.2000000476837158
+  f32.store offset=4
+  local.get $0
+ )
+ (func $assembly/__tests__/example.spec/Foo#run (; 31 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
+  local.get $0
+  local.get $0
+  i32.load
+  local.get $1
+  i32.add
+  i32.store
+ )
+ (func $assembly/__tests__/example.spec/testInterface (; 32 ;) (type $FUNCSIG$vi) (param $0 i32)
+  local.get $0
+  call $~lib/rt/stub/__retain
+  drop
+  local.get $0
+  i32.const 10
+  call $assembly/__tests__/example.spec/Fu#run
+  local.get $0
+  call $~lib/rt/stub/__release
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/Expectation/Expectation<i32>#constructor (; 33 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
+  local.get $0
+  i32.eqz
+  if
+   i32.const 8
+   i32.const 5
+   call $~lib/rt/stub/__alloc
+   call $~lib/rt/stub/__retain
+   local.set $0
+  end
+  local.get $0
+  i32.const 0
+  i32.store
+  local.get $0
+  i32.const 0
+  i32.store offset=4
+  local.get $0
+  local.get $1
+  i32.store offset=4
+  local.get $0
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/Expectation/expect<i32> (; 34 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
+  i32.const 0
+  local.get $0
+  call $node_modules/@as-pect/assembly/assembly/internal/Expectation/Expectation<i32>#constructor
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.report<i32> (; 35 ;) (type $FUNCSIG$vi) (param $0 i32)
+  call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/getStackTrace
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+  i32.const 3
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.type
+  local.get $0
+  drop
+  i32.const 1
+  if (result i32)
+   i32.const 1
+  else   
+   local.get $0
+   drop
+   i32.const 0
+  end
+  if (result i32)
+   i32.const 1
+  else   
+   local.get $0
+   drop
+   i32.const 0
+  end
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.signed
+  local.get $0
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.integer
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.report<i32> (; 36 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
+  global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.ready
+  i32.eqz
+  if
+   call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportInvalidExpectCall
+   return
+  end
+  call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/getStackTrace
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+  local.get $1
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+  i32.const 3
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.type
+  local.get $0
+  drop
+  i32.const 1
+  if (result i32)
+   i32.const 1
+  else   
+   local.get $0
+   drop
+   i32.const 0
+  end
+  if (result i32)
+   i32.const 1
+  else   
+   local.get $0
+   drop
+   i32.const 0
+  end
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.signed
+  local.get $0
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.integer
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.clear (; 37 ;) (type $FUNCSIG$v)
+  i32.const 0
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.type
+  global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.reference
+  i32.const 0
+  i32.gt_u
+  if
+   global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.reference
+   call $~lib/rt/stub/__release
+   i32.const 0
+   global.set $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.reference
+  end
+  i32.const -1
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.clear (; 38 ;) (type $FUNCSIG$v)
+  i32.const 0
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.type
+  global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.reference
+  i32.const 0
+  i32.gt_u
+  if
+   global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.reference
+   call $~lib/rt/stub/__release
+   i32.const 0
+   global.set $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.reference
+  end
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/Expectation/Expectation<i32>#toBe (; 39 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
+  (local $3 i32)
+  (local $4 i32)
+  (local $5 i32)
+  (local $6 i32)
+  (local $7 i32)
+  (local $8 i32)
+  local.get $2
+  call $~lib/rt/stub/__retain
+  drop
+  local.get $0
+  i32.load offset=4
+  local.set $6
+  local.get $1
+  local.set $5
+  local.get $0
+  i32.load
+  local.set $4
+  local.get $2
+  call $~lib/rt/stub/__retain
+  local.set $3
+  local.get $6
+  call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.report<i32>
+  local.get $5
+  local.get $4
+  call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.report<i32>
+  local.get $4
+  local.get $5
+  local.get $6
+  i32.eq
+  i32.xor
+  local.set $8
+  local.get $3
+  call $~lib/rt/stub/__retain
+  local.set $7
+  local.get $8
+  i32.eqz
+  if
+   local.get $7
+   call $~lib/rt/stub/__release
+   local.get $7
+   i32.const 120
+   i32.const 11
+   i32.const 18
+   call $~lib/builtins/abort
+   unreachable
+  end
+  local.get $7
+  call $~lib/rt/stub/__release
+  local.get $3
+  call $~lib/rt/stub/__release
+  call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.clear
+  call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.clear
+  local.get $2
+  call $~lib/rt/stub/__release
+ )
+ (func $start:assembly/__tests__/example.spec~anonymous|0~anonymous|0 (; 40 ;) (type $FUNCSIG$v)
+  (local $0 i32)
+  (local $1 i32)
+  global.get $assembly/__tests__/example.spec/foo
+  i32.const 0
+  call $assembly/__tests__/example.spec/Foo#run
+  global.get $assembly/__tests__/example.spec/foo
+  call $assembly/__tests__/example.spec/testInterface
+  global.get $assembly/__tests__/example.spec/foo
+  i32.load
+  call $node_modules/@as-pect/assembly/assembly/internal/Expectation/expect<i32>
+  local.tee $0
+  i32.const 10
+  i32.const 280
+  call $node_modules/@as-pect/assembly/assembly/internal/Expectation/Expectation<i32>#toBe
+  global.get $assembly/__tests__/example.spec/foo
+  i32.const 5
+  i32.const 5
+  call $assembly/__tests__/example.spec/Fu#runTwo
+  call $node_modules/@as-pect/assembly/assembly/internal/Expectation/expect<i32>
+  local.tee $1
+  i32.const 20
+  i32.const 280
+  call $node_modules/@as-pect/assembly/assembly/internal/Expectation/Expectation<i32>#toBe
+  local.get $0
+  call $~lib/rt/stub/__release
+  local.get $1
+  call $~lib/rt/stub/__release
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/Test/it (; 41 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
+  local.get $0
+  call $~lib/rt/stub/__retain
+  drop
+  local.get $0
+  local.get $1
+  call $node_modules/@as-pect/assembly/assembly/internal/Test/reportTest
+  local.get $0
+  call $~lib/rt/stub/__release
+ )
+ (func $start:assembly/__tests__/example.spec~anonymous|0 (; 42 ;) (type $FUNCSIG$v)
+  i32.const 64
+  i32.const 1
+  call $node_modules/@as-pect/assembly/assembly/internal/Test/it
+ )
+ (func $start:node_modules/@as-pect/assembly/assembly/internal/noOp~anonymous|0 (; 43 ;) (type $FUNCSIG$v)
+  nop
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/Describe/describe (; 44 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
+  local.get $0
+  call $~lib/rt/stub/__retain
+  drop
+  local.get $0
+  call $node_modules/@as-pect/assembly/assembly/internal/Describe/reportDescribe
+  i32.const 0
+  global.set $~lib/argc
+  local.get $1
+  call_indirect (type $FUNCSIG$v)
+  call $node_modules/@as-pect/assembly/assembly/internal/Describe/reportEndDescribe
+  local.get $0
+  call $~lib/rt/stub/__release
+ )
+ (func $start:assembly/__tests__/example.spec (; 45 ;) (type $FUNCSIG$v)
+  i32.const 0
+  call $assembly/__tests__/example.spec/Foo#constructor
+  global.set $assembly/__tests__/example.spec/foo
+  i32.const 24
+  i32.const 2
+  call $node_modules/@as-pect/assembly/assembly/internal/Describe/describe
+ )
+ (func $assembly/__tests__/example.spec/Foo#runTwo (; 46 ;) (type $FUNCSIG$iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+  local.get $0
+  i32.load
+  local.get $1
+  i32.add
+  local.get $2
+  i32.add
+ )
+ (func $node_modules/@as-pect/assembly/assembly/index/__ready (; 47 ;) (type $FUNCSIG$v)
+  i32.const 1
+  global.set $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.ready
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/call/__call (; 48 ;) (type $FUNCSIG$vi) (param $0 i32)
+  i32.const 0
+  global.set $~lib/argc
+  local.get $0
+  call_indirect (type $FUNCSIG$v)
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/report/Actual/__sendActual (; 49 ;) (type $FUNCSIG$v)
+  (local $0 i32)
+  block $break|0
+   block $case8|0
+    block $case7|0
+     block $case6|0
+      block $case5|0
+       block $case4|0
+        block $case3|0
+         block $case2|0
+          block $case1|0
+           block $case0|0
+            global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.type
+            local.set $0
+            local.get $0
+            i32.const 0
+            i32.eq
+            br_if $case0|0
+            local.get $0
+            i32.const 6
+            i32.eq
+            br_if $case1|0
+            local.get $0
+            i32.const 2
+            i32.eq
+            br_if $case2|0
+            local.get $0
+            i32.const 3
+            i32.eq
+            br_if $case3|0
+            local.get $0
+            i32.const 1
+            i32.eq
+            br_if $case4|0
+            local.get $0
+            i32.const 4
+            i32.eq
+            br_if $case5|0
+            local.get $0
+            i32.const 5
+            i32.eq
+            br_if $case6|0
+            local.get $0
+            i32.const 10
+            i32.eq
+            br_if $case7|0
+            local.get $0
+            i32.const 11
+            i32.eq
+            br_if $case8|0
+            br $break|0
+           end
+           return
+          end
+          global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.reference
+          global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+          call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualArray
+          br $break|0
+         end
+         global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.float
+         i32.const 1
+         global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+         call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualFloat
+         br $break|0
+        end
+        global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.integer
+        global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.signed
+        global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+        call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualInteger
+        br $break|0
+       end
+       global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+       call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualNull
+       br $break|0
+      end
+      global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.reference
+      global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.offset
+      global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+      call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualReferenceExternal
+      br $break|0
+     end
+     global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.reference
+     global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+     call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualString
+     br $break|0
+    end
+    global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.reference
+    global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.signed
+    global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+    call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualLong
+    br $break|0
+   end
+   global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.integer
+   global.get $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.stackTrace
+   call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/reportActualBool
+   br $break|0
+  end
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/report/Expected/__sendExpected (; 50 ;) (type $FUNCSIG$v)
+  (local $0 i32)
+  block $break|0
+   block $case10|0
+    block $case9|0
+     block $case8|0
+      block $case7|0
+       block $case6|0
+        block $case5|0
+         block $case4|0
+          block $case3|0
+           block $case2|0
+            block $case1|0
+             block $case0|0
+              global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.type
+              local.set $0
+              local.get $0
+              i32.const 6
+              i32.eq
+              br_if $case0|0
+              local.get $0
+              i32.const 2
+              i32.eq
+              br_if $case1|0
+              local.get $0
+              i32.const 3
+              i32.eq
+              br_if $case2|0
+              local.get $0
+              i32.const 1
+              i32.eq
+              br_if $case3|0
+              local.get $0
+              i32.const 4
+              i32.eq
+              br_if $case4|0
+              local.get $0
+              i32.const 5
+              i32.eq
+              br_if $case5|0
+              local.get $0
+              i32.const 7
+              i32.eq
+              br_if $case6|0
+              local.get $0
+              i32.const 9
+              i32.eq
+              br_if $case7|0
+              local.get $0
+              i32.const 8
+              i32.eq
+              br_if $case8|0
+              local.get $0
+              i32.const 10
+              i32.eq
+              br_if $case9|0
+              local.get $0
+              i32.const 11
+              i32.eq
+              br_if $case10|0
+              br $break|0
+             end
+             global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.reference
+             global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+             global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+             call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedArray
+             br $break|0
+            end
+            global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.float
+            i32.const 1
+            global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+            global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+            call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedFloat
+            br $break|0
+           end
+           global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.integer
+           global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.signed
+           global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+           global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+           call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedInteger
+           br $break|0
+          end
+          global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+          global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+          call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedNull
+          br $break|0
+         end
+         global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.reference
+         global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.offset
+         global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+         global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+         call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedReferenceExternal
+         br $break|0
+        end
+        global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.reference
+        global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+        global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+        call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedString
+        br $break|0
+       end
+       global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+       global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+       call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedFalsy
+       br $break|0
+      end
+      global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+      global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+      call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedFinite
+      br $break|0
+     end
+     global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+     global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+     call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedTruthy
+     br $break|0
+    end
+    global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.reference
+    global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.signed
+    global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+    global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+    call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedLong
+    br $break|0
+   end
+   global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.integer
+   global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.negated
+   global.get $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.stackTrace
+   call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/reportExpectedBool
+   br $break|0
+  end
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/log/__ignoreLogs (; 51 ;) (type $FUNCSIG$vi) (param $0 i32)
+  local.get $0
+  i32.const 0
+  i32.ne
+  global.set $node_modules/@as-pect/assembly/assembly/internal/log/ignoreLogs
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/RTrace/__disableRTrace (; 52 ;) (type $FUNCSIG$v)
+  i32.const 0
+  global.set $node_modules/@as-pect/assembly/assembly/internal/RTrace/RTrace.enabled
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/RTrace/__getUsizeArrayId (; 53 ;) (type $FUNCSIG$i) (result i32)
+  i32.const 6
+ )
+ (func $node_modules/@as-pect/assembly/assembly/internal/Expectation/__cleanup (; 54 ;) (type $FUNCSIG$v)
+  call $node_modules/@as-pect/assembly/assembly/internal/report/Expected/Expected.clear
+  call $node_modules/@as-pect/assembly/assembly/internal/report/Actual/Actual.clear
+ )
+ (func $start (; 55 ;) (type $FUNCSIG$v)
+  global.get $~lib/started
+  if
+   return
+  else   
+   i32.const 1
+   global.set $~lib/started
+  end
+  global.get $~lib/heap/__heap_base
+  i32.const 15
+  i32.add
+  i32.const 15
+  i32.const -1
+  i32.xor
+  i32.and
+  global.set $~lib/rt/stub/startOffset
+  global.get $~lib/rt/stub/startOffset
+  global.set $~lib/rt/stub/offset
+  call $start:assembly/__tests__/example.spec
+ )
+ (func $null (; 56 ;) (type $FUNCSIG$v)
+ )
+ (func $Foo#get:int (; 57 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
+  local.get $0
+  i32.load
+ )
+ (func $Foo#set:int (; 58 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
+  local.get $0
+  local.get $1
+  i32.store
+ )
+ (func $Foo#get:float (; 59 ;) (type $FUNCSIG$fi) (param $0 i32) (result f32)
+  local.get $0
+  f32.load offset=4
+ )
+ (func $Foo#set:float (; 60 ;) (type $FUNCSIG$vif) (param $0 i32) (param $1 f32)
+  local.get $0
+  local.get $1
+  f32.store offset=4
+ )
+ (func $~lib/virtual/virtual (; 61 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
+  (local $2 i32)
+  block $break|0
+   block $case1|0
+    block $case0|0
+     local.get $0
+     local.set $2
+     local.get $2
+     i32.const 0
+     i32.eq
+     br_if $case0|0
+     local.get $2
+     i32.const 1
+     i32.eq
+     br_if $case1|0
+     br $break|0
+    end
+    block $break|1
+     block $case0|1
+      local.get $1
+      local.set $2
+      local.get $2
+      i32.const 3
+      i32.eq
+      br_if $case0|1
+      br $break|1
+     end
+     i32.const 5
+     return
+    end
+   end
+   block $break|2
+    block $case0|2
+     local.get $1
+     local.set $2
+     local.get $2
+     i32.const 3
+     i32.eq
+     br_if $case0|2
+     br $break|2
+    end
+    i32.const 4
+    return
+   end
+  end
+  unreachable
+ )
+ (func $start:~lib/virtual (; 62 ;) (type $FUNCSIG$v)
+  i32.const 1
+  i32.const 3
+  call $~lib/virtual/virtual
+  drop
+ )
+ (func $assembly/__tests__/example.spec/Fu#run (; 63 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32)
+  local.get $0
+  local.get $1
+  i32.const 0
+  local.get $0
+  i32.const 8
+  i32.sub
+  i32.load
+  call $~lib/virtual/virtual
+  call_indirect (type $FUNCSIG$vii)
+ )
+ (func $assembly/__tests__/example.spec/Fu#runTwo (; 64 ;) (type $FUNCSIG$iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
+  local.get $0
+  local.get $1
+  local.get $2
+  i32.const 1
+  local.get $0
+  i32.const 8
+  i32.sub
+  i32.load
+  call $~lib/virtual/virtual
+  call_indirect (type $FUNCSIG$iiii)
+ )
+)
diff --git a/lib/visitor/assembly/class.ts b/lib/visitor/assembly/class.ts
new file mode 100644
index 0000000000..b075d5a316
--- /dev/null
+++ b/lib/visitor/assembly/class.ts
@@ -0,0 +1,37 @@
+/// <reference types="../../../std/types/assembly" />
+
+export class Foo implements Fu {
+  int: i32 = 0;
+  float: f32 = 1.2;
+
+  run(i: i32): void {
+    this.int += i;
+  }
+}
+
+export class Faa extends Foo {
+  constructor(str: string, public arr: Array<i32>) {
+    super(str);
+  }
+
+  run(i: i32): void {
+    this.float += <f32>i;
+  }
+}
+
+interface Fu {
+  run(i: i32): void; 
+}
+
+let x: i32 = 25;
+// declare function virtual(methodID: usize, classID: usize): usize
+
+export function testInterface(fu: Fu): void {
+  fu.run(10);
+  // let id = load<usize>(changetype<usize>(fu)-8);
+  // let i = fu instanceof Faa;
+  // let fn: usize = virtual(0, id);
+  // let test = fn + 0;
+  // call_indirect(4, 10);
+  // fu.run(10); 
+}
diff --git a/lib/visitor/assembly/tsconfig.json b/lib/visitor/assembly/tsconfig.json
new file mode 100644
index 0000000000..8f9b277daf
--- /dev/null
+++ b/lib/visitor/assembly/tsconfig.json
@@ -0,0 +1,4 @@
+{
+  "extends": "../node_modules/assemblyscript/std/assembly.json",
+  "include": ["**/*.ts"]
+}
\ No newline at end of file
diff --git a/lib/visitor/dist/ast/base.js b/lib/visitor/dist/ast/base.js
new file mode 100644
index 0000000000..3f252bff50
--- /dev/null
+++ b/lib/visitor/dist/ast/base.js
@@ -0,0 +1,405 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var __values = (this && this.__values) || function (o) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+    if (m) return m.call(o);
+    return {
+        next: function () {
+            if (o && i >= o.length) o = void 0;
+            return { value: o && o[i++], done: !o };
+        }
+    };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var visitor_1 = require("../visitor");
+var BaseVisitor = /** @class */ (function (_super) {
+    __extends(BaseVisitor, _super);
+    function BaseVisitor(parser, writer) {
+        var _this = _super.call(this) || this;
+        _this.parser = parser;
+        _this.writer = writer;
+        _this.depth = 0;
+        return _this;
+    }
+    // /** Visits each node in an array if array exists. */
+    // visitArray(array: Node[] | null): void {
+    //   if (array) {
+    //     array.map(node => {
+    //       if (node) node.visit(this);
+    //     });
+    //   }
+    // }
+    BaseVisitor.prototype.start = function () {
+        this.visit(this.parser.program.sources);
+    };
+    BaseVisitor.prototype.visitSource = function (node) {
+        var e_1, _a;
+        try {
+            for (var _b = __values(node.statements), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var stmt = _c.value;
+                this.depth++;
+                stmt.visit(this);
+                this.depth--;
+            }
+        }
+        catch (e_1_1) { e_1 = { error: e_1_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_1) throw e_1.error; }
+        }
+    };
+    BaseVisitor.prototype.visitTypeNode = function (node) { };
+    BaseVisitor.prototype.visitTypeName = function (node) {
+        node.identifier.visit(this);
+        if (node.next) {
+            node.visit(this);
+        }
+    };
+    BaseVisitor.prototype.visitNamedTypeNode = function (node) {
+        this.visit(node.name);
+        this.visit(node.typeArguments);
+    };
+    BaseVisitor.prototype.visitFunctionTypeNode = function (node) {
+        var e_2, _a;
+        try {
+            for (var _b = __values(node.parameters), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var param = _c.value;
+                param.visit(this);
+            }
+        }
+        catch (e_2_1) { e_2 = { error: e_2_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_2) throw e_2.error; }
+        }
+        node.returnType.visit(this);
+    };
+    BaseVisitor.prototype.visitTypeParameter = function (node) {
+        node.name.visit(this);
+        if (node.extendsType)
+            node.extendsType.visit(this);
+        if (node.defaultType)
+            node.defaultType.visit(this);
+    };
+    BaseVisitor.prototype.visitIdentifierExpression = function (node) { };
+    BaseVisitor.prototype.visitArrayLiteralExpression = function (node) {
+        var _this = this;
+        node.elementExpressions.map(function (e) {
+            if (e)
+                e.visit(_this);
+        });
+    };
+    BaseVisitor.prototype.visitObjectLiteralExpression = function (node) {
+        if (node.values && node.names) {
+            assert(node.values.length == node.names.length);
+            for (var i = 0; i < node.values.length; i++) {
+                node.names[i].visit(this);
+                node.values[i].visit(this);
+            }
+        }
+    };
+    BaseVisitor.prototype.visitAssertionExpression = function (node) {
+        if (node.toType)
+            node.toType.visit(this);
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitBinaryExpression = function (node) {
+        node.left.visit(this);
+        node.right.visit(this);
+    };
+    BaseVisitor.prototype.visitCallExpression = function (node) {
+        node.expression.visit(this);
+        this.visit(node.typeArguments);
+        this.visit(node.arguments);
+    };
+    BaseVisitor.prototype.visitClassExpression = function (node) {
+        node.declaration.visit(this);
+    };
+    BaseVisitor.prototype.visitCommaExpression = function (node) {
+        this.visit(node.expressions);
+    };
+    BaseVisitor.prototype.visitElementAccessExpression = function (node) {
+        node.elementExpression.visit(this);
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitFunctionExpression = function (node) {
+        node.declaration.visit(this);
+    };
+    BaseVisitor.prototype.visitLiteralExpression = function (node) {
+        // node.
+    };
+    BaseVisitor.prototype.visitFloatLiteralExpression = function (node) { };
+    BaseVisitor.prototype.visitInstanceOfExpression = function (node) {
+        node.expression.visit(this);
+        node.isType.visit(this);
+    };
+    BaseVisitor.prototype.visitIntegerLiteralExpression = function (node) { };
+    BaseVisitor.prototype.visitStringLiteral = function (str, singleQuoted) { };
+    BaseVisitor.prototype.visitStringLiteralExpression = function (node) { };
+    BaseVisitor.prototype.visitRegexpLiteralExpression = function (node) { };
+    BaseVisitor.prototype.visitNewExpression = function (node) {
+        node.expression.visit(this);
+        this.visit(node.typeArguments);
+        this.visit(node.arguments);
+    };
+    BaseVisitor.prototype.visitParenthesizedExpression = function (node) {
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitPropertyAccessExpression = function (node) {
+        node.property.visit(this);
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitTernaryExpression = function (node) {
+        node.condition.visit(this);
+        node.ifThen.visit(this);
+        node.ifElse.visit(this);
+    };
+    BaseVisitor.prototype.visitUnaryExpression = function (node) {
+        node.operand.visit(this);
+    };
+    BaseVisitor.prototype.visitUnaryPostfixExpression = function (node) {
+        node.operand.visit(this);
+    };
+    BaseVisitor.prototype.visitUnaryPrefixExpression = function (node) {
+        node.operand.visit(this);
+    };
+    BaseVisitor.prototype.visitSuperExpression = function (node) { };
+    BaseVisitor.prototype.visitFalseExpression = function (node) { };
+    BaseVisitor.prototype.visitTrueExpression = function (node) { };
+    BaseVisitor.prototype.visitThisExpression = function (node) { };
+    BaseVisitor.prototype.visitNullExperssion = function (node) { };
+    BaseVisitor.prototype.visitConstructorExpression = function (node) { };
+    BaseVisitor.prototype.visitNodeAndTerminate = function (statement) { };
+    BaseVisitor.prototype.visitBlockStatement = function (node) {
+        this.depth++;
+        this.visit(node.statements);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitBreakStatement = function (node) {
+        if (node.label) {
+            node.label.visit(this);
+        }
+    };
+    BaseVisitor.prototype.visitContinueStatement = function (node) {
+        if (node.label) {
+            node.label.visit(this);
+        }
+    };
+    BaseVisitor.prototype.visitClassDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        this.depth++;
+        this.visit(node.decorators);
+        assert(node.isGeneric ? node.typeParameters != null : node.typeParameters == null);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+        }
+        if (node.extendsType) {
+            node.extendsType.visit(this);
+        }
+        this.visit(node.implementsTypes);
+        this.visit(node.members);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitDoStatement = function (node) {
+        node.condition.visit(this);
+        node.statement.visit(this);
+    };
+    BaseVisitor.prototype.visitEmptyStatement = function (node) { };
+    BaseVisitor.prototype.visitEnumDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        this.visit(node.decorators);
+        this.visit(node.values);
+    };
+    BaseVisitor.prototype.visitEnumValueDeclaration = function (node) {
+        node.name.visit(this);
+        if (node.initializer) {
+            node.initializer.visit(this);
+        }
+    };
+    BaseVisitor.prototype.visitExportImportStatement = function (node) {
+        node.name.visit(this);
+        node.externalName.visit(this);
+    };
+    BaseVisitor.prototype.visitExportMember = function (node) {
+        node.localName.visit(this);
+        node.exportedName.visit(this);
+    };
+    BaseVisitor.prototype.visitExportStatement = function (node) {
+        if (node.path) {
+            node.path.visit(this);
+        }
+        this.visit(node.members);
+    };
+    BaseVisitor.prototype.visitExportDefaultStatement = function (node) {
+        node.declaration.visit(this);
+    };
+    BaseVisitor.prototype.visitExpressionStatement = function (node) {
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitFieldDeclaration = function (node) {
+        node.name.visit(this);
+        if (node.type) {
+            node.type.visit(this);
+        }
+        if (node.initializer) {
+            node.initializer.visit(this);
+        }
+        this.visit(node.decorators);
+    };
+    BaseVisitor.prototype.visitForStatement = function (node) {
+        if (node.initializer)
+            node.initializer.visit(this);
+        if (node.condition)
+            node.condition.visit(this);
+        if (node.incrementor)
+            node.incrementor.visit(this);
+        node.statement.visit(this);
+    };
+    BaseVisitor.prototype.visitFunctionDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        this.visit(node.decorators);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+        }
+        node.signature.visit(this);
+        this.depth++;
+        if (node.body)
+            node.body.visit(this);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitFunctionCommon = function (node) {
+        // node.name.visit(this)
+    };
+    BaseVisitor.prototype.visitIfStatement = function (node) {
+        node.condition.visit(this);
+        node.ifTrue.visit(this);
+        if (node.ifFalse)
+            node.ifFalse.visit(this);
+    };
+    BaseVisitor.prototype.visitImportDeclaration = function (node) {
+        node.foreignName.visit(this);
+        node.name.visit(this);
+        this.visit(node.decorators);
+    };
+    BaseVisitor.prototype.visitImportStatement = function (node) {
+        if (node.namespaceName)
+            node.namespaceName.visit(this);
+        this.visit(node.declarations);
+    };
+    BaseVisitor.prototype.visitIndexSignatureDeclaration = function (node) {
+        // node.name.visit(this);
+        // node.keyType.visit(this);
+        // node.valueType.visit(this);
+    };
+    BaseVisitor.prototype.visitInterfaceDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+        }
+        this.visit(node.implementsTypes);
+        if (node.extendsType)
+            node.extendsType.visit(this);
+        this.depth++;
+        this.visit(node.members);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitMethodDeclaration = function (node) {
+        node.name.visit(this);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+        }
+        node.signature.visit(this);
+        this.visit(node.decorators);
+        this.depth++;
+        if (node.body)
+            node.body.visit(this);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitNamespaceDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        this.visit(node.decorators);
+        this.visit(node.members);
+    };
+    BaseVisitor.prototype.visitReturnStatement = function (node) {
+        if (node.value)
+            node.value.visit(this);
+    };
+    BaseVisitor.prototype.visitSwitchCase = function (node) {
+        if (node.label)
+            node.label.visit(this);
+        this.visit(node.statements);
+    };
+    BaseVisitor.prototype.visitSwitchStatement = function (node) {
+        node.condition.visit(this);
+        this.depth++;
+        this.visit(node.cases);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitThrowStatement = function (node) {
+        node.value.visit(this);
+    };
+    BaseVisitor.prototype.visitTryStatement = function (node) {
+        this.visit(node.statements);
+        if (node.catchVariable)
+            node.catchVariable.visit(this);
+        this.visit(node.catchStatements);
+        this.visit(node.finallyStatements);
+    };
+    BaseVisitor.prototype.visitTypeDeclaration = function (node) {
+        node.name.visit(this);
+        this.visit(node.decorators);
+        node.type.visit(this);
+        this.visit(node.typeParameters);
+    };
+    BaseVisitor.prototype.visitVariableDeclaration = function (node) {
+        node.name.visit(this);
+        if (node.type)
+            node.type.visit(this);
+        if (node.initializer)
+            node.initializer.visit(this);
+    };
+    BaseVisitor.prototype.visitVariableStatement = function (node) {
+        this.visit(node.decorators);
+        this.visit(node.declarations);
+    };
+    BaseVisitor.prototype.visitWhileStatement = function (node) {
+        node.condition.visit(this);
+        this.depth++;
+        node.statement.visit(this);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitVoidStatement = function (node) { };
+    BaseVisitor.prototype.visitComment = function (node) { };
+    BaseVisitor.prototype.visitDecoratorNode = function (node) {
+        node.name.visit(this);
+        this.visit(node.arguments);
+    };
+    BaseVisitor.prototype.visitParameter = function (node) {
+        node.name.visit(this);
+        if (node.implicitFieldDeclaration) {
+            node.implicitFieldDeclaration.visit(this);
+        }
+        if (node.initializer)
+            node.initializer.visit(this);
+        node.type.visit(this);
+    };
+    return BaseVisitor;
+}(visitor_1.AbstractVisitor));
+exports.BaseVisitor = BaseVisitor;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hc3QvYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNkVBLHNDQUE2QztBQUk3QztJQUFpQywrQkFBcUI7SUFHcEQscUJBQXNCLE1BQWMsRUFBWSxNQUFjO1FBQTlELFlBQ0UsaUJBQU8sU0FDUjtRQUZxQixZQUFNLEdBQU4sTUFBTSxDQUFRO1FBQVksWUFBTSxHQUFOLE1BQU0sQ0FBUTtRQUY5RCxXQUFLLEdBQVcsQ0FBQyxDQUFDOztJQUlsQixDQUFDO0lBRUQsdURBQXVEO0lBQ3ZELDJDQUEyQztJQUMzQyxpQkFBaUI7SUFDakIsMEJBQTBCO0lBQzFCLG9DQUFvQztJQUNwQyxVQUFVO0lBQ1YsTUFBTTtJQUNOLElBQUk7SUFFSiwyQkFBSyxHQUFMO1FBQ0UsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQsaUNBQVcsR0FBWCxVQUFZLElBQVk7OztZQUN0QixLQUFtQixJQUFBLEtBQUEsU0FBQSxJQUFJLENBQUMsVUFBVSxDQUFBLGdCQUFBLDRCQUFFO2dCQUEvQixJQUFNLElBQUksV0FBQTtnQkFDYixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDakIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQ2Q7Ozs7Ozs7OztJQUNILENBQUM7SUFFRCxtQ0FBYSxHQUFiLFVBQWMsSUFBYyxJQUFTLENBQUM7SUFFdEMsbUNBQWEsR0FBYixVQUFjLElBQWM7UUFDMUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUIsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ2IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJ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Q0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3RCLElBQUksSUFBSSxDQUFDLHdCQUF3QixFQUFFO1lBQ2pDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDM0M7UUFDRCxJQUFJLElBQUksQ0FBQyxXQUFXO1lBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkQsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUNILGtCQUFDO0FBQUQsQ0FBQyxBQWxhRCxDQUFpQyx5QkFBZSxHQWthL0M7QUFsYVksa0NBQVciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBTb3VyY2UsXG4gIFR5cGVOb2RlLFxuICBUeXBlTmFtZSxcbiAgTmFtZWRUeXBlTm9kZSxcbiAgRnVuY3Rpb25UeXBlTm9kZSxcbiAgVHlwZVBhcmFtZXRlck5vZGUsXG4gIElkZW50aWZpZXJFeHByZXNzaW9uLFxuICBBcnJheUxpdGVyYWxFeHByZXNzaW9uLFxuICBPYmplY3RMaXRlcmFsRXhwcmVzc2lvbixcbiAgQXNzZXJ0aW9uRXhwcmVzc2lvbixcbiAgQmluYXJ5RXhwcmVzc2lvbixcbiAgQ2FsbEV4cHJlc3Npb24sXG4gIENsYXNzRXhwcmVzc2lvbixcbiAgQ29tbWFFeHByZXNzaW9uLFxuICBFbGVtZW50QWNjZXNzRXhwcmVzc2lvbixcbiAgRnVuY3Rpb25FeHByZXNzaW9uLFxuICBMaXRlcmFsRXhwcmVzc2lvbixcbiAgRmxvYXRMaXRlcmFsRXhwcmVzc2lvbixcbiAgSW5zdGFuY2VPZkV4cHJlc3Npb24sXG4gIEludGVnZXJMaXRlcmFsRXhwcmVzc2lvbixcbiAgU3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24sXG4gIFJlZ2V4cExpdGVyYWxFeHByZXNzaW9uLFxuICBOZXdFeHByZXNzaW9uLFxuICBQYXJlbnRoZXNpemVkRXhwcmVzc2lvbixcbiAgUHJvcGVydHlBY2Nlc3NFeHByZXNzaW9uLFxuICBUZXJuYXJ5RXhwcmVzc2lvbixcbiAgVW5hcnlFeHByZXNzaW9uLFxuICBVbmFyeVBvc3RmaXhFeHByZXNzaW9uLFxuICBVbmFyeVByZWZpeEV4cHJlc3Npb24sXG4gIFN1cGVyRXhwcmVzc2lvbixcbiAgRmFsc2VFeHByZXNzaW9uLFxuICBUcnVlRXhwcmVzc2lvbixcbiAgVGhpc0V4cHJlc3Npb24sXG4gIE51bGxFeHByZXNzaW9uLFxuICBDb25zdHJ1Y3RvckV4cHJlc3Npb24sXG4gIFN0YXRlbWVudCxcbiAgQmxvY2tTdGF0ZW1lbnQsXG4gIEJyZWFrU3RhdGVtZW50LFxuICBDb250aW51ZVN0YXRlbWVudCxcbiAgQ2xhc3NEZWNsYXJhdGlvbixcbiAgRG9TdGF0ZW1lbnQsXG4gIEVtcHR5U3RhdGVtZW50LFxuICBFbnVtRGVjbGFyYXRpb24sXG4gIEVudW1WYWx1ZURlY2xhcmF0aW9uLFxuICBFeHBvcnRJbXBvcnRTdGF0ZW1lbnQsXG4gIEV4cG9ydE1lbWJlcixcbiAgRXhwb3J0U3RhdGVtZW50LFxuICBFeHBvcnREZWZhdWx0U3RhdGVtZW50LFxuICBFeHByZXNzaW9uU3RhdGVtZW50LFxuICBGaWVsZERlY2xhcmF0aW9uLFxuICBGb3JTdGF0ZW1lbnQsXG4gIEZ1bmN0aW9uRGVjbGFyYXRpb24sXG4gIElmU3RhdGVtZW50LFxuICBJbXBvcnREZWNsYXJhdGlvbixcbiAgSW1wb3J0U3RhdGVtZW50LFxuICBJbmRleFNpZ25hdHVyZURlY2xhcmF0aW9uLFxuICBJbnRlcmZhY2VEZWNsYXJhdGlvbixcbiAgTWV0aG9kRGVjbGFyYXRpb24sXG4gIE5hbWVzcGFjZURlY2xhcmF0aW9uLFxuICBSZXR1cm5TdGF0ZW1lbnQsXG4gIFN3aXRjaENhc2UsXG4gIFN3aXRjaFN0YXRlbWVudCxcbiAgVGhyb3dTdGF0ZW1lbnQsXG4gIFRyeVN0YXRlbWVudCxcbiAgVHlwZURlY2xhcmF0aW9uLFxuICBWYXJpYWJsZURlY2xhcmF0aW9uLFxuICBWYXJpYWJsZVN0YXRlbWVudCxcbiAgV2hpbGVTdGF0ZW1lbnQsXG4gIFZvaWRTdGF0ZW1lbnQsXG4gIENvbW1lbnROb2RlLFxuICBEZWNvcmF0b3JOb2RlLFxuICBQYXJhbWV0ZXJOb2RlLFxuICBOb2RlLFxuICBQYXJzZXJcbn0gZnJvbSBcImFzc2VtYmx5c2NyaXB0XCI7XG5cbmltcG9ydCB7IEFic3RyYWN0VmlzaXRvciB9IGZyb20gXCIuLi92aXNpdG9yXCI7XG5pbXBvcnQgeyBBU1RWaXNpdG9yIH0gZnJvbSBcIi5cIjtcbmltcG9ydCB7IFdyaXRlciB9IGZyb20gXCIuLlwiO1xuXG5leHBvcnQgY2xhc3MgQmFzZVZpc2l0b3IgZXh0ZW5kcyBBYnN0cmFjdFZpc2l0b3I8Tm9kZT4gaW1wbGVtZW50cyBBU1RWaXNpdG9yIHtcbiAgZGVwdGg6IG51bWJlciA9IDA7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIHBhcnNlcjogUGFyc2VyLCBwcm90ZWN0ZWQgd3JpdGVyOiBXcml0ZXIpIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgLy8gLyoqIFZpc2l0cyBlYWNoIG5vZGUgaW4gYW4gYXJyYXkgaWYgYXJyYXkgZXhpc3RzLiAqL1xuICAvLyB2aXNpdEFycmF5KGFycmF5OiBOb2RlW10gfCBudWxsKTogdm9pZCB7XG4gIC8vICAgaWYgKGFycmF5KSB7XG4gIC8vICAgICBhcnJheS5tYXAobm9kZSA9PiB7XG4gIC8vICAgICAgIGlmIChub2RlKSBub2RlLnZpc2l0KHRoaXMpO1xuICAvLyAgICAgfSk7XG4gIC8vICAgfVxuICAvLyB9XG5cbiAgc3RhcnQoKTogdm9pZCB7XG4gICAgdGhpcy52aXNpdCh0aGlzLnBhcnNlci5wcm9ncmFtLnNvdXJjZXMpO1xuICB9XG5cbiAgdmlzaXRTb3VyY2Uobm9kZTogU291cmNlKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBzdG10IG9mIG5vZGUuc3RhdGVtZW50cykge1xuICAgICAgdGhpcy5kZXB0aCsrO1xuICAgICAgc3RtdC52aXNpdCh0aGlzKTtcbiAgICAgIHRoaXMuZGVwdGgtLTtcbiAgICB9XG4gIH1cblxuICB2aXNpdFR5cGVOb2RlKG5vZGU6IFR5cGVOb2RlKTogdm9pZCB7fVxuXG4gIHZpc2l0VHlwZU5hbWUobm9kZTogVHlwZU5hbWUpOiB2b2lkIHtcbiAgICBub2RlLmlkZW50aWZpZXIudmlzaXQodGhpcyk7XG4gICAgaWYgKG5vZGUubmV4dCkge1xuICAgICAgbm9kZS52aXNpdCh0aGlzKTtcbiAgICB9XG4gIH1cblxuICB2aXNpdE5hbWVkVHlwZU5vZGUobm9kZTogTmFtZWRUeXBlTm9kZSk6IHZvaWQge1xuICAgIHRoaXMudmlzaXQobm9kZS5uYW1lKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUudHlwZUFyZ3VtZW50cyk7XG4gIH1cblxuICB2aXNpdEZ1bmN0aW9uVHlwZU5vZGUobm9kZTogRnVuY3Rpb25UeXBlTm9kZSk6IHZvaWQge1xuICAgIGZvciAobGV0IHBhcmFtIG9mIG5vZGUucGFyYW1ldGVycykge1xuICAgICAgcGFyYW0udmlzaXQodGhpcyk7XG4gICAgfVxuICAgIG5vZGUucmV0dXJuVHlwZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0VHlwZVBhcmFtZXRlcihub2RlOiBUeXBlUGFyYW1ldGVyTm9kZSk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICBpZiAobm9kZS5leHRlbmRzVHlwZSkgbm9kZS5leHRlbmRzVHlwZS52aXNpdCh0aGlzKTtcbiAgICBpZiAobm9kZS5kZWZhdWx0VHlwZSkgbm9kZS5kZWZhdWx0VHlwZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0SWRlbnRpZmllckV4cHJlc3Npb24obm9kZTogSWRlbnRpZmllckV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRBcnJheUxpdGVyYWxFeHByZXNzaW9uKG5vZGU6IEFycmF5TGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLmVsZW1lbnRFeHByZXNzaW9ucy5tYXAoZSA9PiB7XG4gICAgICBpZiAoZSkgZS52aXNpdCh0aGlzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHZpc2l0T2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24obm9kZTogT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBpZiAobm9kZS52YWx1ZXMgJiYgbm9kZS5uYW1lcykge1xuICAgICAgYXNzZXJ0KG5vZGUudmFsdWVzLmxlbmd0aCA9PSBub2RlLm5hbWVzLmxlbmd0aCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG5vZGUubmFtZXNbaV0udmlzaXQodGhpcyk7XG4gICAgICAgIG5vZGUudmFsdWVzW2ldLnZpc2l0KHRoaXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZpc2l0QXNzZXJ0aW9uRXhwcmVzc2lvbihub2RlOiBBc3NlcnRpb25FeHByZXNzaW9uKTogdm9pZCB7XG4gICAgaWYgKG5vZGUudG9UeXBlKSBub2RlLnRvVHlwZS52aXNpdCh0aGlzKTtcbiAgICBub2RlLmV4cHJlc3Npb24udmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEJpbmFyeUV4cHJlc3Npb24obm9kZTogQmluYXJ5RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUubGVmdC52aXNpdCh0aGlzKTtcbiAgICBub2RlLnJpZ2h0LnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRDYWxsRXhwcmVzc2lvbihub2RlOiBDYWxsRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUuZXhwcmVzc2lvbi52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUudHlwZUFyZ3VtZW50cyk7XG4gICAgdGhpcy52aXNpdChub2RlLmFyZ3VtZW50cyk7XG4gIH1cblxuICB2aXNpdENsYXNzRXhwcmVzc2lvbihub2RlOiBDbGFzc0V4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLmRlY2xhcmF0aW9uLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRDb21tYUV4cHJlc3Npb24obm9kZTogQ29tbWFFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy52aXNpdChub2RlLmV4cHJlc3Npb25zKTtcbiAgfVxuXG4gIHZpc2l0RWxlbWVudEFjY2Vzc0V4cHJlc3Npb24obm9kZTogRWxlbWVudEFjY2Vzc0V4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLmVsZW1lbnRFeHByZXNzaW9uLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUuZXhwcmVzc2lvbi52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0RnVuY3Rpb25FeHByZXNzaW9uKG5vZGU6IEZ1bmN0aW9uRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUuZGVjbGFyYXRpb24udmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdExpdGVyYWxFeHByZXNzaW9uKG5vZGU6IExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgLy8gbm9kZS5cbiAgfVxuXG4gIHZpc2l0RmxvYXRMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBGbG9hdExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7fVxuXG4gIHZpc2l0SW5zdGFuY2VPZkV4cHJlc3Npb24obm9kZTogSW5zdGFuY2VPZkV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLmV4cHJlc3Npb24udmlzaXQodGhpcyk7XG4gICAgbm9kZS5pc1R5cGUudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEludGVnZXJMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBJbnRlZ2VyTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRTdHJpbmdMaXRlcmFsKHN0cjogc3RyaW5nLCBzaW5nbGVRdW90ZWQ/OiBib29sZWFuKTogdm9pZCB7fVxuXG4gIHZpc2l0U3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogU3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRSZWdleHBMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBSZWdleHBMaXRlcmFsRXhwcmVzc2lvbik6IHZvaWQge31cblxuICB2aXNpdE5ld0V4cHJlc3Npb24obm9kZTogTmV3RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUuZXhwcmVzc2lvbi52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUudHlwZUFyZ3VtZW50cyk7XG4gICAgdGhpcy52aXNpdChub2RlLmFyZ3VtZW50cyk7XG4gIH1cblxuICB2aXNpdFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uKG5vZGU6IFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgbm9kZS5leHByZXNzaW9uLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24obm9kZTogUHJvcGVydHlBY2Nlc3NFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgbm9kZS5wcm9wZXJ0eS52aXNpdCh0aGlzKTtcbiAgICBub2RlLmV4cHJlc3Npb24udmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdFRlcm5hcnlFeHByZXNzaW9uKG5vZGU6IFRlcm5hcnlFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgbm9kZS5jb25kaXRpb24udmlzaXQodGhpcyk7XG4gICAgbm9kZS5pZlRoZW4udmlzaXQodGhpcyk7XG4gICAgbm9kZS5pZkVsc2UudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdFVuYXJ5RXhwcmVzc2lvbihub2RlOiBVbmFyeUV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLm9wZXJhbmQudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdFVuYXJ5UG9zdGZpeEV4cHJlc3Npb24obm9kZTogVW5hcnlQb3N0Zml4RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUub3BlcmFuZC52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0VW5hcnlQcmVmaXhFeHByZXNzaW9uKG5vZGU6IFVuYXJ5UHJlZml4RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUub3BlcmFuZC52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0U3VwZXJFeHByZXNzaW9uKG5vZGU6IFN1cGVyRXhwcmVzc2lvbik6IHZvaWQge31cblxuICB2aXNpdEZhbHNlRXhwcmVzc2lvbihub2RlOiBGYWxzZUV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRUcnVlRXhwcmVzc2lvbihub2RlOiBUcnVlRXhwcmVzc2lvbik6IHZvaWQge31cblxuICB2aXNpdFRoaXNFeHByZXNzaW9uKG5vZGU6IFRoaXNFeHByZXNzaW9uKTogdm9pZCB7fVxuXG4gIHZpc2l0TnVsbEV4cGVyc3Npb24obm9kZTogTnVsbEV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRDb25zdHJ1Y3RvckV4cHJlc3Npb24obm9kZTogQ29uc3RydWN0b3JFeHByZXNzaW9uKTogdm9pZCB7fVxuXG4gIHZpc2l0Tm9kZUFuZFRlcm1pbmF0ZShzdGF0ZW1lbnQ6IFN0YXRlbWVudCk6IHZvaWQge31cblxuICB2aXNpdEJsb2NrU3RhdGVtZW50KG5vZGU6IEJsb2NrU3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5kZXB0aCsrO1xuICAgIHRoaXMudmlzaXQobm9kZS5zdGF0ZW1lbnRzKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cblxuICB2aXNpdEJyZWFrU3RhdGVtZW50KG5vZGU6IEJyZWFrU3RhdGVtZW50KTogdm9pZCB7XG4gICAgaWYgKG5vZGUubGFiZWwpIHtcbiAgICAgIG5vZGUubGFiZWwudmlzaXQodGhpcyk7XG4gICAgfVxuICB9XG5cbiAgdmlzaXRDb250aW51ZVN0YXRlbWVudChub2RlOiBDb250aW51ZVN0YXRlbWVudCk6IHZvaWQge1xuICAgIGlmIChub2RlLmxhYmVsKSB7XG4gICAgICBub2RlLmxhYmVsLnZpc2l0KHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHZpc2l0Q2xhc3NEZWNsYXJhdGlvbihub2RlOiBDbGFzc0RlY2xhcmF0aW9uLCBpc0RlZmF1bHQ/OiBib29sZWFuKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIHRoaXMuZGVwdGgrKztcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgYXNzZXJ0KFxuICAgICAgbm9kZS5pc0dlbmVyaWMgPyBub2RlLnR5cGVQYXJhbWV0ZXJzICE9IG51bGwgOiBub2RlLnR5cGVQYXJhbWV0ZXJzID09IG51bGxcbiAgICApO1xuICAgIGlmIChub2RlLmlzR2VuZXJpYykge1xuICAgICAgdGhpcy52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJzKTtcbiAgICB9XG4gICAgaWYgKG5vZGUuZXh0ZW5kc1R5cGUpIHtcbiAgICAgIG5vZGUuZXh0ZW5kc1R5cGUudmlzaXQodGhpcyk7XG4gICAgfVxuICAgIHRoaXMudmlzaXQobm9kZS5pbXBsZW1lbnRzVHlwZXMpO1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cblxuICB2aXNpdERvU3RhdGVtZW50KG5vZGU6IERvU3RhdGVtZW50KTogdm9pZCB7XG4gICAgbm9kZS5jb25kaXRpb24udmlzaXQodGhpcyk7XG4gICAgbm9kZS5zdGF0ZW1lbnQudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEVtcHR5U3RhdGVtZW50KG5vZGU6IEVtcHR5U3RhdGVtZW50KTogdm9pZCB7fVxuXG4gIHZpc2l0RW51bURlY2xhcmF0aW9uKG5vZGU6IEVudW1EZWNsYXJhdGlvbiwgaXNEZWZhdWx0PzogYm9vbGVhbik6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgdGhpcy52aXNpdChub2RlLnZhbHVlcyk7XG4gIH1cblxuICB2aXNpdEVudW1WYWx1ZURlY2xhcmF0aW9uKG5vZGU6IEVudW1WYWx1ZURlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmluaXRpYWxpemVyKSB7XG4gICAgICBub2RlLmluaXRpYWxpemVyLnZpc2l0KHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHZpc2l0RXhwb3J0SW1wb3J0U3RhdGVtZW50KG5vZGU6IEV4cG9ydEltcG9ydFN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICBub2RlLmV4dGVybmFsTmFtZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0RXhwb3J0TWVtYmVyKG5vZGU6IEV4cG9ydE1lbWJlcik6IHZvaWQge1xuICAgIG5vZGUubG9jYWxOYW1lLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUuZXhwb3J0ZWROYW1lLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRFeHBvcnRTdGF0ZW1lbnQobm9kZTogRXhwb3J0U3RhdGVtZW50KTogdm9pZCB7XG4gICAgaWYgKG5vZGUucGF0aCkge1xuICAgICAgbm9kZS5wYXRoLnZpc2l0KHRoaXMpO1xuICAgIH1cbiAgICB0aGlzLnZpc2l0KG5vZGUubWVtYmVycyk7XG4gIH1cblxuICB2aXNpdEV4cG9ydERlZmF1bHRTdGF0ZW1lbnQobm9kZTogRXhwb3J0RGVmYXVsdFN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUuZGVjbGFyYXRpb24udmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEV4cHJlc3Npb25TdGF0ZW1lbnQobm9kZTogRXhwcmVzc2lvblN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUuZXhwcmVzc2lvbi52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0RmllbGREZWNsYXJhdGlvbihub2RlOiBGaWVsZERlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLnR5cGUpIHtcbiAgICAgIG5vZGUudHlwZS52aXNpdCh0aGlzKTtcbiAgICB9XG4gICAgaWYgKG5vZGUuaW5pdGlhbGl6ZXIpIHtcbiAgICAgIG5vZGUuaW5pdGlhbGl6ZXIudmlzaXQodGhpcyk7XG4gICAgfVxuICAgIHRoaXMudmlzaXQobm9kZS5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIHZpc2l0Rm9yU3RhdGVtZW50KG5vZGU6IEZvclN0YXRlbWVudCk6IHZvaWQge1xuICAgIGlmIChub2RlLmluaXRpYWxpemVyKSBub2RlLmluaXRpYWxpemVyLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmNvbmRpdGlvbikgbm9kZS5jb25kaXRpb24udmlzaXQodGhpcyk7XG4gICAgaWYgKG5vZGUuaW5jcmVtZW50b3IpIG5vZGUuaW5jcmVtZW50b3IudmlzaXQodGhpcyk7XG4gICAgbm9kZS5zdGF0ZW1lbnQudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEZ1bmN0aW9uRGVjbGFyYXRpb24oXG4gICAgbm9kZTogRnVuY3Rpb25EZWNsYXJhdGlvbixcbiAgICBpc0RlZmF1bHQ/OiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgaWYgKG5vZGUuaXNHZW5lcmljKSB7XG4gICAgICB0aGlzLnZpc2l0KG5vZGUudHlwZVBhcmFtZXRlcnMpO1xuICAgIH1cbiAgICBub2RlLnNpZ25hdHVyZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLmRlcHRoKys7XG4gICAgaWYgKG5vZGUuYm9keSkgbm9kZS5ib2R5LnZpc2l0KHRoaXMpO1xuICAgIHRoaXMuZGVwdGgtLTtcbiAgfVxuXG4gIHZpc2l0RnVuY3Rpb25Db21tb24obm9kZTogRnVuY3Rpb25EZWNsYXJhdGlvbik6IHZvaWQge1xuICAgIC8vIG5vZGUubmFtZS52aXNpdCh0aGlzKVxuICB9XG5cbiAgdmlzaXRJZlN0YXRlbWVudChub2RlOiBJZlN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUuY29uZGl0aW9uLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUuaWZUcnVlLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmlmRmFsc2UpIG5vZGUuaWZGYWxzZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0SW1wb3J0RGVjbGFyYXRpb24obm9kZTogSW1wb3J0RGVjbGFyYXRpb24pOiB2b2lkIHtcbiAgICBub2RlLmZvcmVpZ25OYW1lLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gIH1cblxuICB2aXNpdEltcG9ydFN0YXRlbWVudChub2RlOiBJbXBvcnRTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICBpZiAobm9kZS5uYW1lc3BhY2VOYW1lKSBub2RlLm5hbWVzcGFjZU5hbWUudmlzaXQodGhpcyk7XG4gICAgdGhpcy52aXNpdChub2RlLmRlY2xhcmF0aW9ucyk7XG4gIH1cblxuICB2aXNpdEluZGV4U2lnbmF0dXJlRGVjbGFyYXRpb24obm9kZTogSW5kZXhTaWduYXR1cmVEZWNsYXJhdGlvbik6IHZvaWQge1xuICAgIC8vIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICAvLyBub2RlLmtleVR5cGUudmlzaXQodGhpcyk7XG4gICAgLy8gbm9kZS52YWx1ZVR5cGUudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEludGVyZmFjZURlY2xhcmF0aW9uKFxuICAgIG5vZGU6IEludGVyZmFjZURlY2xhcmF0aW9uLFxuICAgIGlzRGVmYXVsdD86IGJvb2xlYW5cbiAgKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmlzR2VuZXJpYykge1xuICAgICAgdGhpcy52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJzKTtcbiAgICB9XG4gICAgdGhpcy52aXNpdChub2RlLmltcGxlbWVudHNUeXBlcyk7XG4gICAgaWYgKG5vZGUuZXh0ZW5kc1R5cGUpIG5vZGUuZXh0ZW5kc1R5cGUudmlzaXQodGhpcyk7XG4gICAgdGhpcy5kZXB0aCsrO1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cblxuICB2aXNpdE1ldGhvZERlY2xhcmF0aW9uKG5vZGU6IE1ldGhvZERlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmlzR2VuZXJpYykge1xuICAgICAgdGhpcy52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJzKTtcbiAgICB9XG4gICAgbm9kZS5zaWduYXR1cmUudmlzaXQodGhpcyk7XG4gICAgdGhpcy52aXNpdChub2RlLmRlY29yYXRvcnMpO1xuICAgIHRoaXMuZGVwdGgrKztcbiAgICBpZiAobm9kZS5ib2R5KSBub2RlLmJvZHkudmlzaXQodGhpcyk7XG4gICAgdGhpcy5kZXB0aC0tO1xuICB9XG5cbiAgdmlzaXROYW1lc3BhY2VEZWNsYXJhdGlvbihcbiAgICBub2RlOiBOYW1lc3BhY2VEZWNsYXJhdGlvbixcbiAgICBpc0RlZmF1bHQ/OiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgdGhpcy52aXNpdChub2RlLm1lbWJlcnMpO1xuICB9XG5cbiAgdmlzaXRSZXR1cm5TdGF0ZW1lbnQobm9kZTogUmV0dXJuU3RhdGVtZW50KTogdm9pZCB7XG4gICAgaWYgKG5vZGUudmFsdWUpIG5vZGUudmFsdWUudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdFN3aXRjaENhc2Uobm9kZTogU3dpdGNoQ2FzZSk6IHZvaWQge1xuICAgIGlmIChub2RlLmxhYmVsKSBub2RlLmxhYmVsLnZpc2l0KHRoaXMpO1xuICAgIHRoaXMudmlzaXQobm9kZS5zdGF0ZW1lbnRzKTtcbiAgfVxuXG4gIHZpc2l0U3dpdGNoU3RhdGVtZW50KG5vZGU6IFN3aXRjaFN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUuY29uZGl0aW9uLnZpc2l0KHRoaXMpO1xuICAgIHRoaXMuZGVwdGgrKztcbiAgICB0aGlzLnZpc2l0KG5vZGUuY2FzZXMpO1xuICAgIHRoaXMuZGVwdGgtLTtcbiAgfVxuXG4gIHZpc2l0VGhyb3dTdGF0ZW1lbnQobm9kZTogVGhyb3dTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICBub2RlLnZhbHVlLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRUcnlTdGF0ZW1lbnQobm9kZTogVHJ5U3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy52aXNpdChub2RlLnN0YXRlbWVudHMpO1xuICAgIGlmIChub2RlLmNhdGNoVmFyaWFibGUpIG5vZGUuY2F0Y2hWYXJpYWJsZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuY2F0Y2hTdGF0ZW1lbnRzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZmluYWxseVN0YXRlbWVudHMpO1xuICB9XG5cbiAgdmlzaXRUeXBlRGVjbGFyYXRpb24obm9kZTogVHlwZURlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIHRoaXMudmlzaXQobm9kZS5kZWNvcmF0b3JzKTtcbiAgICBub2RlLnR5cGUudmlzaXQodGhpcyk7XG4gICAgdGhpcy52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJzKTtcbiAgfVxuXG4gIHZpc2l0VmFyaWFibGVEZWNsYXJhdGlvbihub2RlOiBWYXJpYWJsZURlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLnR5cGUpIG5vZGUudHlwZS52aXNpdCh0aGlzKTtcbiAgICBpZiAobm9kZS5pbml0aWFsaXplcikgbm9kZS5pbml0aWFsaXplci52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0VmFyaWFibGVTdGF0ZW1lbnQobm9kZTogVmFyaWFibGVTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgdGhpcy52aXNpdChub2RlLmRlY2xhcmF0aW9ucyk7XG4gIH1cblxuICB2aXNpdFdoaWxlU3RhdGVtZW50KG5vZGU6IFdoaWxlU3RhdGVtZW50KTogdm9pZCB7XG4gICAgbm9kZS5jb25kaXRpb24udmlzaXQodGhpcyk7XG4gICAgdGhpcy5kZXB0aCsrO1xuICAgIG5vZGUuc3RhdGVtZW50LnZpc2l0KHRoaXMpO1xuICAgIHRoaXMuZGVwdGgtLTtcbiAgfVxuXG4gIHZpc2l0Vm9pZFN0YXRlbWVudChub2RlOiBWb2lkU3RhdGVtZW50KTogdm9pZCB7fVxuXG4gIHZpc2l0Q29tbWVudChub2RlOiBDb21tZW50Tm9kZSk6IHZvaWQge31cblxuICB2aXNpdERlY29yYXRvck5vZGUobm9kZTogRGVjb3JhdG9yTm9kZSk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuYXJndW1lbnRzKTtcbiAgfVxuXG4gIHZpc2l0UGFyYW1ldGVyKG5vZGU6IFBhcmFtZXRlck5vZGUpOiB2b2lkIHtcbiAgICBub2RlLm5hbWUudmlzaXQodGhpcyk7XG4gICAgaWYgKG5vZGUuaW1wbGljaXRGaWVsZERlY2xhcmF0aW9uKSB7XG4gICAgICBub2RlLmltcGxpY2l0RmllbGREZWNsYXJhdGlvbi52aXNpdCh0aGlzKTtcbiAgICB9XG4gICAgaWYgKG5vZGUuaW5pdGlhbGl6ZXIpIG5vZGUuaW5pdGlhbGl6ZXIudmlzaXQodGhpcyk7XG4gICAgbm9kZS50eXBlLnZpc2l0KHRoaXMpO1xuICB9XG59XG4iXX0=
\ No newline at end of file
diff --git a/lib/visitor/dist/ast/empty.js b/lib/visitor/dist/ast/empty.js
new file mode 100644
index 0000000000..72fe05a46d
--- /dev/null
+++ b/lib/visitor/dist/ast/empty.js
@@ -0,0 +1,83 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var EmptyVisitor = /** @class */ (function () {
+    function EmptyVisitor() {
+    }
+    EmptyVisitor.prototype.visitSource = function (node) { };
+    EmptyVisitor.prototype.visitTypeNode = function (node) { };
+    EmptyVisitor.prototype.visitTypeName = function (node) { };
+    EmptyVisitor.prototype.visitNamedTypeNode = function (node) { };
+    EmptyVisitor.prototype.visitFunctionTypeNode = function (node) { };
+    EmptyVisitor.prototype.visitTypeParameter = function (node) { };
+    EmptyVisitor.prototype.visitIdentifierExpression = function (node) { };
+    EmptyVisitor.prototype.visitArrayLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitObjectLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitAssertionExpression = function (node) { };
+    EmptyVisitor.prototype.visitBinaryExpression = function (node) { };
+    EmptyVisitor.prototype.visitCallExpression = function (node) { };
+    EmptyVisitor.prototype.visitClassExpression = function (node) { };
+    EmptyVisitor.prototype.visitCommaExpression = function (node) { };
+    EmptyVisitor.prototype.visitElementAccessExpression = function (node) { };
+    EmptyVisitor.prototype.visitFunctionExpression = function (node) { };
+    EmptyVisitor.prototype.visitLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitFloatLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitInstanceOfExpression = function (node) { };
+    EmptyVisitor.prototype.visitIntegerLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitStringLiteral = function (str, singleQuoted) { };
+    EmptyVisitor.prototype.visitStringLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitRegexpLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitNewExpression = function (node) { };
+    EmptyVisitor.prototype.visitParenthesizedExpression = function (node) { };
+    EmptyVisitor.prototype.visitPropertyAccessExpression = function (node) { };
+    EmptyVisitor.prototype.visitTernaryExpression = function (node) { };
+    EmptyVisitor.prototype.visitUnaryExpression = function (node) { };
+    EmptyVisitor.prototype.visitUnaryPostfixExpression = function (node) { };
+    EmptyVisitor.prototype.visitUnaryPrefixExpression = function (node) { };
+    EmptyVisitor.prototype.visitSuperExpression = function (node) { };
+    EmptyVisitor.prototype.visitFalseExpression = function (node) { };
+    EmptyVisitor.prototype.visitTrueExpression = function (node) { };
+    EmptyVisitor.prototype.visitThisExpression = function (node) { };
+    EmptyVisitor.prototype.visitNullExperssion = function (node) { };
+    EmptyVisitor.prototype.visitConstructorExpression = function (node) { };
+    EmptyVisitor.prototype.visitNodeAndTerminate = function (statement) { };
+    EmptyVisitor.prototype.visitBlockStatement = function (node) { };
+    EmptyVisitor.prototype.visitBreakStatement = function (node) { };
+    EmptyVisitor.prototype.visitContinueStatement = function (node) { };
+    EmptyVisitor.prototype.visitClassDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitDoStatement = function (node) { };
+    EmptyVisitor.prototype.visitEmptyStatement = function (node) { };
+    EmptyVisitor.prototype.visitEnumDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitEnumValueDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitExportImportStatement = function (node) { };
+    EmptyVisitor.prototype.visitExportMember = function (node) { };
+    EmptyVisitor.prototype.visitExportStatement = function (node) { };
+    EmptyVisitor.prototype.visitExportDefaultStatement = function (node) { };
+    EmptyVisitor.prototype.visitExpressionStatement = function (node) { };
+    EmptyVisitor.prototype.visitFieldDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitForStatement = function (node) { };
+    EmptyVisitor.prototype.visitFunctionDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitFunctionCommon = function (node) { };
+    EmptyVisitor.prototype.visitIfStatement = function (node) { };
+    EmptyVisitor.prototype.visitImportDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitImportStatement = function (node) { };
+    EmptyVisitor.prototype.visitIndexSignatureDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitInterfaceDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitMethodDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitNamespaceDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitReturnStatement = function (node) { };
+    EmptyVisitor.prototype.visitSwitchCase = function (node) { };
+    EmptyVisitor.prototype.visitSwitchStatement = function (node) { };
+    EmptyVisitor.prototype.visitThrowStatement = function (node) { };
+    EmptyVisitor.prototype.visitTryStatement = function (node) { };
+    EmptyVisitor.prototype.visitTypeDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitVariableDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitVariableStatement = function (node) { };
+    EmptyVisitor.prototype.visitWhileStatement = function (node) { };
+    EmptyVisitor.prototype.visitVoidStatement = function (node) { };
+    EmptyVisitor.prototype.visitComment = function (node) { };
+    EmptyVisitor.prototype.visitDecoratorNode = function (node) { };
+    EmptyVisitor.prototype.visitParameter = function (node) { };
+    return EmptyVisitor;
+}());
+exports.EmptyVisitor = EmptyVisitor;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1wdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXN0L2VtcHR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBNEVBO0lBQUE7SUFvRkEsQ0FBQztJQW5GQyxrQ0FBVyxHQUFYLFVBQVksSUFBWSxJQUFTLENBQUM7SUFDbEMsb0NBQWEsR0FBYixVQUFjLElBQWMsSUFBUyxDQUFDO0lBQ3RDLG9DQUFhLEdBQWIsVUFBYyxJQUFjLElBQVMsQ0FBQztJQUN0Qyx5Q0FBa0IsR0FBbEIsVUFBbUIsSUFBbUIsSUFBUyxDQUFDO0lBQ2hELDRDQUFxQixHQUFyQixVQUFzQixJQUFzQixJQUFTLENBQUM7SUFDdEQseUNBQWtCLEdBQWxCLFVBQW1CLElBQXVCLElBQVMsQ0FBQztJQUNwRCxnREFBeUIsR0FBekIsVUFBMEIsSUFBMEIsSUFBUyxDQUFDO0lBQzlELGtEQUEyQixHQUEzQixVQUE0QixJQUE0QixJQUFTLENBQUM7SUFDbEUsbURBQTRCLEdBQTVCLFVBQTZCLElBQTZCLElBQVMsQ0FBQztJQUNwRSwrQ0FBd0IsR0FBeEIsVUFBeUIsSUFBeUIsSUFBUyxDQUFDO0lBQzVELDRDQUFxQixHQUFyQixVQUFzQixJQUFzQixJQUFTLENBQUM7SUFDdEQsMENBQW1CLEdBQW5CLFVBQW9CLElBQW9CLElBQVMsQ0FBQztJQUNsRCwyQ0FBb0IsR0FBcEIsVUFBcUIsSUFBcUIsSUFBUyxDQUFDO0lBQ3BELDJDQUFvQixHQUFwQixVQUFxQixJQUFxQixJQUFTLENBQUM7SUFDcEQsbURBQTRCLEdBQTVCLFVBQTZCLElBQTZCLElBQVMsQ0FBQztJQUNwRSw4Q0FBdUIsR0FBdkIsVUFBd0IsSUFBd0IsSUFBUyxDQUFDO0lBQzFELDZDQUFzQixHQUF0QixVQUF1QixJQUF1QixJQUFTLENBQUM7SUFDeEQsa0RBQTJCLEdBQTNCLFVBQTRCLElBQTRCLElBQVMsQ0FBQztJQUNsRSxnREFBeUIsR0FBekIsVUFBMEIsSUFBMEIsSUFBUyxDQUFDO0lB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LFVBQXFCLElBQXFCLElBQVMsQ0FBQztJQUNwRCxzQ0FBZSxHQUFmLFVBQWdCLElBQWdCLElBQVMsQ0FBQztJQUMxQywyQ0FBb0IsR0FBcEIsVUFBcUIsSUFBcUIsSUFBUyxDQUFDO0lBQ3BELDBDQUFtQixHQUFuQixVQUFvQixJQUFvQixJQUFTLENBQUM7SUFDbEQsd0NBQWlCLEdBQWpCLFVBQWtCLElBQWtCLElBQVMsQ0FBQztJQUM5QywyQ0FBb0IsR0FBcEIsVUFBcUIsSUFBcUIsSUFBUyxDQUFDO0lBQ3BELCtDQUF3QixHQUF4QixVQUF5QixJQUF5QixJQUFTLENBQUM7SUFDNUQsNkNBQXNCLEdBQXRCLFVBQXVCLElBQXVCLElBQVMsQ0FBQztJQUN4RCwwQ0FBbUIsR0FBbkIsVUFBb0IsSUFBb0IsSUFBUyxDQUFDO0lBQ2xELHlDQUFrQixHQUFsQixVQUFtQixJQUFtQixJQUFTLENBQUM7SUFDaEQsbUNBQVksR0FBWixVQUFhLElBQWlCLElBQVMsQ0FBQztJQUN4Qyx5Q0FBa0IsR0FBbEIsVUFBbUIsSUFBbUIsSUFBUyxDQUFDO0lBQ2hELHFDQUFjLEdBQWQsVUFBZSxJQUFtQixJQUFTLENBQUM7SUFDOUMsbUJBQUM7QUFBRCxDQUFDLEFBcEZELElBb0ZDO0FBcEZZLG9DQUFZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQVNUVmlzaXRvcixcbiAgU291cmNlLFxuICBUeXBlTm9kZSxcbiAgVHlwZU5hbWUsXG4gIE5hbWVkVHlwZU5vZGUsXG4gIEZ1bmN0aW9uVHlwZU5vZGUsXG4gIFR5cGVQYXJhbWV0ZXJOb2RlLFxuICBJZGVudGlmaWVyRXhwcmVzc2lvbixcbiAgQXJyYXlMaXRlcmFsRXhwcmVzc2lvbixcbiAgT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24sXG4gIEFzc2VydGlvbkV4cHJlc3Npb24sXG4gIEJpbmFyeUV4cHJlc3Npb24sXG4gIENhbGxFeHByZXNzaW9uLFxuICBDbGFzc0V4cHJlc3Npb24sXG4gIENvbW1hRXhwcmVzc2lvbixcbiAgRWxlbWVudEFjY2Vzc0V4cHJlc3Npb24sXG4gIEZ1bmN0aW9uRXhwcmVzc2lvbixcbiAgTGl0ZXJhbEV4cHJlc3Npb24sXG4gIEZsb2F0TGl0ZXJhbEV4cHJlc3Npb24sXG4gIEluc3RhbmNlT2ZFeHByZXNzaW9uLFxuICBJbnRlZ2VyTGl0ZXJhbEV4cHJlc3Npb24sXG4gIFN0cmluZ0xpdGVyYWxFeHByZXNzaW9uLFxuICBSZWdleHBMaXRlcmFsRXhwcmVzc2lvbixcbiAgTmV3RXhwcmVzc2lvbixcbiAgUGFyZW50aGVzaXplZEV4cHJlc3Npb24sXG4gIFByb3BlcnR5QWNjZXNzRXhwcmVzc2lvbixcbiAgVGVybmFyeUV4cHJlc3Npb24sXG4gIFVuYXJ5RXhwcmVzc2lvbixcbiAgVW5hcnlQb3N0Zml4RXhwcmVzc2lvbixcbiAgVW5hcnlQcmVmaXhFeHByZXNzaW9uLFxuICBTdXBlckV4cHJlc3Npb24sXG4gIEZhbHNlRXhwcmVzc2lvbixcbiAgVHJ1ZUV4cHJlc3Npb24sXG4gIFRoaXNFeHByZXNzaW9uLFxuICBOdWxsRXhwcmVzc2lvbixcbiAgQ29uc3RydWN0b3JFeHByZXNzaW9uLFxuICBTdGF0ZW1lbnQsXG4gIEJsb2NrU3RhdGVtZW50LFxuICBCcmVha1N0YXRlbWVudCxcbiAgQ29udGludWVTdGF0ZW1lbnQsXG4gIENsYXNzRGVjbGFyYXRpb24sXG4gIERvU3RhdGVtZW50LFxuICBFbXB0eVN0YXRlbWVudCxcbiAgRW51bURlY2xhcmF0aW9uLFxuICBFbnVtVmFsdWVEZWNsYXJhdGlvbixcbiAgRXhwb3J0SW1wb3J0U3RhdGVtZW50LFxuICBFeHBvcnRNZW1iZXIsXG4gIEV4cG9ydFN0YXRlbWVudCxcbiAgRXhwb3J0RGVmYXVsdFN0YXRlbWVudCxcbiAgRXhwcmVzc2lvblN0YXRlbWVudCxcbiAgRmllbGREZWNsYXJhdGlvbixcbiAgRm9yU3RhdGVtZW50LFxuICBGdW5jdGlvbkRlY2xhcmF0aW9uLFxuICBJZlN0YXRlbWVudCxcbiAgSW1wb3J0RGVjbGFyYXRpb24sXG4gIEltcG9ydFN0YXRlbWVudCxcbiAgSW5kZXhTaWduYXR1cmVEZWNsYXJhdGlvbixcbiAgSW50ZXJmYWNlRGVjbGFyYXRpb24sXG4gIE1ldGhvZERlY2xhcmF0aW9uLFxuICBOYW1lc3BhY2VEZWNsYXJhdGlvbixcbiAgUmV0dXJuU3RhdGVtZW50LFxuICBTd2l0Y2hDYXNlLFxuICBTd2l0Y2hTdGF0ZW1lbnQsXG4gIFRocm93U3RhdGVtZW50LFxuICBUcnlTdGF0ZW1lbnQsXG4gIFR5cGVEZWNsYXJhdGlvbixcbiAgVmFyaWFibGVEZWNsYXJhdGlvbixcbiAgVmFyaWFibGVTdGF0ZW1lbnQsXG4gIFdoaWxlU3RhdGVtZW50LFxuICBWb2lkU3RhdGVtZW50LFxuICBDb21tZW50Tm9kZSxcbiAgRGVjb3JhdG9yTm9kZSxcbiAgUGFyYW1ldGVyTm9kZVxufSBmcm9tIFwiYXNzZW1ibHlzY3JpcHRcIjtcblxuZXhwb3J0IGNsYXNzIEVtcHR5VmlzaXRvciBpbXBsZW1lbnRzIEFTVFZpc2l0b3Ige1xuICB2aXNpdFNvdXJjZShub2RlOiBTb3VyY2UpOiB2b2lkIHt9XG4gIHZpc2l0VHlwZU5vZGUobm9kZTogVHlwZU5vZGUpOiB2b2lkIHt9XG4gIHZpc2l0VHlwZU5hbWUobm9kZTogVHlwZU5hbWUpOiB2b2lkIHt9XG4gIHZpc2l0TmFtZWRUeXBlTm9kZShub2RlOiBOYW1lZFR5cGVOb2RlKTogdm9pZCB7fVxuICB2aXNpdEZ1bmN0aW9uVHlwZU5vZGUobm9kZTogRnVuY3Rpb25UeXBlTm9kZSk6IHZvaWQge31cbiAgdmlzaXRUeXBlUGFyYW1ldGVyKG5vZGU6IFR5cGVQYXJhbWV0ZXJOb2RlKTogdm9pZCB7fVxuICB2aXNpdElkZW50aWZpZXJFeHByZXNzaW9uKG5vZGU6IElkZW50aWZpZXJFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdEFycmF5TGl0ZXJhbEV4cHJlc3Npb24obm9kZTogQXJyYXlMaXRlcmFsRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRPYmplY3RMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBPYmplY3RMaXRlcmFsRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRBc3NlcnRpb25FeHByZXNzaW9uKG5vZGU6IEFzc2VydGlvbkV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0QmluYXJ5RXhwcmVzc2lvbihub2RlOiBCaW5hcnlFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdENhbGxFeHByZXNzaW9uKG5vZGU6IENhbGxFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdENsYXNzRXhwcmVzc2lvbihub2RlOiBDbGFzc0V4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0Q29tbWFFeHByZXNzaW9uKG5vZGU6IENvbW1hRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRFbGVtZW50QWNjZXNzRXhwcmVzc2lvbihub2RlOiBFbGVtZW50QWNjZXNzRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRGdW5jdGlvbkV4cHJlc3Npb24obm9kZTogRnVuY3Rpb25FeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdExpdGVyYWxFeHByZXNzaW9uKG5vZGU6IExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdEZsb2F0TGl0ZXJhbEV4cHJlc3Npb24obm9kZTogRmxvYXRMaXRlcmFsRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRJbnN0YW5jZU9mRXhwcmVzc2lvbihub2RlOiBJbnN0YW5jZU9mRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRJbnRlZ2VyTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogSW50ZWdlckxpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdFN0cmluZ0xpdGVyYWwoc3RyOiBzdHJpbmcsIHNpbmdsZVF1b3RlZD86IGJvb2xlYW4pOiB2b2lkIHt9XG4gIHZpc2l0U3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogU3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0UmVnZXhwTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogUmVnZXhwTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0TmV3RXhwcmVzc2lvbihub2RlOiBOZXdFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uKG5vZGU6IFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdFByb3BlcnR5QWNjZXNzRXhwcmVzc2lvbihub2RlOiBQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VGVybmFyeUV4cHJlc3Npb24obm9kZTogVGVybmFyeUV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VW5hcnlFeHByZXNzaW9uKG5vZGU6IFVuYXJ5RXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRVbmFyeVBvc3RmaXhFeHByZXNzaW9uKG5vZGU6IFVuYXJ5UG9zdGZpeEV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VW5hcnlQcmVmaXhFeHByZXNzaW9uKG5vZGU6IFVuYXJ5UHJlZml4RXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRTdXBlckV4cHJlc3Npb24obm9kZTogU3VwZXJFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdEZhbHNlRXhwcmVzc2lvbihub2RlOiBGYWxzZUV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VHJ1ZUV4cHJlc3Npb24obm9kZTogVHJ1ZUV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VGhpc0V4cHJlc3Npb24obm9kZTogVGhpc0V4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0TnVsbEV4cGVyc3Npb24obm9kZTogTnVsbEV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0Q29uc3RydWN0b3JFeHByZXNzaW9uKG5vZGU6IENvbnN0cnVjdG9yRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXROb2RlQW5kVGVybWluYXRlKHN0YXRlbWVudDogU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdEJsb2NrU3RhdGVtZW50KG5vZGU6IEJsb2NrU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdEJyZWFrU3RhdGVtZW50KG5vZGU6IEJyZWFrU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdENvbnRpbnVlU3RhdGVtZW50KG5vZGU6IENvbnRpbnVlU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdENsYXNzRGVjbGFyYXRpb24obm9kZTogQ2xhc3NEZWNsYXJhdGlvbiwgaXNEZWZhdWx0PzogYm9vbGVhbik6IHZvaWQge31cbiAgdmlzaXREb1N0YXRlbWVudChub2RlOiBEb1N0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRFbXB0eVN0YXRlbWVudChub2RlOiBFbXB0eVN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRFbnVtRGVjbGFyYXRpb24obm9kZTogRW51bURlY2xhcmF0aW9uLCBpc0RlZmF1bHQ/OiBib29sZWFuKTogdm9pZCB7fVxuICB2aXNpdEVudW1WYWx1ZURlY2xhcmF0aW9uKG5vZGU6IEVudW1WYWx1ZURlY2xhcmF0aW9uKTogdm9pZCB7fVxuICB2aXNpdEV4cG9ydEltcG9ydFN0YXRlbWVudChub2RlOiBFeHBvcnRJbXBvcnRTdGF0ZW1lbnQpOiB2b2lkIHt9XG4gIHZpc2l0RXhwb3J0TWVtYmVyKG5vZGU6IEV4cG9ydE1lbWJlcik6IHZvaWQge31cbiAgdmlzaXRFeHBvcnRTdGF0ZW1lbnQobm9kZTogRXhwb3J0U3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdEV4cG9ydERlZmF1bHRTdGF0ZW1lbnQobm9kZTogRXhwb3J0RGVmYXVsdFN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRFeHByZXNzaW9uU3RhdGVtZW50KG5vZGU6IEV4cHJlc3Npb25TdGF0ZW1lbnQpOiB2b2lkIHt9XG4gIHZpc2l0RmllbGREZWNsYXJhdGlvbihub2RlOiBGaWVsZERlY2xhcmF0aW9uKTogdm9pZCB7fVxuICB2aXNpdEZvclN0YXRlbWVudChub2RlOiBGb3JTdGF0ZW1lbnQpOiB2b2lkIHt9XG4gIHZpc2l0RnVuY3Rpb25EZWNsYXJhdGlvbihcbiAgICBub2RlOiBGdW5jdGlvbkRlY2xhcmF0aW9uLFxuICAgIGlzRGVmYXVsdD86IGJvb2xlYW5cbiAgKTogdm9pZCB7fVxuICB2aXNpdEZ1bmN0aW9uQ29tbW9uKG5vZGU6IEZ1bmN0aW9uRGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0SWZTdGF0ZW1lbnQobm9kZTogSWZTdGF0ZW1lbnQpOiB2b2lkIHt9XG4gIHZpc2l0SW1wb3J0RGVjbGFyYXRpb24obm9kZTogSW1wb3J0RGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0SW1wb3J0U3RhdGVtZW50KG5vZGU6IEltcG9ydFN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRJbmRleFNpZ25hdHVyZURlY2xhcmF0aW9uKG5vZGU6IEluZGV4U2lnbmF0dXJlRGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0SW50ZXJmYWNlRGVjbGFyYXRpb24oXG4gICAgbm9kZTogSW50ZXJmYWNlRGVjbGFyYXRpb24sXG4gICAgaXNEZWZhdWx0PzogYm9vbGVhblxuICApOiB2b2lkIHt9XG4gIHZpc2l0TWV0aG9kRGVjbGFyYXRpb24obm9kZTogTWV0aG9kRGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0TmFtZXNwYWNlRGVjbGFyYXRpb24oXG4gICAgbm9kZTogTmFtZXNwYWNlRGVjbGFyYXRpb24sXG4gICAgaXNEZWZhdWx0PzogYm9vbGVhblxuICApOiB2b2lkIHt9XG4gIHZpc2l0UmV0dXJuU3RhdGVtZW50KG5vZGU6IFJldHVyblN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRTd2l0Y2hDYXNlKG5vZGU6IFN3aXRjaENhc2UpOiB2b2lkIHt9XG4gIHZpc2l0U3dpdGNoU3RhdGVtZW50KG5vZGU6IFN3aXRjaFN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRUaHJvd1N0YXRlbWVudChub2RlOiBUaHJvd1N0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRUcnlTdGF0ZW1lbnQobm9kZTogVHJ5U3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdFR5cGVEZWNsYXJhdGlvbihub2RlOiBUeXBlRGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0VmFyaWFibGVEZWNsYXJhdGlvbihub2RlOiBWYXJpYWJsZURlY2xhcmF0aW9uKTogdm9pZCB7fVxuICB2aXNpdFZhcmlhYmxlU3RhdGVtZW50KG5vZGU6IFZhcmlhYmxlU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdFdoaWxlU3RhdGVtZW50KG5vZGU6IFdoaWxlU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdFZvaWRTdGF0ZW1lbnQobm9kZTogVm9pZFN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRDb21tZW50KG5vZGU6IENvbW1lbnROb2RlKTogdm9pZCB7fVxuICB2aXNpdERlY29yYXRvck5vZGUobm9kZTogRGVjb3JhdG9yTm9kZSk6IHZvaWQge31cbiAgdmlzaXRQYXJhbWV0ZXIobm9kZTogUGFyYW1ldGVyTm9kZSk6IHZvaWQge31cbn1cbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/ast/index.js b/lib/visitor/dist/ast/index.js
new file mode 100644
index 0000000000..c4166e1f1f
--- /dev/null
+++ b/lib/visitor/dist/ast/index.js
@@ -0,0 +1,8 @@
+"use strict";
+function __export(m) {
+    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+Object.defineProperty(exports, "__esModule", { value: true });
+__export(require("./base"));
+__export(require("./empty"));
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXN0L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBS0EsNEJBQXVCO0FBQ3ZCLDZCQUF3QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFTVFZpc2l0b3IgYXMgSVZpc2l0b3IsIE5vZGUgfSBmcm9tIFwiYXNzZW1ibHlzY3JpcHRcIjtcbmltcG9ydCB7IFZpc2l0b3IgfSBmcm9tIFwiLi4vdmlzaXRvclwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFTVFZpc2l0b3IgZXh0ZW5kcyBJVmlzaXRvciwgVmlzaXRvcjxOb2RlPnt9XG5cbmV4cG9ydCAqIGZyb20gXCIuL2Jhc2VcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2VtcHR5XCI7Il19
\ No newline at end of file
diff --git a/lib/visitor/dist/element/base.js b/lib/visitor/dist/element/base.js
new file mode 100644
index 0000000000..c74c3d9708
--- /dev/null
+++ b/lib/visitor/dist/element/base.js
@@ -0,0 +1,182 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var __values = (this && this.__values) || function (o) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+    if (m) return m.call(o);
+    return {
+        next: function () {
+            if (o && i >= o.length) o = void 0;
+            return { value: o && o[i++], done: !o };
+        }
+    };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var assemblyscript_1 = require("assemblyscript");
+var visitor_1 = require("../visitor");
+var assemblyscript_2 = require("assemblyscript");
+var BaseElementVisitor = /** @class */ (function (_super) {
+    __extends(BaseElementVisitor, _super);
+    function BaseElementVisitor(parser, compiler, writer) {
+        var _this = _super.call(this) || this;
+        _this.parser = parser;
+        _this.compiler = compiler;
+        _this.writer = writer;
+        return _this;
+    }
+    Object.defineProperty(BaseElementVisitor.prototype, "files", {
+        get: function () {
+            return this.parser.program.filesByName.values();
+        },
+        enumerable: true,
+        configurable: true
+    });
+    BaseElementVisitor.prototype.getFunctionByName = function (name) {
+        return this.compiler.program.instancesByName.get(name);
+    };
+    BaseElementVisitor.prototype.start = function () {
+        this.visit(this.files);
+    };
+    BaseElementVisitor.prototype.visitFile = function (node) {
+        var declares;
+        // tslint:disable-next-line: as-types
+        declares = node.source.statements.filter(function (s) { return s instanceof assemblyscript_2.DeclarationStatement; });
+        this.visit(declares.map(function (stmt) { return node.program.elementsByDeclaration.get(stmt); }));
+        // this.visit(node.members);
+        // this.visit(node.program.elementsByName);
+    };
+    BaseElementVisitor.prototype.visitNode = function (node) {
+        this.astVisitor.visit(node);
+    };
+    // visit(element: Element | Element[] | null ): void {
+    //   if (element) {
+    //     if (element instanceof Element) {
+    //       element.visit(this);
+    //     }else {
+    //       element.map(this.visit);
+    //     }
+    //   }
+    // }
+    // visitMemebers(map: Map<any, Element> | null): void {
+    //   if (map) {
+    //     for (let element of map.values()) {
+    //       element.visit(this);
+    //     }
+    //   }
+    // }
+    BaseElementVisitor.prototype.visitManagedClasses = function (files, visitor) {
+        this.visitElements(files, assemblyscript_1.ElementKind.CLASS, visitor);
+    };
+    BaseElementVisitor.prototype.visitInterfaces = function (files, visitor) {
+        this.visitElements(files, assemblyscript_1.ElementKind.INTERFACE_PROTOTYPE, visitor);
+    };
+    BaseElementVisitor.prototype.visitElements = function (files, elementKind, visitor) {
+        var e_1, _a, e_2, _b;
+        try {
+            for (var files_1 = __values(files), files_1_1 = files_1.next(); !files_1_1.done; files_1_1 = files_1.next()) {
+                var file = files_1_1.value;
+                if (!file.name.startsWith("~lib")) {
+                    if (file.members) {
+                        try {
+                            for (var _c = __values(file.members.values()), _d = _c.next(); !_d.done; _d = _c.next()) {
+                                var element = _d.value;
+                                if (element.kind == elementKind) {
+                                    if (visitor) {
+                                        visitor(element);
+                                    }
+                                    else {
+                                        element.visit(this);
+                                    }
+                                }
+                            }
+                        }
+                        catch (e_2_1) { e_2 = { error: e_2_1 }; }
+                        finally {
+                            try {
+                                if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
+                            }
+                            finally { if (e_2) throw e_2.error; }
+                        }
+                    }
+                }
+            }
+        }
+        catch (e_1_1) { e_1 = { error: e_1_1 }; }
+        finally {
+            try {
+                if (files_1_1 && !files_1_1.done && (_a = files_1.return)) _a.call(files_1);
+            }
+            finally { if (e_1) throw e_1.error; }
+        }
+    };
+    BaseElementVisitor.prototype.visitTypeDefinition = function (node) { };
+    BaseElementVisitor.prototype.visitNamespace = function (node) {
+        this.visit(node.members);
+    };
+    BaseElementVisitor.prototype.visitEnum = function (node) {
+        this.visit(node.members);
+    };
+    BaseElementVisitor.prototype.visitEnumValue = function (node) { };
+    BaseElementVisitor.prototype.visitGlobal = function (node) { };
+    BaseElementVisitor.prototype.visitLocal = function (node) { };
+    BaseElementVisitor.prototype.visitFunctionPrototype = function (node) {
+        if (node.parent instanceof assemblyscript_1.Function) {
+            node.parent.visit(this);
+        }
+        else {
+            this.visit(node.members);
+        }
+    };
+    BaseElementVisitor.prototype.visitFunction = function (node) {
+        this.visit(node.members);
+    };
+    BaseElementVisitor.prototype.visitFunctionTarget = function (node) { };
+    BaseElementVisitor.prototype.visitFieldPrototype = function (node) {
+        if (node.parent instanceof assemblyscript_1.Field) {
+            node.parent.visit(this);
+        }
+    };
+    BaseElementVisitor.prototype.visitField = function (node) { };
+    BaseElementVisitor.prototype.visitPropertyPrototype = function (node) {
+        if (node.parent instanceof assemblyscript_1.Property) {
+            node.parent.visit(this);
+        }
+        else {
+            this.visit(node.getterPrototype);
+            this.visit(node.setterPrototype);
+        }
+    };
+    BaseElementVisitor.prototype.visitProperty = function (node) {
+        this.visit(node.getterInstance);
+        this.visit(node.setterInstance);
+    };
+    BaseElementVisitor.prototype.visitClassPrototype = function (node) {
+        if (node.parent instanceof assemblyscript_1.Class) {
+            node.parent.visit(this);
+        }
+        else {
+            this.visit(node.instanceMembers);
+        }
+    };
+    BaseElementVisitor.prototype.visitClass = function (node) {
+        this.visit(node.members);
+    };
+    BaseElementVisitor.prototype.visitInterfacePrototype = function (node) { };
+    BaseElementVisitor.prototype.visitInterface = function (node) {
+        this.visit(node.prototype.instanceMembers);
+    };
+    return BaseElementVisitor;
+}(visitor_1.AbstractVisitor));
+exports.BaseElementVisitor = BaseElementVisitor;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9lbGVtZW50L2Jhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlEQTBCd0I7QUFFeEIsc0NBQWtFO0FBRWxFLGlEQUFzRDtBQU10RDtJQUFpRCxzQ0FBd0I7SUFLdkUsNEJBQW1CLE1BQWMsRUFBUyxRQUFrQixFQUFTLE1BQWM7UUFBbkYsWUFDRSxpQkFBTyxTQUNSO1FBRmtCLFlBQU0sR0FBTixNQUFNLENBQVE7UUFBUyxjQUFRLEdBQVIsUUFBUSxDQUFVO1FBQVMsWUFBTSxHQUFOLE1BQU0sQ0FBUTs7SUFFbkYsQ0FBQztJQUVELHNCQUFJLHFDQUFLO2FBQVQ7WUFDRSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNsRCxDQUFDOzs7T0FBQTtJQUVELDhDQUFpQixHQUFqQixVQUFrQixJQUFZO1FBQzVCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQWEsQ0FBQztJQUNyRSxDQUFDO0lBRUQsa0NBQUssR0FBTDtRQUNFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pCLENBQUM7SUFFRCxzQ0FBUyxHQUFULFVBQVUsSUFBVTtRQUNsQixJQUFJLFFBQWdDLENBQUM7UUFDckMscUNBQXFDO1FBQ3JDLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsVUFBQSxDQUFDLElBQUksT0FBQSxDQUFDLFlBQVkscUNBQW9CLEVBQWpDLENBQWlDLENBQTJCLENBQUM7UUFDM0csSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFVBQUEsSUFBSSxJQUFJLE9BQUEsSUFBSSxDQUFDLE9BQU8sQ0FB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MUQsMkNBQWMsR0FBZCxVQUFlLElBQWU7UUFDNUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFDSCx5QkFBQztBQUFELENBQUMsQUFuSUQsQ0FBaUQseUJBQWUsR0FtSS9EO0FBbklxQixnREFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBFbGVtZW50VmlzaXRvciBhcyBJVmlzaXRvcixcbiAgRmlsZSxcbiAgVHlwZURlZmluaXRpb24sXG4gIE5hbWVzcGFjZSxcbiAgRW51bSxcbiAgRW51bVZhbHVlLFxuICBHbG9iYWwsXG4gIExvY2FsLFxuICBGdW5jdGlvblByb3RvdHlwZSxcbiAgRnVuY3Rpb24sXG4gIEZ1bmN0aW9uVGFyZ2V0LFxuICBGaWVsZFByb3RvdHlwZSxcbiAgRmllbGQsXG4gIFByb3BlcnR5UHJvdG90eXBlLFxuICBQcm9wZXJ0eSxcbiAgQ2xhc3NQcm90b3R5cGUsXG4gIENsYXNzLFxuICBJbnRlcmZhY2VQcm90b3R5cGUsXG4gIEludGVyZmFjZSxcbiAgRWxlbWVudCxcbiAgTm9kZSxcbiAgTm9kZUtpbmQsXG4gIEVsZW1lbnRLaW5kLFxuICBQYXJzZXIsXG4gIENvbXBpbGVyXG59IGZyb20gXCJhc3NlbWJseXNjcmlwdFwiO1xuXG5pbXBvcnQgeyBWaXNpdG9yLCBBYnN0cmFjdFZpc2l0b3IsIENvbGxlY3Rpb24gfSBmcm9tIFwiLi4vdmlzaXRvclwiO1xuaW1wb3J0IHsgQVNUVmlzaXRvciB9IGZyb20gXCIuLi9hc3QvaW5kZXhcIjtcbmltcG9ydCB7IERlY2xhcmF0aW9uU3RhdGVtZW50IH0gZnJvbSBcImFzc2VtYmx5c2NyaXB0XCI7XG5pbXBvcnQgeyBEZWNsYXJlZEVsZW1lbnQgfSBmcm9tIFwiYXNzZW1ibHlzY3JpcHRcIjtcbmltcG9ydCB7IFdyaXRlciB9IGZyb20gXCIuLlwiO1xuXG5pbnRlcmZhY2UgRWxlbWVudFZpc2l0b3IgZXh0ZW5kcyBWaXNpdG9yPEVsZW1lbnQ+LCBJVmlzaXRvciB7fVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZUVsZW1lbnRWaXNpdG9yIGV4dGVuZHMgQWJzdHJhY3RWaXNpdG9yPEVsZW1lbnQ+XG4gIGltcGxlbWVudHMgRWxlbWVudFZpc2l0b3Ige1xuXG4gIGFzdFZpc2l0b3I6IEFTVFZpc2l0b3I7XG5cbiAgY29uc3RydWN0b3IocHVibGljIHBhcnNlcjogUGFyc2VyLCBwdWJsaWMgY29tcGlsZXI6IENvbXBpbGVyLCBwdWJsaWMgd3JpdGVyOiBXcml0ZXIpIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgZ2V0IGZpbGVzKCk6IEl0ZXJhYmxlPEZpbGU+IHtcbiAgICByZXR1cm4gdGhpcy5wYXJzZXIucHJvZ3JhbS5maWxlc0J5TmFtZS52YWx1ZXMoKTtcbiAgfVxuXG4gIGdldEZ1bmN0aW9uQnlOYW1lKG5hbWU6IHN0cmluZyk6IEZ1bmN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5jb21waWxlci5wcm9ncmFtLmluc3RhbmNlc0J5TmFtZS5nZXQobmFtZSkgYXMgRnVuY3Rpb247XG4gIH1cblxuICBzdGFydCgpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KHRoaXMuZmlsZXMpO1xuICB9XG5cbiAgdmlzaXRGaWxlKG5vZGU6IEZpbGUpOiB2b2lkIHtcbiAgICB2YXIgZGVjbGFyZXM6IERlY2xhcmF0aW9uU3RhdGVtZW50W107XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBhcy10eXBlc1xuICAgIGRlY2xhcmVzID0gbm9kZS5zb3VyY2Uuc3RhdGVtZW50cy5maWx0ZXIocyA9PiBzIGluc3RhbmNlb2YgRGVjbGFyYXRpb25TdGF0ZW1lbnQpIGFzIERlY2xhcmF0aW9uU3RhdGVtZW50W107XG4gICAgdGhpcy52aXNpdChkZWNsYXJlcy5tYXAoc3RtdCA9PiBub2RlLnByb2dyYW0uZWxlbWVudHNCeURlY2xhcmF0aW9uLmdldChzdG10KSkgYXMgRGVjbGFyZWRFbGVtZW50W10pO1xuICAgIC8vIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgICAvLyB0aGlzLnZpc2l0KG5vZGUucHJvZ3JhbS5lbGVtZW50c0J5TmFtZSk7XG4gIH1cblxuICB2aXNpdE5vZGUobm9kZTogQ29sbGVjdGlvbjxOb2RlPik6IHZvaWQge1xuICAgIHRoaXMuYXN0VmlzaXRvci52aXNpdChub2RlKTtcbiAgfVxuXG4gIC8vIHZpc2l0KGVsZW1lbnQ6IEVsZW1lbnQgfCBFbGVtZW50W10gfCBudWxsICk6IHZvaWQge1xuICAvLyAgIGlmIChlbGVtZW50KSB7XG4gIC8vICAgICBpZiAoZWxlbWVudCBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgLy8gICAgICAgZWxlbWVudC52aXNpdCh0aGlzKTtcbiAgLy8gICAgIH1lbHNlIHtcbiAgLy8gICAgICAgZWxlbWVudC5tYXAodGhpcy52aXNpdCk7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG5cbiAgLy8gdmlzaXRNZW1lYmVycyhtYXA6IE1hcDxhbnksIEVsZW1lbnQ+IHwgbnVsbCk6IHZvaWQge1xuICAvLyAgIGlmIChtYXApIHtcbiAgLy8gICAgIGZvciAobGV0IGVsZW1lbnQgb2YgbWFwLnZhbHVlcygpKSB7XG4gIC8vICAgICAgIGVsZW1lbnQudmlzaXQodGhpcyk7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG5cbiAgdmlzaXRNYW5hZ2VkQ2xhc3NlcyhmaWxlczogSXRlcmFibGU8RmlsZT4sIHZpc2l0b3I/OiAoYzogQ2xhc3MpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0RWxlbWVudHMoZmlsZXMsIEVsZW1lbnRLaW5kLkNMQVNTLCB2aXNpdG9yKTtcbiAgfVxuXG4gIHZpc2l0SW50ZXJmYWNlcyhmaWxlczogSXRlcmFibGU8RmlsZT4sIHZpc2l0b3I/OiAoKGk6IEludGVyZmFjZVByb3RvdHlwZSkgPT4gdm9pZCkpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0RWxlbWVudHMoZmlsZXMsIEVsZW1lbnRLaW5kLklOVEVSRkFDRV9QUk9UT1RZUEUgLCB2aXNpdG9yKTtcbiAgfVxuXG4gIHByaXZhdGUgdmlzaXRFbGVtZW50cyhmaWxlczogSXRlcmFibGU8RmlsZT4sIGVsZW1lbnRLaW5kOiBFbGVtZW50S2luZCwgdmlzaXRvcj86ICgoZTogRGVjbGFyZWRFbGVtZW50KSA9PiB2b2lkKSk6IHZvaWQge1xuICAgIGZvciAobGV0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgIGlmICghZmlsZS5uYW1lLnN0YXJ0c1dpdGgoXCJ+bGliXCIpKSB7XG4gICAgICAgIGlmIChmaWxlLm1lbWJlcnMpIHtcbiAgICAgICAgICBmb3IgKGxldCBlbGVtZW50IG9mIGZpbGUubWVtYmVycy52YWx1ZXMoKSkge1xuICAgICAgICAgICAgaWYgKGVsZW1lbnQua2luZCA9PSBlbGVtZW50S2luZCkge1xuICAgICAgICAgICAgICBpZiAodmlzaXRvcikge1xuICAgICAgICAgICAgICAgIHZpc2l0b3IoZWxlbWVudCk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZWxlbWVudC52aXNpdCh0aGlzKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZpc2l0VHlwZURlZmluaXRpb24obm9kZTogVHlwZURlZmluaXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0TmFtZXNwYWNlKG5vZGU6IE5hbWVzcGFjZSk6IHZvaWQge1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgfVxuICB2aXNpdEVudW0obm9kZTogRW51bSk6IHZvaWQge1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgfVxuICB2aXNpdEVudW1WYWx1ZShub2RlOiBFbnVtVmFsdWUpOiB2b2lkIHt9XG4gIHZpc2l0R2xvYmFsKG5vZGU6IEdsb2JhbCk6IHZvaWQge31cbiAgdmlzaXRMb2NhbChub2RlOiBMb2NhbCk6IHZvaWQge31cbiAgdmlzaXRGdW5jdGlvblByb3RvdHlwZShub2RlOiBGdW5jdGlvblByb3RvdHlwZSk6IHZvaWQge1xuICAgIGlmIChub2RlLnBhcmVudCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBub2RlLnBhcmVudC52aXNpdCh0aGlzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52aXNpdChub2RlLm1lbWJlcnMpO1xuICAgIH1cbiAgfVxuICB2aXNpdEZ1bmN0aW9uKG5vZGU6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy52aXNpdChub2RlLm1lbWJlcnMpO1xuICB9XG4gIHZpc2l0RnVuY3Rpb25UYXJnZXQobm9kZTogRnVuY3Rpb25UYXJnZXQpOiB2b2lkIHt9XG4gIHZpc2l0RmllbGRQcm90b3R5cGUobm9kZTogRmllbGRQcm90b3R5cGUpOiB2b2lkIHtcbiAgICBpZiAobm9kZS5wYXJlbnQgaW5zdGFuY2VvZiBGaWVsZCkge1xuICAgICAgbm9kZS5wYXJlbnQudmlzaXQodGhpcyk7XG4gICAgfVxuICB9XG4gIHZpc2l0RmllbGQobm9kZTogRmllbGQpOiB2b2lkIHt9XG4gIHZpc2l0UHJvcGVydHlQcm90b3R5cGUobm9kZTogUHJvcGVydHlQcm90b3R5cGUpOiB2b2lkIHtcbiAgICBpZiAobm9kZS5wYXJlbnQgaW5zdGFuY2VvZiBQcm9wZXJ0eSkge1xuICAgICAgbm9kZS5wYXJlbnQudmlzaXQodGhpcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudmlzaXQobm9kZS5nZXR0ZXJQcm90b3R5cGUpO1xuICAgICAgdGhpcy52aXNpdChub2RlLnNldHRlclByb3RvdHlwZSk7XG4gICAgfVxuICB9XG4gIHZpc2l0UHJvcGVydHkobm9kZTogUHJvcGVydHkpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZ2V0dGVySW5zdGFuY2UpO1xuICAgIHRoaXMudmlzaXQobm9kZS5zZXR0ZXJJbnN0YW5jZSk7XG4gIH1cbiAgdmlzaXRDbGFzc1Byb3RvdHlwZShub2RlOiBDbGFzc1Byb3RvdHlwZSk6IHZvaWQge1xuICAgIGlmIChub2RlLnBhcmVudCBpbnN0YW5jZW9mIENsYXNzKSB7XG4gICAgICBub2RlLnBhcmVudC52aXNpdCh0aGlzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52aXNpdChub2RlLmluc3RhbmNlTWVtYmVycyk7XG4gICAgfVxuICB9XG4gIHZpc2l0Q2xhc3Mobm9kZTogQ2xhc3MpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KG5vZGUubWVtYmVycyk7XG4gIH1cbiAgdmlzaXRJbnRlcmZhY2VQcm90b3R5cGUobm9kZTogSW50ZXJmYWNlUHJvdG90eXBlKTogdm9pZCB7fVxuICB2aXNpdEludGVyZmFjZShub2RlOiBJbnRlcmZhY2UpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KG5vZGUucHJvdG90eXBlLmluc3RhbmNlTWVtYmVycyk7XG4gIH1cbn1cbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/element/index.js b/lib/visitor/dist/element/index.js
new file mode 100644
index 0000000000..58861ab9de
--- /dev/null
+++ b/lib/visitor/dist/element/index.js
@@ -0,0 +1,7 @@
+"use strict";
+function __export(m) {
+    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+Object.defineProperty(exports, "__esModule", { value: true });
+__export(require("./base"));
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZWxlbWVudC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDRCQUF1QiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gXCIuL2Jhc2VcIjtcbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/index.js b/lib/visitor/dist/index.js
new file mode 100644
index 0000000000..9668b7c4fc
--- /dev/null
+++ b/lib/visitor/dist/index.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBpbnRlcmZhY2UgV3JpdGVyIHtcbiAgd3JpdGUoc3RyOiBzdHJpbmcpOiB2b2lkO1xufVxuIl19
\ No newline at end of file
diff --git a/lib/visitor/dist/instances/astPrinter.js b/lib/visitor/dist/instances/astPrinter.js
new file mode 100644
index 0000000000..3a268d669c
--- /dev/null
+++ b/lib/visitor/dist/instances/astPrinter.js
@@ -0,0 +1,407 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var __values = (this && this.__values) || function (o) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+    if (m) return m.call(o);
+    return {
+        next: function () {
+            if (o && i >= o.length) o = void 0;
+            return { value: o && o[i++], done: !o };
+        }
+    };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var assemblyscript_1 = require("assemblyscript");
+var ast_1 = require("../ast");
+var PrinterVisitor = /** @class */ (function (_super) {
+    __extends(PrinterVisitor, _super);
+    function PrinterVisitor() {
+        var _this = _super !== null && _super.apply(this, arguments) || this;
+        _this.depth = 0;
+        _this.sb = [];
+        return _this;
+    }
+    PrinterVisitor.prototype.write = function (str, newline) {
+        if (newline === void 0) { newline = true; }
+        this.writer.write("  ".repeat(this.depth) + str + (newline ? "\n" : " "));
+    };
+    PrinterVisitor.prototype.flush = function (seperator) {
+        var res = this.sb.join(seperator);
+        this.sb.length = 0;
+        return res;
+    };
+    PrinterVisitor.prototype.visitSource = function (node) {
+        this.write("Source: " + node.normalizedPath);
+        _super.prototype.visitSource.call(this, node);
+    };
+    PrinterVisitor.prototype.visitTypeNode = function (node) {
+        this.write("TypeNode: " + node.kind.toString());
+        _super.prototype.visitTypeNode.call(this, node);
+    };
+    PrinterVisitor.prototype.visitFunctionTypeNode = function (node) {
+        var e_1, _a;
+        this.write("FunctionTypeNode: ", false);
+        try {
+            for (var _b = __values(node.parameters), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var param = _c.value;
+                param.visit(this);
+            }
+        }
+        catch (e_1_1) { e_1 = { error: e_1_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_1) throw e_1.error; }
+        }
+        this.write("(" + this.flush(", ") + ") -> ");
+        this.write("return type: ", false);
+        node.returnType.visit(this);
+    };
+    PrinterVisitor.prototype.visitTypeParameter = function (node) {
+        this.write("TypeParameter ", false);
+        node.name.visit(this);
+    };
+    PrinterVisitor.prototype.visitIdentifierExpression = function (node) {
+        this.sb.push(node.symbol);
+        _super.prototype.visitIdentifierExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitArrayLiteralExpression = function (node) {
+        this.write("ArrayLiteralExpression: ", false);
+        _super.prototype.visitArrayLiteralExpression.call(this, node);
+        this.write("[" + this.flush(", ") + "]");
+    };
+    PrinterVisitor.prototype.visitObjectLiteralExpression = function (node) {
+        this.write("ObjectLiteralExpression: ");
+        _super.prototype.visitObjectLiteralExpression.call(this, node);
+        this.depth++;
+        this.write("{");
+        for (var i = 0; i < this.sb.length; i += 2) {
+            this.write("  " + this.sb[i] + ": " + this.sb[i + 1]);
+        }
+        this.write("}");
+        this.depth--;
+    };
+    PrinterVisitor.prototype.visitAssertionExpression = function (node) {
+        this.write("AssertionExpression: ", false);
+        _super.prototype.visitAssertionExpression.call(this, node);
+        this.write(this.flush(" "));
+    };
+    PrinterVisitor.prototype.visitBinaryExpression = function (node) {
+        this.write("BinaryExpression: ", false);
+        _super.prototype.visitBinaryExpression.call(this, node);
+        this.sb.push(this.flush(assemblyscript_1.operatorTokenToString(node.operator)));
+    };
+    PrinterVisitor.prototype.visitCallExpression = function (node) {
+        this.write("CallExpression");
+        _super.prototype.visitCallExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitClassExpression = function (node) {
+        this.write("ClassExpression");
+        _super.prototype.visitClassExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitCommaExpression = function (node) {
+        this.write("CommaExpression");
+        _super.prototype.visitCommaExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitElementAccessExpression = function (node) {
+        this.write("ElementAccessExpression");
+        _super.prototype.visitElementAccessExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitFunctionExpression = function (node) {
+        this.write("FunctionExpression");
+        _super.prototype.visitFunctionExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitLiteralExpression = function (node) {
+        this.write("LiteralExpression");
+        _super.prototype.visitLiteralExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitFloatLiteralExpression = function (node) {
+        this.write("FloatLiteralExpression");
+        _super.prototype.visitFloatLiteralExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitInstanceOfExpression = function (node) {
+        this.write("InstanceOfExpression");
+        _super.prototype.visitInstanceOfExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitIntegerLiteralExpression = function (node) {
+        this.sb.push(i64_to_string(node.value));
+    };
+    PrinterVisitor.prototype.visitStringLiteral = function (str, singleQuoted) {
+        this.write("StringLiteral");
+        this.sb.push(str);
+    };
+    PrinterVisitor.prototype.visitStringLiteralExpression = function (node) {
+        this.write("StringLiteralExpression");
+        _super.prototype.visitStringLiteralExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitRegexpLiteralExpression = function (node) {
+        this.write("RegexpLiteralExpression");
+        _super.prototype.visitRegexpLiteralExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitNewExpression = function (node) {
+        this.write("NewExpression");
+        _super.prototype.visitNewExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitParenthesizedExpression = function (node) {
+        this.write("ParenthesizedExpression");
+        _super.prototype.visitParenthesizedExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitPropertyAccessExpression = function (node) {
+        this.write("PropertyAccessExpression");
+        _super.prototype.visitPropertyAccessExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitTernaryExpression = function (node) {
+        this.write("TernaryExpression");
+        _super.prototype.visitTernaryExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitUnaryExpression = function (node) {
+        this.write("UnaryExpression");
+        _super.prototype.visitUnaryExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitUnaryPostfixExpression = function (node) {
+        this.write("UnaryPostfixExpression");
+        _super.prototype.visitUnaryPostfixExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitUnaryPrefixExpression = function (node) {
+        this.write("UnaryPrefixExpression");
+        _super.prototype.visitUnaryPrefixExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitSuperExpression = function (node) {
+        this.write("SuperExpression: " + node.symbol);
+        _super.prototype.visitSuperExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitFalseExpression = function (node) {
+        this.write("FalseExpression");
+        _super.prototype.visitFalseExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitTrueExpression = function (node) {
+        this.write("TrueExpression");
+        _super.prototype.visitTrueExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitThisExpression = function (node) {
+        this.write("ThisExpression");
+        _super.prototype.visitThisExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitNullExperssion = function (node) {
+        this.write("NullExperssion");
+        _super.prototype.visitNullExperssion.call(this, node);
+    };
+    PrinterVisitor.prototype.visitConstructorExpression = function (node) {
+        this.write("ConstructorExpression");
+        _super.prototype.visitConstructorExpression.call(this, node);
+    };
+    PrinterVisitor.prototype.visitNodeAndTerminate = function (statement) {
+        this.write("NodeAndTerminate");
+    };
+    PrinterVisitor.prototype.visitBlockStatement = function (node) {
+        this.write("BlockStatement");
+        this.depth++;
+        _super.prototype.visitBlockStatement.call(this, node);
+        this.depth--;
+    };
+    PrinterVisitor.prototype.visitBreakStatement = function (node) {
+        this.write("BreakStatement");
+        _super.prototype.visitBreakStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitContinueStatement = function (node) {
+        this.write("ContinueStatement");
+        _super.prototype.visitContinueStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitClassDeclaration = function (node, isDefault) {
+        var e_2, _a;
+        this.write("ClassDeclaration: " + node.name.symbol);
+        try {
+            for (var _b = __values(node.members), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var member = _c.value;
+                this.depth++;
+                member.visit(this);
+                this.depth--;
+            }
+        }
+        catch (e_2_1) { e_2 = { error: e_2_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_2) throw e_2.error; }
+        }
+    };
+    PrinterVisitor.prototype.visitDoStatement = function (node) {
+        this.write("DoStatement");
+        _super.prototype.visitDoStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitEmptyStatement = function (node) {
+        this.write("EmptyStatement");
+        _super.prototype.visitEmptyStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitEnumDeclaration = function (node, isDefault) {
+        this.write("EnumDeclaration: " + node.name);
+        _super.prototype.visitEnumDeclaration.call(this, node);
+    };
+    PrinterVisitor.prototype.visitEnumValueDeclaration = function (node) {
+        this.write("EnumValueDeclaration");
+        _super.prototype.visitEnumValueDeclaration.call(this, node);
+    };
+    PrinterVisitor.prototype.visitExportImportStatement = function (node) {
+        this.write("ExportImportStatement");
+        _super.prototype.visitExportImportStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitExportMember = function (node) {
+        this.write("ExportMember");
+        _super.prototype.visitExportMember.call(this, node);
+    };
+    PrinterVisitor.prototype.visitExportStatement = function (node) {
+        this.write("ExportStatement");
+        _super.prototype.visitExportStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitExportDefaultStatement = function (node) {
+        this.write("ExportDefaultStatement");
+        _super.prototype.visitExportDefaultStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitExpressionStatement = function (node) {
+        this.write("ExpressionStatement: ");
+        _super.prototype.visitExpressionStatement.call(this, node);
+        this.write(this.flush(" "));
+    };
+    PrinterVisitor.prototype.visitFieldDeclaration = function (node) {
+        this.write("FieldDeclaration: ", false);
+        node.name.visit(this);
+        node.type.visit(this);
+        this.write(this.flush(": "));
+    };
+    PrinterVisitor.prototype.visitForStatement = function (node) {
+        this.write("ForStatement");
+        _super.prototype.visitForStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitFunctionDeclaration = function (node, isDefault) {
+        this.write("FunctionDeclaration: " + node.name.symbol, false);
+        node.signature.visit(this);
+    };
+    PrinterVisitor.prototype.visitFunctionCommon = function (node) {
+        this.write("FunctionCommon");
+        _super.prototype.visitFunctionCommon.call(this, node);
+    };
+    PrinterVisitor.prototype.visitIfStatement = function (node) {
+        this.write("IfStatement");
+        _super.prototype.visitIfStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitImportDeclaration = function (node) {
+        this.write("ImportDeclaration");
+        _super.prototype.visitImportDeclaration.call(this, node);
+    };
+    PrinterVisitor.prototype.visitImportStatement = function (node) {
+        this.write("ImportStatement: " + node.internalPath);
+        _super.prototype.visitImportStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitIndexSignatureDeclaration = function (node) {
+        this.write("IndexSignatureDeclaration");
+        _super.prototype.visitIndexSignatureDeclaration.call(this, node);
+    };
+    PrinterVisitor.prototype.visitInterfaceDeclaration = function (node, isDefault) {
+        this.write("InterfaceDeclaration", false);
+        node.name.visit(this);
+        this.write(this.flush(""), false);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+            this.write("<" + this.flush(", ") + "> ", false);
+        }
+        this.visit(node.implementsTypes);
+        if (this.sb.length > 0) {
+            this.write("implements " + this.flush(", "));
+        }
+        if (node.extendsType) {
+            node.extendsType.visit(this);
+            this.write("extends " + this.flush(""), false);
+        }
+        this.write("");
+        this.depth++;
+        this.visit(node.members);
+        this.depth--;
+    };
+    PrinterVisitor.prototype.visitMethodDeclaration = function (node) {
+        this.write("MethodDeclaration: " + node.name.symbol);
+        this.depth++;
+        if (node.body)
+            node.body.visit(this);
+        this.depth--;
+    };
+    PrinterVisitor.prototype.visitNamespaceDeclaration = function (node, isDefault) {
+        this.write("NamespaceDeclaration");
+        _super.prototype.visitNamespaceDeclaration.call(this, node);
+    };
+    PrinterVisitor.prototype.visitReturnStatement = function (node) {
+        this.write("ReturnStatement");
+        _super.prototype.visitReturnStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitSwitchCase = function (node) {
+        this.write("SwitchCase");
+        _super.prototype.visitSwitchCase.call(this, node);
+    };
+    PrinterVisitor.prototype.visitSwitchStatement = function (node) {
+        this.write("SwitchStatement");
+        _super.prototype.visitSwitchStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitThrowStatement = function (node) {
+        this.write("ThrowStatement");
+        _super.prototype.visitThrowStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitTryStatement = function (node) {
+        this.write("TryStatement");
+        _super.prototype.visitTryStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitTypeDeclaration = function (node) {
+        this.write("TypeDeclaration");
+        _super.prototype.visitTypeDeclaration.call(this, node);
+    };
+    PrinterVisitor.prototype.visitVariableDeclaration = function (node) {
+        this.write("VariableDeclaration: ", false);
+        node.name.visit(this);
+        if (node.type)
+            node.type.visit(this);
+        var name = this.flush(": ");
+        if (node.initializer)
+            node.initializer.visit(this);
+        var initializer = this.flush(" ");
+        this.write(name + (node.initializer ? " = " + initializer : "") + ";");
+    };
+    PrinterVisitor.prototype.visitVariableStatement = function (node) {
+        this.write("VariableStatement");
+        _super.prototype.visitVariableStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitWhileStatement = function (node) {
+        this.write("WhileStatement");
+        _super.prototype.visitWhileStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitVoidStatement = function (node) {
+        this.write("VoidStatement");
+        _super.prototype.visitVoidStatement.call(this, node);
+    };
+    PrinterVisitor.prototype.visitComment = function (node) {
+        this.write("Comment");
+        _super.prototype.visitComment.call(this, node);
+    };
+    PrinterVisitor.prototype.visitDecoratorNode = function (node) {
+        this.write("DecoratorNode");
+        _super.prototype.visitDecoratorNode.call(this, node);
+    };
+    PrinterVisitor.prototype.visitParameter = function (node) {
+        this.write("Parameter " + node.name.symbol + ":", false);
+        node.type.visit(this);
+    };
+    return PrinterVisitor;
+}(ast_1.BaseVisitor));
+exports.PrinterVisitor = PrinterVisitor;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN0UHJpbnRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnN0YW5jZXMvYXN0UHJpbnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBMkV3QjtBQUN4Qiw4QkFBcUM7QUFFckM7SUFBb0Msa0NBQVc7SUFBL0M7UUFBQSxxRUErWkM7UUE5WkMsV0FBSyxHQUFXLENBQUMsQ0FBQztRQUNsQixRQUFFLEdBQWEsRUFBRSxDQUFDOztJQTZacEIsQ0FBQztJQTFaQyw4QkFBSyxHQUFMLFVBQU0sR0FBVyxFQUFFLE9BQXVCO1FBQXZCLHdCQUFBLEVBQUEsY0FBdUI7UUFDeEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUUsQ0FBQztJQUVELDhCQUFLLEdBQUwsVUFBTSxTQUFpQjtRQUNyQixJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDbkIsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQsb0NBQVcsR0FBWCxVQUFZLElBQVk7UUFDdEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzdDLGlCQUFNLFdBQVcsWUFBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsc0NBQWEsR0FBYixVQUFjLElBQWM7UUFDMUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUs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cG9ydCB7XG4gIEFTVFZpc2l0b3IsXG4gIFNvdXJjZSxcbiAgVHlwZU5vZGUsXG4gIFR5cGVOYW1lLFxuICBOYW1lZFR5cGVOb2RlLFxuICBGdW5jdGlvblR5cGVOb2RlLFxuICBUeXBlUGFyYW1ldGVyTm9kZSxcbiAgSWRlbnRpZmllckV4cHJlc3Npb24sXG4gIEFycmF5TGl0ZXJhbEV4cHJlc3Npb24sXG4gIE9iamVjdExpdGVyYWxFeHByZXNzaW9uLFxuICBBc3NlcnRpb25FeHByZXNzaW9uLFxuICBCaW5hcnlFeHByZXNzaW9uLFxuICBDYWxsRXhwcmVzc2lvbixcbiAgQ2xhc3NFeHByZXNzaW9uLFxuICBDb21tYUV4cHJlc3Npb24sXG4gIEVsZW1lbnRBY2Nlc3NFeHByZXNzaW9uLFxuICBGdW5jdGlvbkV4cHJlc3Npb24sXG4gIExpdGVyYWxFeHByZXNzaW9uLFxuICBGbG9hdExpdGVyYWxFeHByZXNzaW9uLFxuICBJbnN0YW5jZU9mRXhwcmVzc2lvbixcbiAgSW50ZWdlckxpdGVyYWxFeHByZXNzaW9uLFxuICBTdHJpbmdMaXRlcmFsRXhwcmVzc2lvbixcbiAgUmVnZXhwTGl0ZXJhbEV4cHJlc3Npb24sXG4gIE5ld0V4cHJlc3Npb24sXG4gIFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uLFxuICBQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24sXG4gIFRlcm5hcnlFeHByZXNzaW9uLFxuICBVbmFyeUV4cHJlc3Npb24sXG4gIFVuYXJ5UG9zdGZpeEV4cHJlc3Npb24sXG4gIFVuYXJ5UHJlZml4RXhwcmVzc2lvbixcbiAgU3VwZXJFeHByZXNzaW9uLFxuICBGYWxzZUV4cHJlc3Npb24sXG4gIFRydWVFeHByZXNzaW9uLFxuICBUaGlzRXhwcmVzc2lvbixcbiAgTnVsbEV4cHJlc3Npb24sXG4gIENvbnN0cnVjdG9yRXhwcmVzc2lvbixcbiAgU3RhdGVtZW50LFxuICBCbG9ja1N0YXRlbWVudCxcbiAgQnJlYWtTdGF0ZW1lbnQsXG4gIENvbnRpbnVlU3RhdGVtZW50LFxuICBDbGFzc0RlY2xhcmF0aW9uLFxuICBEb1N0YXRlbWVudCxcbiAgRW1wdHlTdGF0ZW1lbnQsXG4gIEVudW1EZWNsYXJhdGlvbixcbiAgRW51bVZhbHVlRGVjbGFyYXRpb24sXG4gIEV4cG9ydEltcG9ydFN0YXRlbWVudCxcbiAgRXhwb3J0TWVtYmVyLFxuICBFeHBvcnRTdGF0ZW1lbnQsXG4gIEV4cG9ydERlZmF1bHRTdGF0ZW1lbnQsXG4gIEV4cHJlc3Npb25TdGF0ZW1lbnQsXG4gIEZpZWxkRGVjbGFyYXRpb24sXG4gIEZvclN0YXRlbWVudCxcbiAgRnVuY3Rpb25EZWNsYXJhdGlvbixcbiAgSWZTdGF0ZW1lbnQsXG4gIEltcG9ydERlY2xhcmF0aW9uLFxuICBJbXBvcnRTdGF0ZW1lbnQsXG4gIEluZGV4U2lnbmF0dXJlRGVjbGFyYXRpb24sXG4gIEludGVyZmFjZURlY2xhcmF0aW9uLFxuICBNZXRob2REZWNsYXJhdGlvbixcbiAgTmFtZXNwYWNlRGVjbGFyYXRpb24sXG4gIFJldHVyblN0YXRlbWVudCxcbiAgU3dpdGNoQ2FzZSxcbiAgU3dpdGNoU3RhdGVtZW50LFxuICBUaHJvd1N0YXRlbWVudCxcbiAgVHJ5U3RhdGVtZW50LFxuICBUeXBlRGVjbGFyYXRpb24sXG4gIFZhcmlhYmxlRGVjbGFyYXRpb24sXG4gIFZhcmlhYmxlU3RhdGVtZW50LFxuICBXaGlsZVN0YXRlbWVudCxcbiAgVm9pZFN0YXRlbWVudCxcbiAgQ29tbWVudE5vZGUsXG4gIERlY29yYXRvck5vZGUsXG4gIFBhcmFtZXRlck5vZGUsXG4gIG9wZXJhdG9yVG9rZW5Ub1N0cmluZ1xufSBmcm9tIFwiYXNzZW1ibHlzY3JpcHRcIjtcbmltcG9ydCB7IEJhc2VWaXNpdG9yIH0gZnJvbSBcIi4uL2FzdFwiO1xuXG5leHBvcnQgY2xhc3MgUHJpbnRlclZpc2l0b3IgZXh0ZW5kcyBCYXNlVmlzaXRvciBpbXBsZW1lbnRzIEFTVFZpc2l0b3Ige1xuICBkZXB0aDogbnVtYmVyID0gMDtcbiAgc2I6IHN0cmluZ1tdID0gW107XG5cblxuICB3cml0ZShzdHI6IHN0cmluZywgbmV3bGluZTogYm9vbGVhbiA9IHRydWUpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlci53cml0ZShcIiAgXCIucmVwZWF0KHRoaXMuZGVwdGgpICsgc3RyICsgKG5ld2xpbmUgPyBcIlxcblwiIDogXCIgXCIpKTtcbiAgfVxuXG4gIGZsdXNoKHNlcGVyYXRvcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBsZXQgcmVzID0gdGhpcy5zYi5qb2luKHNlcGVyYXRvcik7XG4gICAgdGhpcy5zYi5sZW5ndGggPSAwO1xuICAgIHJldHVybiByZXM7XG4gIH1cblxuICB2aXNpdFNvdXJjZShub2RlOiBTb3VyY2UpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiU291cmNlOiBcIiArIG5vZGUubm9ybWFsaXplZFBhdGgpO1xuICAgIHN1cGVyLnZpc2l0U291cmNlKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRUeXBlTm9kZShub2RlOiBUeXBlTm9kZSk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJUeXBlTm9kZTogXCIgKyBub2RlLmtpbmQudG9TdHJpbmcoKSk7XG4gICAgc3VwZXIudmlzaXRUeXBlTm9kZShub2RlKTtcbiAgfVxuXG4gIHZpc2l0RnVuY3Rpb25UeXBlTm9kZShub2RlOiBGdW5jdGlvblR5cGVOb2RlKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkZ1bmN0aW9uVHlwZU5vZGU6IFwiLCBmYWxzZSk7XG4gICAgZm9yIChsZXQgcGFyYW0gb2Ygbm9kZS5wYXJhbWV0ZXJzKSB7XG4gICAgICBwYXJhbS52aXNpdCh0aGlzKTtcbiAgICB9XG4gICAgdGhpcy53cml0ZShcIihcIiArIHRoaXMuZmx1c2goXCIsIFwiKSArIFwiKSAtPiBcIik7XG4gICAgdGhpcy53cml0ZShcInJldHVybiB0eXBlOiBcIiwgZmFsc2UpO1xuICAgIG5vZGUucmV0dXJuVHlwZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0VHlwZVBhcmFtZXRlcihub2RlOiBUeXBlUGFyYW1ldGVyTm9kZSk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJUeXBlUGFyYW1ldGVyIFwiLCBmYWxzZSk7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRJZGVudGlmaWVyRXhwcmVzc2lvbihub2RlOiBJZGVudGlmaWVyRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMuc2IucHVzaChub2RlLnN5bWJvbCk7XG4gICAgc3VwZXIudmlzaXRJZGVudGlmaWVyRXhwcmVzc2lvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0QXJyYXlMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBBcnJheUxpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkFycmF5TGl0ZXJhbEV4cHJlc3Npb246IFwiLCBmYWxzZSk7XG4gICAgc3VwZXIudmlzaXRBcnJheUxpdGVyYWxFeHByZXNzaW9uKG5vZGUpO1xuICAgIHRoaXMud3JpdGUoXCJbXCIgKyB0aGlzLmZsdXNoKFwiLCBcIikgKyBcIl1cIik7XG4gIH1cblxuICB2aXNpdE9iamVjdExpdGVyYWxFeHByZXNzaW9uKG5vZGU6IE9iamVjdExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIk9iamVjdExpdGVyYWxFeHByZXNzaW9uOiBcIik7XG4gICAgc3VwZXIudmlzaXRPYmplY3RMaXRlcmFsRXhwcmVzc2lvbihub2RlKTtcbiAgICB0aGlzLmRlcHRoKys7XG5cbiAgICB0aGlzLndyaXRlKFwie1wiKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc2IubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgIHRoaXMud3JpdGUoXCIgIFwiICsgdGhpcy5zYltpXSArIFwiOiBcIiArIHRoaXMuc2JbaSArIDFdKTtcbiAgICB9XG4gICAgdGhpcy53cml0ZShcIn1cIik7XG4gICAgdGhpcy5kZXB0aC0tO1xuICB9XG5cbiAgdmlzaXRBc3NlcnRpb25FeHByZXNzaW9uKG5vZGU6IEFzc2VydGlvbkV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiQXNzZXJ0aW9uRXhwcmVzc2lvbjogXCIsIGZhbHNlKTtcbiAgICBzdXBlci52aXNpdEFzc2VydGlvbkV4cHJlc3Npb24obm9kZSk7XG4gICAgdGhpcy53cml0ZSh0aGlzLmZsdXNoKFwiIFwiKSk7XG4gIH1cblxuICB2aXNpdEJpbmFyeUV4cHJlc3Npb24obm9kZTogQmluYXJ5RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJCaW5hcnlFeHByZXNzaW9uOiBcIiwgZmFsc2UpO1xuICAgIHN1cGVyLnZpc2l0QmluYXJ5RXhwcmVzc2lvbihub2RlKTtcbiAgICB0aGlzLnNiLnB1c2godGhpcy5mbHVzaChvcGVyYXRvclRva2VuVG9TdHJpbmcobm9kZS5vcGVyYXRvcikpKTtcbiAgfVxuXG4gIHZpc2l0Q2FsbEV4cHJlc3Npb24obm9kZTogQ2FsbEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiQ2FsbEV4cHJlc3Npb25cIik7XG4gICAgc3VwZXIudmlzaXRDYWxsRXhwcmVzc2lvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0Q2xhc3NFeHByZXNzaW9uKG5vZGU6IENsYXNzRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJDbGFzc0V4cHJlc3Npb25cIik7XG4gICAgc3VwZXIudmlzaXRDbGFzc0V4cHJlc3Npb24obm9kZSk7XG4gIH1cblxuICB2aXNpdENvbW1hRXhwcmVzc2lvbihub2RlOiBDb21tYUV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiQ29tbWFFeHByZXNzaW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0Q29tbWFFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRFbGVtZW50QWNjZXNzRXhwcmVzc2lvbihub2RlOiBFbGVtZW50QWNjZXNzRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJFbGVtZW50QWNjZXNzRXhwcmVzc2lvblwiKTtcbiAgICBzdXBlci52aXNpdEVsZW1lbnRBY2Nlc3NFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRGdW5jdGlvbkV4cHJlc3Npb24obm9kZTogRnVuY3Rpb25FeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkZ1bmN0aW9uRXhwcmVzc2lvblwiKTtcbiAgICBzdXBlci52aXNpdEZ1bmN0aW9uRXhwcmVzc2lvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0TGl0ZXJhbEV4cHJlc3Npb24obm9kZTogTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiTGl0ZXJhbEV4cHJlc3Npb25cIik7XG4gICAgc3VwZXIudmlzaXRMaXRlcmFsRXhwcmVzc2lvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0RmxvYXRMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBGbG9hdExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkZsb2F0TGl0ZXJhbEV4cHJlc3Npb25cIik7XG4gICAgc3VwZXIudmlzaXRGbG9hdExpdGVyYWxFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRJbnN0YW5jZU9mRXhwcmVzc2lvbihub2RlOiBJbnN0YW5jZU9mRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJJbnN0YW5jZU9mRXhwcmVzc2lvblwiKTtcbiAgICBzdXBlci52aXNpdEluc3RhbmNlT2ZFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRJbnRlZ2VyTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogSW50ZWdlckxpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy5zYi5wdXNoKGk2NF90b19zdHJpbmcobm9kZS52YWx1ZSkpO1xuICB9XG5cbiAgdmlzaXRTdHJpbmdMaXRlcmFsKHN0cjogc3RyaW5nLCBzaW5nbGVRdW90ZWQ/OiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlN0cmluZ0xpdGVyYWxcIik7XG4gICAgdGhpcy5zYi5wdXNoKHN0cik7XG4gIH1cblxuICB2aXNpdFN0cmluZ0xpdGVyYWxFeHByZXNzaW9uKG5vZGU6IFN0cmluZ0xpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlN0cmluZ0xpdGVyYWxFeHByZXNzaW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0U3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24obm9kZSk7XG4gIH1cblxuICB2aXNpdFJlZ2V4cExpdGVyYWxFeHByZXNzaW9uKG5vZGU6IFJlZ2V4cExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlJlZ2V4cExpdGVyYWxFeHByZXNzaW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0UmVnZXhwTGl0ZXJhbEV4cHJlc3Npb24obm9kZSk7XG4gIH1cblxuICB2aXNpdE5ld0V4cHJlc3Npb24obm9kZTogTmV3RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJOZXdFeHByZXNzaW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0TmV3RXhwcmVzc2lvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0UGFyZW50aGVzaXplZEV4cHJlc3Npb24obm9kZTogUGFyZW50aGVzaXplZEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiUGFyZW50aGVzaXplZEV4cHJlc3Npb25cIik7XG4gICAgc3VwZXIudmlzaXRQYXJlbnRoZXNpemVkRXhwcmVzc2lvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0UHJvcGVydHlBY2Nlc3NFeHByZXNzaW9uKG5vZGU6IFByb3BlcnR5QWNjZXNzRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb25cIik7XG4gICAgc3VwZXIudmlzaXRQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24obm9kZSk7XG4gIH1cblxuICB2aXNpdFRlcm5hcnlFeHByZXNzaW9uKG5vZGU6IFRlcm5hcnlFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlRlcm5hcnlFeHByZXNzaW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0VGVybmFyeUV4cHJlc3Npb24obm9kZSk7XG4gIH1cblxuICB2aXNpdFVuYXJ5RXhwcmVzc2lvbihub2RlOiBVbmFyeUV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiVW5hcnlFeHByZXNzaW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0VW5hcnlFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRVbmFyeVBvc3RmaXhFeHByZXNzaW9uKG5vZGU6IFVuYXJ5UG9zdGZpeEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiVW5hcnlQb3N0Zml4RXhwcmVzc2lvblwiKTtcbiAgICBzdXBlci52aXNpdFVuYXJ5UG9zdGZpeEV4cHJlc3Npb24obm9kZSk7XG4gIH1cblxuICB2aXNpdFVuYXJ5UHJlZml4RXhwcmVzc2lvbihub2RlOiBVbmFyeVByZWZpeEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiVW5hcnlQcmVmaXhFeHByZXNzaW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0VW5hcnlQcmVmaXhFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRTdXBlckV4cHJlc3Npb24obm9kZTogU3VwZXJFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlN1cGVyRXhwcmVzc2lvbjogXCIgKyBub2RlLnN5bWJvbCk7XG4gICAgc3VwZXIudmlzaXRTdXBlckV4cHJlc3Npb24obm9kZSk7XG4gIH1cblxuICB2aXNpdEZhbHNlRXhwcmVzc2lvbihub2RlOiBGYWxzZUV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiRmFsc2VFeHByZXNzaW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0RmFsc2VFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRUcnVlRXhwcmVzc2lvbihub2RlOiBUcnVlRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJUcnVlRXhwcmVzc2lvblwiKTtcbiAgICBzdXBlci52aXNpdFRydWVFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRUaGlzRXhwcmVzc2lvbihub2RlOiBUaGlzRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJUaGlzRXhwcmVzc2lvblwiKTtcbiAgICBzdXBlci52aXNpdFRoaXNFeHByZXNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXROdWxsRXhwZXJzc2lvbihub2RlOiBOdWxsRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJOdWxsRXhwZXJzc2lvblwiKTtcbiAgICBzdXBlci52aXNpdE51bGxFeHBlcnNzaW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRDb25zdHJ1Y3RvckV4cHJlc3Npb24obm9kZTogQ29uc3RydWN0b3JFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkNvbnN0cnVjdG9yRXhwcmVzc2lvblwiKTtcbiAgICBzdXBlci52aXNpdENvbnN0cnVjdG9yRXhwcmVzc2lvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0Tm9kZUFuZFRlcm1pbmF0ZShzdGF0ZW1lbnQ6IFN0YXRlbWVudCk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJOb2RlQW5kVGVybWluYXRlXCIpO1xuICB9XG5cbiAgdmlzaXRCbG9ja1N0YXRlbWVudChub2RlOiBCbG9ja1N0YXRlbWVudCk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJCbG9ja1N0YXRlbWVudFwiKTtcbiAgICB0aGlzLmRlcHRoKys7XG4gICAgc3VwZXIudmlzaXRCbG9ja1N0YXRlbWVudChub2RlKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cblxuICB2aXNpdEJyZWFrU3RhdGVtZW50KG5vZGU6IEJyZWFrU3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkJyZWFrU3RhdGVtZW50XCIpO1xuICAgIHN1cGVyLnZpc2l0QnJlYWtTdGF0ZW1lbnQobm9kZSk7XG4gIH1cblxuICB2aXNpdENvbnRpbnVlU3RhdGVtZW50KG5vZGU6IENvbnRpbnVlU3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkNvbnRpbnVlU3RhdGVtZW50XCIpO1xuICAgIHN1cGVyLnZpc2l0Q29udGludWVTdGF0ZW1lbnQobm9kZSk7XG4gIH1cblxuICB2aXNpdENsYXNzRGVjbGFyYXRpb24obm9kZTogQ2xhc3NEZWNsYXJhdGlvbiwgaXNEZWZhdWx0PzogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJDbGFzc0RlY2xhcmF0aW9uOiBcIiArIG5vZGUubmFtZS5zeW1ib2wpO1xuICAgIGZvciAoY29uc3QgbWVtYmVyIG9mIG5vZGUubWVtYmVycykge1xuICAgICAgdGhpcy5kZXB0aCsrO1xuICAgICAgbWVtYmVyLnZpc2l0KHRoaXMpO1xuICAgICAgdGhpcy5kZXB0aC0tO1xuICAgIH1cbiAgfVxuXG4gIHZpc2l0RG9TdGF0ZW1lbnQobm9kZTogRG9TdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiRG9TdGF0ZW1lbnRcIik7XG4gICAgc3VwZXIudmlzaXREb1N0YXRlbWVudChub2RlKTtcbiAgfVxuXG4gIHZpc2l0RW1wdHlTdGF0ZW1lbnQobm9kZTogRW1wdHlTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiRW1wdHlTdGF0ZW1lbnRcIik7XG4gICAgc3VwZXIudmlzaXRFbXB0eVN0YXRlbWVudChub2RlKTtcbiAgfVxuXG4gIHZpc2l0RW51bURlY2xhcmF0aW9uKG5vZGU6IEVudW1EZWNsYXJhdGlvbiwgaXNEZWZhdWx0PzogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJFbnVtRGVjbGFyYXRpb246IFwiICsgbm9kZS5uYW1lKTtcbiAgICBzdXBlci52aXNpdEVudW1EZWNsYXJhdGlvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0RW51bVZhbHVlRGVjbGFyYXRpb24obm9kZTogRW51bVZhbHVlRGVjbGFyYXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiRW51bVZhbHVlRGVjbGFyYXRpb25cIik7XG4gICAgc3VwZXIudmlzaXRFbnVtVmFsdWVEZWNsYXJhdGlvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0RXhwb3J0SW1wb3J0U3RhdGVtZW50KG5vZGU6IEV4cG9ydEltcG9ydFN0YXRlbWVudCk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJFeHBvcnRJbXBvcnRTdGF0ZW1lbnRcIik7XG4gICAgc3VwZXIudmlzaXRFeHBvcnRJbXBvcnRTdGF0ZW1lbnQobm9kZSk7XG4gIH1cblxuICB2aXNpdEV4cG9ydE1lbWJlcihub2RlOiBFeHBvcnRNZW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiRXhwb3J0TWVtYmVyXCIpO1xuICAgIHN1cGVyLnZpc2l0RXhwb3J0TWVtYmVyKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRFeHBvcnRTdGF0ZW1lbnQobm9kZTogRXhwb3J0U3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkV4cG9ydFN0YXRlbWVudFwiKTtcbiAgICBzdXBlci52aXNpdEV4cG9ydFN0YXRlbWVudChub2RlKTtcbiAgfVxuXG4gIHZpc2l0RXhwb3J0RGVmYXVsdFN0YXRlbWVudChub2RlOiBFeHBvcnREZWZhdWx0U3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkV4cG9ydERlZmF1bHRTdGF0ZW1lbnRcIik7XG4gICAgc3VwZXIudmlzaXRFeHBvcnREZWZhdWx0U3RhdGVtZW50KG5vZGUpO1xuICB9XG5cbiAgdmlzaXRFeHByZXNzaW9uU3RhdGVtZW50KG5vZGU6IEV4cHJlc3Npb25TdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiRXhwcmVzc2lvblN0YXRlbWVudDogXCIpO1xuICAgIHN1cGVyLnZpc2l0RXhwcmVzc2lvblN0YXRlbWVudChub2RlKTtcbiAgICB0aGlzLndyaXRlKHRoaXMuZmx1c2goXCIgXCIpKTtcbiAgfVxuXG4gIHZpc2l0RmllbGREZWNsYXJhdGlvbihub2RlOiBGaWVsZERlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkZpZWxkRGVjbGFyYXRpb246IFwiLCBmYWxzZSk7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUudHlwZSEudmlzaXQodGhpcyk7XG4gICAgdGhpcy53cml0ZSh0aGlzLmZsdXNoKFwiOiBcIikpO1xuICB9XG5cbiAgdmlzaXRGb3JTdGF0ZW1lbnQobm9kZTogRm9yU3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkZvclN0YXRlbWVudFwiKTtcbiAgICBzdXBlci52aXNpdEZvclN0YXRlbWVudChub2RlKTtcbiAgfVxuXG4gIHZpc2l0RnVuY3Rpb25EZWNsYXJhdGlvbihcbiAgICBub2RlOiBGdW5jdGlvbkRlY2xhcmF0aW9uLFxuICAgIGlzRGVmYXVsdD86IGJvb2xlYW5cbiAgKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkZ1bmN0aW9uRGVjbGFyYXRpb246IFwiICsgbm9kZS5uYW1lLnN5bWJvbCwgZmFsc2UpO1xuICAgIG5vZGUuc2lnbmF0dXJlLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRGdW5jdGlvbkNvbW1vbihub2RlOiBGdW5jdGlvbkRlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkZ1bmN0aW9uQ29tbW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0RnVuY3Rpb25Db21tb24obm9kZSk7XG4gIH1cbiAgdmlzaXRJZlN0YXRlbWVudChub2RlOiBJZlN0YXRlbWVudCk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJJZlN0YXRlbWVudFwiKTtcbiAgICBzdXBlci52aXNpdElmU3RhdGVtZW50KG5vZGUpO1xuICB9XG5cbiAgdmlzaXRJbXBvcnREZWNsYXJhdGlvbihub2RlOiBJbXBvcnREZWNsYXJhdGlvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJJbXBvcnREZWNsYXJhdGlvblwiKTtcbiAgICBzdXBlci52aXNpdEltcG9ydERlY2xhcmF0aW9uKG5vZGUpO1xuICB9XG5cbiAgdmlzaXRJbXBvcnRTdGF0ZW1lbnQobm9kZTogSW1wb3J0U3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkltcG9ydFN0YXRlbWVudDogXCIgKyBub2RlLmludGVybmFsUGF0aCk7XG4gICAgc3VwZXIudmlzaXRJbXBvcnRTdGF0ZW1lbnQobm9kZSk7XG4gIH1cblxuICB2aXNpdEluZGV4U2lnbmF0dXJlRGVjbGFyYXRpb24obm9kZTogSW5kZXhTaWduYXR1cmVEZWNsYXJhdGlvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJJbmRleFNpZ25hdHVyZURlY2xhcmF0aW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0SW5kZXhTaWduYXR1cmVEZWNsYXJhdGlvbihub2RlKTtcbiAgfVxuXG4gIHZpc2l0SW50ZXJmYWNlRGVjbGFyYXRpb24oXG4gICAgbm9kZTogSW50ZXJmYWNlRGVjbGFyYXRpb24sXG4gICAgaXNEZWZhdWx0PzogYm9vbGVhblxuICApOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiSW50ZXJmYWNlRGVjbGFyYXRpb25cIiwgZmFsc2UpO1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLndyaXRlKHRoaXMuZmx1c2goXCJcIiksIGZhbHNlKTtcbiAgICBpZiAobm9kZS5pc0dlbmVyaWMpIHtcbiAgICAgIHRoaXMudmlzaXQobm9kZS50eXBlUGFyYW1ldGVycyk7XG4gICAgICB0aGlzLndyaXRlKFwiPFwiICsgdGhpcy5mbHVzaChcIiwgXCIpICsgXCI+IFwiLCBmYWxzZSk7XG4gICAgfVxuICAgIHRoaXMudmlzaXQobm9kZS5pbXBsZW1lbnRzVHlwZXMpO1xuICAgIGlmICh0aGlzLnNiLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMud3JpdGUoXCJpbXBsZW1lbnRzIFwiICsgdGhpcy5mbHVzaChcIiwgXCIpKTtcbiAgICB9XG4gICAgaWYgKG5vZGUuZXh0ZW5kc1R5cGUpIHtcbiAgICAgIG5vZGUuZXh0ZW5kc1R5cGUudmlzaXQodGhpcyk7XG4gICAgICB0aGlzLndyaXRlKFwiZXh0ZW5kcyBcIiArIHRoaXMuZmx1c2goXCJcIiksIGZhbHNlKTtcbiAgICB9XG4gICAgdGhpcy53cml0ZShcIlwiKTtcbiAgICB0aGlzLmRlcHRoKys7XG4gICAgdGhpcy52aXNpdChub2RlLm1lbWJlcnMpO1xuICAgIHRoaXMuZGVwdGgtLTtcbiAgfVxuXG4gIHZpc2l0TWV0aG9kRGVjbGFyYXRpb24obm9kZTogTWV0aG9kRGVjbGFyYXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiTWV0aG9kRGVjbGFyYXRpb246IFwiICsgbm9kZS5uYW1lLnN5bWJvbCk7XG4gICAgdGhpcy5kZXB0aCsrO1xuICAgIGlmIChub2RlLmJvZHkpIG5vZGUuYm9keS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cbiAgdmlzaXROYW1lc3BhY2VEZWNsYXJhdGlvbihcbiAgICBub2RlOiBOYW1lc3BhY2VEZWNsYXJhdGlvbixcbiAgICBpc0RlZmF1bHQ/OiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJOYW1lc3BhY2VEZWNsYXJhdGlvblwiKTtcbiAgICBzdXBlci52aXNpdE5hbWVzcGFjZURlY2xhcmF0aW9uKG5vZGUpO1xuICB9XG4gIHZpc2l0UmV0dXJuU3RhdGVtZW50KG5vZGU6IFJldHVyblN0YXRlbWVudCk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJSZXR1cm5TdGF0ZW1lbnRcIik7XG4gICAgc3VwZXIudmlzaXRSZXR1cm5TdGF0ZW1lbnQobm9kZSk7XG4gIH1cbiAgdmlzaXRTd2l0Y2hDYXNlKG5vZGU6IFN3aXRjaENhc2UpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiU3dpdGNoQ2FzZVwiKTtcbiAgICBzdXBlci52aXNpdFN3aXRjaENhc2Uobm9kZSk7XG4gIH1cbiAgdmlzaXRTd2l0Y2hTdGF0ZW1lbnQobm9kZTogU3dpdGNoU3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlN3aXRjaFN0YXRlbWVudFwiKTtcbiAgICBzdXBlci52aXNpdFN3aXRjaFN0YXRlbWVudChub2RlKTtcbiAgfVxuICB2aXNpdFRocm93U3RhdGVtZW50KG5vZGU6IFRocm93U3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlRocm93U3RhdGVtZW50XCIpO1xuICAgIHN1cGVyLnZpc2l0VGhyb3dTdGF0ZW1lbnQobm9kZSk7XG4gIH1cbiAgdmlzaXRUcnlTdGF0ZW1lbnQobm9kZTogVHJ5U3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlRyeVN0YXRlbWVudFwiKTtcbiAgICBzdXBlci52aXNpdFRyeVN0YXRlbWVudChub2RlKTtcbiAgfVxuICB2aXNpdFR5cGVEZWNsYXJhdGlvbihub2RlOiBUeXBlRGVjbGFyYXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiVHlwZURlY2xhcmF0aW9uXCIpO1xuICAgIHN1cGVyLnZpc2l0VHlwZURlY2xhcmF0aW9uKG5vZGUpO1xuICB9XG4gIHZpc2l0VmFyaWFibGVEZWNsYXJhdGlvbihub2RlOiBWYXJpYWJsZURlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIlZhcmlhYmxlRGVjbGFyYXRpb246IFwiLCBmYWxzZSk7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLnR5cGUpIG5vZGUudHlwZS52aXNpdCh0aGlzKTtcbiAgICBsZXQgbmFtZSA9IHRoaXMuZmx1c2goXCI6IFwiKTtcbiAgICBpZiAobm9kZS5pbml0aWFsaXplcikgbm9kZS5pbml0aWFsaXplci52aXNpdCh0aGlzKTtcbiAgICBsZXQgaW5pdGlhbGl6ZXIgPSB0aGlzLmZsdXNoKFwiIFwiKTtcbiAgICB0aGlzLndyaXRlKG5hbWUgKyAobm9kZS5pbml0aWFsaXplciA/IFwiID0gXCIgKyBpbml0aWFsaXplciA6IFwiXCIpICsgXCI7XCIpO1xuICB9XG4gIHZpc2l0VmFyaWFibGVTdGF0ZW1lbnQobm9kZTogVmFyaWFibGVTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiVmFyaWFibGVTdGF0ZW1lbnRcIik7XG4gICAgc3VwZXIudmlzaXRWYXJpYWJsZVN0YXRlbWVudChub2RlKTtcbiAgfVxuICB2aXNpdFdoaWxlU3RhdGVtZW50KG5vZGU6IFdoaWxlU3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIldoaWxlU3RhdGVtZW50XCIpO1xuICAgIHN1cGVyLnZpc2l0V2hpbGVTdGF0ZW1lbnQobm9kZSk7XG4gIH1cbiAgdmlzaXRWb2lkU3RhdGVtZW50KG5vZGU6IFZvaWRTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiVm9pZFN0YXRlbWVudFwiKTtcbiAgICBzdXBlci52aXNpdFZvaWRTdGF0ZW1lbnQobm9kZSk7XG4gIH1cbiAgdmlzaXRDb21tZW50KG5vZGU6IENvbW1lbnROb2RlKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkNvbW1lbnRcIik7XG4gICAgc3VwZXIudmlzaXRDb21tZW50KG5vZGUpO1xuICB9XG4gIHZpc2l0RGVjb3JhdG9yTm9kZShub2RlOiBEZWNvcmF0b3JOb2RlKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkRlY29yYXRvck5vZGVcIik7XG4gICAgc3VwZXIudmlzaXREZWNvcmF0b3JOb2RlKG5vZGUpO1xuICB9XG4gIHZpc2l0UGFyYW1ldGVyKG5vZGU6IFBhcmFtZXRlck5vZGUpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiUGFyYW1ldGVyIFwiICsgbm9kZS5uYW1lLnN5bWJvbCArIFwiOlwiLCBmYWxzZSk7XG4gICAgbm9kZS50eXBlLnZpc2l0KHRoaXMpO1xuICB9XG59XG4iXX0=
\ No newline at end of file
diff --git a/lib/visitor/dist/instances/elementPrinter.js b/lib/visitor/dist/instances/elementPrinter.js
new file mode 100644
index 0000000000..fd0f4728e8
--- /dev/null
+++ b/lib/visitor/dist/instances/elementPrinter.js
@@ -0,0 +1,120 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var element_1 = require("../element");
+var astPrinter_1 = require("./astPrinter");
+var ProgramPrinter = /** @class */ (function (_super) {
+    __extends(ProgramPrinter, _super);
+    function ProgramPrinter() {
+        var _this = _super !== null && _super.apply(this, arguments) || this;
+        _this.depth = 0;
+        _this.astVisitor = new astPrinter_1.PrinterVisitor(_this.parser, _this.writer);
+        return _this;
+    }
+    ProgramPrinter.prototype.visit = function (node) {
+        if (node && node.name && node.internalName.startsWith("~")) {
+            return;
+        }
+        _super.prototype.visit.call(this, node);
+    };
+    ProgramPrinter.prototype.write = function (str, newline) {
+        if (newline === void 0) { newline = false; }
+        this.writer.write("  ".repeat(this.depth) + str + (newline ? "\n" : " "));
+    };
+    ProgramPrinter.prototype.visitFile = function (node) {
+        if (node.name.startsWith("~")) {
+            return;
+        }
+        this.write("visiting file: " + node.name, true);
+        this.depth++;
+        _super.prototype.visitFile.call(this, node);
+        this.depth--;
+    };
+    ProgramPrinter.prototype.visitTypeDefinition = function (node) {
+        this.write(node.type.toString());
+        this.astVisitor.visit(node.typeParameterNodes);
+    };
+    ProgramPrinter.prototype.visitNamespace = function (node) {
+        this.write("Namespace: " + node.name, true);
+        _super.prototype.visitNamespace.call(this, node);
+    };
+    ProgramPrinter.prototype.visitEnum = function (node) {
+        this.write("Enum: " + node, true);
+        _super.prototype.visitNamespace.call(this, node);
+    };
+    ProgramPrinter.prototype.visitEnumValue = function (node) {
+        this.astVisitor.visit(node.valueNode);
+    };
+    ProgramPrinter.prototype.visitGlobal = function (node) {
+        this.write("Global: ");
+        this.visitNode(node.declaration);
+        // this.astVisitor.visit(node.identifierNode);
+        // this.visitNode(node.typeNode);
+        // this.visitNode(node.initializerNode);
+        // this.astVisitor.write(this.astVisitor.flush(": "));
+    };
+    ProgramPrinter.prototype.visitLocal = function (node) {
+        this.write("Local: " + node.name, true);
+        this.visitNode(node.identifierNode);
+        this.visitNode(node.initializerNode);
+    };
+    ProgramPrinter.prototype.visitFunctionPrototype = function (node) {
+        this.write("Function ProtoType:" + node.signature);
+        _super.prototype.visitFunctionPrototype.call(this, node);
+    };
+    ProgramPrinter.prototype.visitFunction = function (node) {
+        this.write("visiting function: " + node.name);
+        this.write(node.signature.toString(), true);
+        // this.write(node.toString());
+        // if(mems)
+        // for (let mem of mems.values()){
+        //     this.write(mem.toString(), true)
+        // }
+    };
+    ProgramPrinter.prototype.visitFunctionTarget = function (node) { };
+    ProgramPrinter.prototype.visitFieldPrototype = function (node) { };
+    ProgramPrinter.prototype.visitField = function (node) { };
+    ProgramPrinter.prototype.visitPropertyPrototype = function (node) { };
+    ProgramPrinter.prototype.visitProperty = function (node) { };
+    ProgramPrinter.prototype.visitClassPrototype = function (node) {
+        _super.prototype.visitClassPrototype.call(this, node);
+        this.write("", true);
+    };
+    ProgramPrinter.prototype.visitClass = function (node) {
+        this.write(node.name);
+        // this.write(node.members!.size.toString());
+        var interfaces = node.declaration.implementsTypes;
+        if (interfaces) {
+            this.write("implements " + interfaces.join(", "));
+        }
+        this.write("", true);
+        this.visit(node.members);
+    };
+    ProgramPrinter.prototype.visitInterfacePrototype = function (node) {
+        this.write("Interface Prototype: ");
+        this.write(node.name, true);
+        _super.prototype.visitInterfacePrototype.call(this, node);
+    };
+    ProgramPrinter.prototype.visitInterface = function (node) {
+        this.write("Interface: " + node.name);
+        _super.prototype.visitInterface.call(this, node);
+        // for (let [key, value] of node.members!.entries()) {
+        //   this.write(key + " " + value.toString());
+        // }
+    };
+    return ProgramPrinter;
+}(element_1.BaseElementVisitor));
+exports.default = ProgramPrinter;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxlbWVudFByaW50ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5zdGFuY2VzL2VsZW1lbnRQcmludGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQTBCQSxzQ0FBZ0Q7QUFDaEQsMkNBQThDO0FBRzlDO0lBQTRDLGtDQUFrQjtJQUE5RDtRQUFBLHFFQW1HQztRQWpHQyxXQUFLLEdBQVcsQ0FBQyxDQUFDO1FBQ2xCLGdCQUFVLEdBQW9CLElBQUksMkJBQWMsQ0FBQyxLQUFJLENBQUMsTUFBTSxFQUFFLEtBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQzs7SUFnRzdFLENBQUM7SUE3RkMsOEJBQUssR0FBTCxVQUFNLElBQXlCO1FBQzdCLElBQUksSUFBSSxJQUFjLElBQUssQ0FBQyxJQUFJLElBQWMsSUFBSyxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDaEYsT0FBTztTQUNSO1FBQ0QsaUJBQU0sS0FBSyxZQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BCLENBQUM7SUFFRCw4QkFBSyxHQUFMLFVBQU0sR0FBVyxFQUFFLE9BQXdCO1FBQXhCLHdCQUFBLEVBQUEsZUFBd0I7UUFDekMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUUsQ0FBQztJQUVELGtDQUFTLEdBQVQsVUFBVSxJQUFVO1FBQ2xCLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDN0IsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFD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LENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3RCLDZDQUE2QztRQUM3QyxJQUFJLFVBQVUsR0FBc0IsSUFBSSxDQUFDLFdBQVksQ0FBQyxlQUFlLENBQUM7UUFDdEUsSUFBSSxVQUFVLEVBQUU7WUFDZCxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7U0FDbkQ7UUFDRCxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBQ0QsZ0RBQXVCLEdBQXZCLFVBQXdCLElBQXdCO1FBQzlDLElBQUksQ0FBQyxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDNUIsaUJBQU0sdUJBQXVCLFlBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELHVDQUFjLEdBQWQsVUFBZSxJQUFlO1FBQzVCLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QyxpQkFBTSxjQUFjLFlBQUMsSUFBSSxDQUFDLENBQUM7UUFDM0Isc0RBQXNEO1FBQ3RELDhDQUE4QztRQUM5QyxJQUFJO0lBQ04sQ0FBQztJQUNILHFCQUFDO0FBQUQsQ0FBQyxBQW5HRCxDQUE0Qyw0QkFBa0IsR0FtRzdEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRWxlbWVudFZpc2l0b3IsXG4gIEZpbGUsXG4gIFR5cGVEZWZpbml0aW9uLFxuICBOYW1lc3BhY2UsXG4gIEVudW0sXG4gIEVudW1WYWx1ZSxcbiAgR2xvYmFsLFxuICBMb2NhbCxcbiAgRnVuY3Rpb25Qcm90b3R5cGUsXG4gIEZ1bmN0aW9uVGFyZ2V0LFxuICBGaWVsZFByb3RvdHlwZSxcbiAgRmllbGQsXG4gIFByb3BlcnR5UHJvdG90eXBlLFxuICBQcm9wZXJ0eSxcbiAgQ2xhc3NQcm90b3R5cGUsXG4gIENsYXNzLFxuICBJbnRlcmZhY2VQcm90b3R5cGUsXG4gIEludGVyZmFjZSxcbiAgRnVuY3Rpb24sXG4gIFByb2dyYW0sXG4gIENvbXBpbGVyLFxuICBDbGFzc0RlY2xhcmF0aW9uLFxuICBQYXJzZXIsXG4gIEVsZW1lbnRcbn0gZnJvbSBcImFzc2VtYmx5c2NyaXB0XCI7XG5pbXBvcnQgeyBCYXNlRWxlbWVudFZpc2l0b3IgfSBmcm9tIFwiLi4vZWxlbWVudFwiO1xuaW1wb3J0IHsgUHJpbnRlclZpc2l0b3IgfSBmcm9tIFwiLi9hc3RQcmludGVyXCI7XG5pbXBvcnQgeyBDb2xsZWN0aW9uIH0gZnJvbSBcIi4uL3Zpc2l0b3JcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvZ3JhbVByaW50ZXIgZXh0ZW5kcyBCYXNlRWxlbWVudFZpc2l0b3JcbiAgaW1wbGVtZW50cyBFbGVtZW50VmlzaXRvciB7XG4gIGRlcHRoOiBudW1iZXIgPSAwO1xuICBhc3RWaXNpdG9yOiBQcmludGVyVmlzaXRvciAgPSBuZXcgUHJpbnRlclZpc2l0b3IodGhpcy5wYXJzZXIsIHRoaXMud3JpdGVyKTtcblxuXG4gIHZpc2l0KG5vZGU6IENvbGxlY3Rpb248RWxlbWVudD4pOiB2b2lkIHtcbiAgICBpZiAobm9kZSAmJiAoPEVsZW1lbnQ+bm9kZSkubmFtZSAmJiAoPEVsZW1lbnQ+bm9kZSkuaW50ZXJuYWxOYW1lLnN0YXJ0c1dpdGgoXCJ+XCIpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHN1cGVyLnZpc2l0KG5vZGUpO1xuICB9XG5cbiAgd3JpdGUoc3RyOiBzdHJpbmcsIG5ld2xpbmU6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIHRoaXMud3JpdGVyLndyaXRlKFwiICBcIi5yZXBlYXQodGhpcy5kZXB0aCkgKyBzdHIgKyAobmV3bGluZSA/IFwiXFxuXCIgOiBcIiBcIikpO1xuICB9XG5cbiAgdmlzaXRGaWxlKG5vZGU6IEZpbGUpOiB2b2lkIHtcbiAgICBpZiAobm9kZS5uYW1lLnN0YXJ0c1dpdGgoXCJ+XCIpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMud3JpdGUoXCJ2aXNpdGluZyBmaWxlOiBcIiArIG5vZGUubmFtZSwgdHJ1ZSk7XG4gICAgdGhpcy5kZXB0aCsrO1xuICAgIHN1cGVyLnZpc2l0RmlsZShub2RlKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cbiAgdmlzaXRUeXBlRGVmaW5pdGlvbihub2RlOiBUeXBlRGVmaW5pdGlvbik6IHZvaWQge1xuICAgIHRoaXMud3JpdGUobm9kZS50eXBlLnRvU3RyaW5nKCkpO1xuICAgIHRoaXMuYXN0VmlzaXRvci52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJOb2Rlcyk7XG4gIH1cbiAgdmlzaXROYW1lc3BhY2Uobm9kZTogTmFtZXNwYWNlKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIk5hbWVzcGFjZTogXCIgKyBub2RlLm5hbWUsIHRydWUpO1xuICAgIHN1cGVyLnZpc2l0TmFtZXNwYWNlKG5vZGUpO1xuICB9XG4gIHZpc2l0RW51bShub2RlOiBFbnVtKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkVudW06IFwiICsgbm9kZSwgdHJ1ZSk7XG4gICAgc3VwZXIudmlzaXROYW1lc3BhY2Uobm9kZSk7XG4gIH1cbiAgdmlzaXRFbnVtVmFsdWUobm9kZTogRW51bVZhbHVlKTogdm9pZCB7XG4gICAgdGhpcy5hc3RWaXNpdG9yLnZpc2l0KG5vZGUudmFsdWVOb2RlKTtcbiAgfVxuICB2aXNpdEdsb2JhbChub2RlOiBHbG9iYWwpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiR2xvYmFsOiBcIik7XG4gICAgdGhpcy52aXNpdE5vZGUobm9kZS5kZWNsYXJhdGlvbik7XG4gICAgLy8gdGhpcy5hc3RWaXNpdG9yLnZpc2l0KG5vZGUuaWRlbnRpZmllck5vZGUpO1xuICAgIC8vIHRoaXMudmlzaXROb2RlKG5vZGUudHlwZU5vZGUpO1xuICAgIC8vIHRoaXMudmlzaXROb2RlKG5vZGUuaW5pdGlhbGl6ZXJOb2RlKTtcbiAgICAvLyB0aGlzLmFzdFZpc2l0b3Iud3JpdGUodGhpcy5hc3RWaXNpdG9yLmZsdXNoKFwiOiBcIikpO1xuICB9XG4gIHZpc2l0TG9jYWwobm9kZTogTG9jYWwpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiTG9jYWw6IFwiICsgbm9kZS5uYW1lLCB0cnVlKTtcbiAgICB0aGlzLnZpc2l0Tm9kZShub2RlLmlkZW50aWZpZXJOb2RlKTtcbiAgICB0aGlzLnZpc2l0Tm9kZShub2RlLmluaXRpYWxpemVyTm9kZSk7XG4gIH1cbiAgdmlzaXRGdW5jdGlvblByb3RvdHlwZShub2RlOiBGdW5jdGlvblByb3RvdHlwZSk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJGdW5jdGlvbiBQcm90b1R5cGU6XCIgKyBub2RlLnNpZ25hdHVyZSk7XG4gICAgc3VwZXIudmlzaXRGdW5jdGlvblByb3RvdHlwZShub2RlKTtcbiAgfVxuICB2aXNpdEZ1bmN0aW9uKG5vZGU6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcInZpc2l0aW5nIGZ1bmN0aW9uOiBcIiArIG5vZGUubmFtZSk7XG4gICAgdGhpcy53cml0ZShub2RlLnNpZ25hdHVyZS50b1N0cmluZygpLCB0cnVlKTtcbiAgICAvLyB0aGlzLndyaXRlKG5vZGUudG9TdHJpbmcoKSk7XG4gICAgLy8gaWYobWVtcylcbiAgICAvLyBmb3IgKGxldCBtZW0gb2YgbWVtcy52YWx1ZXMoKSl7XG4gICAgLy8gICAgIHRoaXMud3JpdGUobWVtLnRvU3RyaW5nKCksIHRydWUpXG4gICAgLy8gfVxuICB9XG4gIHZpc2l0RnVuY3Rpb25UYXJnZXQobm9kZTogRnVuY3Rpb25UYXJnZXQpOiB2b2lkIHt9XG4gIHZpc2l0RmllbGRQcm90b3R5cGUobm9kZTogRmllbGRQcm90b3R5cGUpOiB2b2lkIHt9XG4gIHZpc2l0RmllbGQobm9kZTogRmllbGQpOiB2b2lkIHt9XG4gIHZpc2l0UHJvcGVydHlQcm90b3R5cGUobm9kZTogUHJvcGVydHlQcm90b3R5cGUpOiB2b2lkIHt9XG4gIHZpc2l0UHJvcGVydHkobm9kZTogUHJvcGVydHkpOiB2b2lkIHt9XG4gIHZpc2l0Q2xhc3NQcm90b3R5cGUobm9kZTogQ2xhc3NQcm90b3R5cGUpOiB2b2lkIHtcbiAgICBzdXBlci52aXNpdENsYXNzUHJvdG90eXBlKG5vZGUpO1xuICAgIHRoaXMud3JpdGUoXCJcIiwgdHJ1ZSk7XG4gIH1cbiAgdmlzaXRDbGFzcyhub2RlOiBDbGFzcyk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUobm9kZS5uYW1lKTtcbiAgICAvLyB0aGlzLndyaXRlKG5vZGUubWVtYmVycyEuc2l6ZS50b1N0cmluZygpKTtcbiAgICBsZXQgaW50ZXJmYWNlcyA9ICg8Q2xhc3NEZWNsYXJhdGlvbj5ub2RlLmRlY2xhcmF0aW9uKS5pbXBsZW1lbnRzVHlwZXM7XG4gICAgaWYgKGludGVyZmFjZXMpIHtcbiAgICAgIHRoaXMud3JpdGUoXCJpbXBsZW1lbnRzIFwiICsgaW50ZXJmYWNlcy5qb2luKFwiLCBcIikpO1xuICAgIH1cbiAgICB0aGlzLndyaXRlKFwiXCIsIHRydWUpO1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgfVxuICB2aXNpdEludGVyZmFjZVByb3RvdHlwZShub2RlOiBJbnRlcmZhY2VQcm90b3R5cGUpOiB2b2lkIHtcbiAgICB0aGlzLndyaXRlKFwiSW50ZXJmYWNlIFByb3RvdHlwZTogXCIpO1xuICAgIHRoaXMud3JpdGUobm9kZS5uYW1lLCB0cnVlKTtcbiAgICBzdXBlci52aXNpdEludGVyZmFjZVByb3RvdHlwZShub2RlKTtcbiAgfVxuXG4gIHZpc2l0SW50ZXJmYWNlKG5vZGU6IEludGVyZmFjZSk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUoXCJJbnRlcmZhY2U6IFwiICsgbm9kZS5uYW1lKTtcbiAgICBzdXBlci52aXNpdEludGVyZmFjZShub2RlKTtcbiAgICAvLyBmb3IgKGxldCBba2V5LCB2YWx1ZV0gb2Ygbm9kZS5tZW1iZXJzIS5lbnRyaWVzKCkpIHtcbiAgICAvLyAgIHRoaXMud3JpdGUoa2V5ICsgXCIgXCIgKyB2YWx1ZS50b1N0cmluZygpKTtcbiAgICAvLyB9XG4gIH1cbn1cbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/instances/printIds.js b/lib/visitor/dist/instances/printIds.js
new file mode 100644
index 0000000000..cc21e2d741
--- /dev/null
+++ b/lib/visitor/dist/instances/printIds.js
@@ -0,0 +1,51 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+var element_1 = require("../element");
+var PrintIDs = /** @class */ (function (_super) {
+    __extends(PrintIDs, _super);
+    function PrintIDs() {
+        var _this = _super !== null && _super.apply(this, arguments) || this;
+        _this.seen = new Set();
+        return _this;
+    }
+    PrintIDs.prototype.start = function () {
+        this.visitManagedClasses(this.files);
+    };
+    PrintIDs.prototype.write = function (str, newline) {
+        if (newline === void 0) { newline = false; }
+        this.writer.write(str + (newline ? "\n" : " "));
+    };
+    PrintIDs.prototype.visitClass = function (node) {
+        if (this.seen.has(node)) {
+            return;
+        }
+        this.seen.add(node);
+        this.write(node.name + ": " + node.id.toString(), true);
+        this.visit(node.members);
+    };
+    PrintIDs.prototype.visitField = function (node) {
+        this.write("  Field:\t" + node.name + ": " + node.typeNode.toString(), true);
+    };
+    PrintIDs.prototype.visitProperty = function (node) {
+        var typeName = node.typeNode
+            ? node.typeNode.toString()
+            : node.type.toString();
+        this.write("  Property:\t" + node.name + ": " + typeName, true);
+    };
+    return PrintIDs;
+}(element_1.BaseElementVisitor));
+exports.default = PrintIDs;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpbnRJZHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5zdGFuY2VzL3ByaW50SWRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQVNBLHNDQUFnRDtBQUVoRDtJQUFzQyw0QkFBa0I7SUFBeEQ7UUFBQSxxRUFpQ0M7UUFoQ0MsVUFBSSxHQUFlLElBQUksR0FBRyxFQUFFLENBQUM7O0lBZ0MvQixDQUFDO0lBOUJDLHdCQUFLLEdBQUw7UUFDRSxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRCx3QkFBSyxHQUFMLFVBQU0sR0FBVyxFQUFFLE9BQXdCO1FBQXhCLHdCQUFBLEVBQUEsZUFBd0I7UUFDekMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVELDZCQUFVLEdBQVYsVUFBVyxJQUFXO1FBQ3BCLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDdkIsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFRCw2QkFBVSxHQUFWLFVBQVcsSUFBVztRQUNwQixJQUFJLENBQUMsS0FBSyxDQUNSLFlBQVksR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUyxDQUFDLFFBQVEsRUFBRSxFQUMzRCxJQUFJLENBQ0wsQ0FBQztJQUNKLENBQUM7SUFFRCxnQ0FBYSxHQUFiLFVBQWMsSUFBYztRQUMxQixJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUMxQixDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUU7WUFDMUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLEdBQUcsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFDSCxlQUFDO0FBQUQsQ0FBQyxBQWpDRCxDQUFzQyw0QkFBa0IsR0FpQ3ZEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRWxlbWVudFZpc2l0b3IsXG4gIENsYXNzLFxuICBDb21waWxlcixcbiAgUGFyc2VyLFxuICBGaWVsZCxcbiAgUHJvcGVydHlcbn0gZnJvbSBcImFzc2VtYmx5c2NyaXB0XCI7XG5cbmltcG9ydCB7IEJhc2VFbGVtZW50VmlzaXRvciB9IGZyb20gXCIuLi9lbGVtZW50XCI7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFByaW50SURzIGV4dGVuZHMgQmFzZUVsZW1lbnRWaXNpdG9yIHtcbiAgc2VlbjogU2V0PENsYXNzPiA9IG5ldyBTZXQoKTtcblxuICBzdGFydCgpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0TWFuYWdlZENsYXNzZXModGhpcy5maWxlcyk7XG4gIH1cblxuICB3cml0ZShzdHI6IHN0cmluZywgbmV3bGluZTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZXIud3JpdGUoc3RyICsgKG5ld2xpbmUgPyBcIlxcblwiIDogXCIgXCIpKTtcbiAgfVxuXG4gIHZpc2l0Q2xhc3Mobm9kZTogQ2xhc3MpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZWVuLmhhcyhub2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnNlZW4uYWRkKG5vZGUpO1xuICAgIHRoaXMud3JpdGUobm9kZS5uYW1lICsgXCI6IFwiICsgbm9kZS5pZC50b1N0cmluZygpLCB0cnVlKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUubWVtYmVycyk7XG4gIH1cblxuICB2aXNpdEZpZWxkKG5vZGU6IEZpZWxkKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcbiAgICAgIFwiICBGaWVsZDpcXHRcIiArIG5vZGUubmFtZSArIFwiOiBcIiArIG5vZGUudHlwZU5vZGUhLnRvU3RyaW5nKCksXG4gICAgICB0cnVlXG4gICAgKTtcbiAgfVxuXG4gIHZpc2l0UHJvcGVydHkobm9kZTogUHJvcGVydHkpOiB2b2lkIHtcbiAgICBsZXQgdHlwZU5hbWUgPSBub2RlLnR5cGVOb2RlXG4gICAgICA/IG5vZGUudHlwZU5vZGUudG9TdHJpbmcoKVxuICAgICAgOiBub2RlLnR5cGUudG9TdHJpbmcoKTtcbiAgICB0aGlzLndyaXRlKFwiICBQcm9wZXJ0eTpcXHRcIiArIG5vZGUubmFtZSArIFwiOiBcIiArIHR5cGVOYW1lLCB0cnVlKTtcbiAgfVxufVxuIl19
\ No newline at end of file
diff --git a/lib/visitor/dist/instances/virtual.js b/lib/visitor/dist/instances/virtual.js
new file mode 100644
index 0000000000..042b3ca4e4
--- /dev/null
+++ b/lib/visitor/dist/instances/virtual.js
@@ -0,0 +1,272 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var __values = (this && this.__values) || function (o) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+    if (m) return m.call(o);
+    return {
+        next: function () {
+            if (o && i >= o.length) o = void 0;
+            return { value: o && o[i++], done: !o };
+        }
+    };
+};
+var __read = (this && this.__read) || function (o, n) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator];
+    if (!m) return o;
+    var i = m.call(o), r, ar = [], e;
+    try {
+        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
+    }
+    catch (error) { e = { error: error }; }
+    finally {
+        try {
+            if (r && !r.done && (m = i["return"])) m.call(i);
+        }
+        finally { if (e) throw e.error; }
+    }
+    return ar;
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var assemblyscript_1 = require("assemblyscript");
+var element_1 = require("../element");
+var astPrinter_1 = require("./astPrinter");
+var Virtualizer = /** @class */ (function (_super) {
+    __extends(Virtualizer, _super);
+    function Virtualizer(parser, compiler, writer) {
+        var _this = _super.call(this, parser, compiler, writer) || this;
+        _this.interfaceMethods = new Map();
+        _this.classIds = new Map();
+        _this.log = false;
+        debugger;
+        return _this;
+    }
+    Virtualizer.prototype.start = function () {
+        var _this = this;
+        var e_1, _a;
+        var compiler = this.compiler;
+        this.astVisitor = new astPrinter_1.PrinterVisitor(this.parser, this.writer);
+        this.visitInterfaces(this.files);
+        var managedClasses = [];
+        try {
+            for (var _b = __values(compiler.program.managedClasses.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var _class = _c.value;
+                managedClasses.push(_class.id);
+                if (!_class.file.name.startsWith("~") && _class.prototype.implementsNodes != null) {
+                    _class.visit(this);
+                }
+            }
+        }
+        catch (e_1_1) { e_1 = { error: e_1_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_1) throw e_1.error; }
+        }
+        this.write(this.compiler.functionTable.join(" "), true);
+        this.createVitualFunction();
+        var module = compiler.module;
+        var updateInterfaceMethods = function (i) {
+            var e_2, _a;
+            if (i.instanceMembers == null)
+                return;
+            try {
+                for (var _b = __values(i.instanceMembers.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
+                    var member = _c.value;
+                    if (member.kind != assemblyscript_1.ElementKind.FUNCTION_PROTOTYPE)
+                        continue;
+                    var func = _this.getFunctionByName(member.internalName);
+                    var signature = func.signature;
+                    var _type = _this.compiler.ensureFunctionType(signature.parameterTypes, signature.returnType, signature.thisType);
+                    var loadMethodID = module.i32(_this.interfaceMethods.get(func.prototype.signature));
+                    // let target = this.compiler.program.instancesByName("virtual");
+                    var loadClass = module.load(4, false, module.binary(assemblyscript_1.BinaryOp.SubI32, module.local_get(0, assemblyscript_1.NativeType.I32), module.i32(8)), assemblyscript_1.NativeType.I32);
+                    var callVirtual = module.call("~lib/virtual/virtual", [loadMethodID, loadClass], assemblyscript_1.NativeType.I32);
+                    module.removeFunction(member.internalName);
+                    var callIndirect = module.call_indirect(callVirtual, func.localsByIndex.map(function (local) { return module.local_get(local.index, local.type.toNativeType()); }), assemblyscript_1.Signature.makeSignatureString(func.signature.parameterTypes, func.signature.returnType, func.signature.thisType));
+                    var body = module.block(null, [callIndirect], func.signature.returnType.toNativeType());
+                    module.addFunction(member.internalName, _type, null, body);
+                }
+            }
+            catch (e_2_1) { e_2 = { error: e_2_1 }; }
+            finally {
+                try {
+                    if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+                }
+                finally { if (e_2) throw e_2.error; }
+            }
+            debugger;
+        };
+        try {
+            this.visitInterfaces(this.files, updateInterfaceMethods);
+        }
+        catch (e) {
+            this.write(e.toString());
+        }
+    };
+    Virtualizer.prototype.createVitualFunction = function () {
+        var e_3, _a, e_4, _b;
+        var module = this.compiler.module;
+        var functionTable = this.compiler.functionTable;
+        module.setFunctionTable(functionTable.length, 0xffffffff, functionTable);
+        this.write(functionTable.join("\n"), true);
+        var methodIDCases = [];
+        var dummyMethodId = 0, dummyClassid = 0;
+        try {
+            for (var _c = __values(this.classIds.entries()), _d = _c.next(); !_d.done; _d = _c.next()) {
+                var _e = __read(_d.value, 2), id = _e[0], classes = _e[1];
+                var str = ["case ", id.toString(), ": {\n\tswitch (classID) {\n"];
+                dummyMethodId = id;
+                try {
+                    for (var classes_1 = __values(classes), classes_1_1 = classes_1.next(); !classes_1_1.done; classes_1_1 = classes_1.next()) {
+                        var _f = __read(classes_1_1.value, 2), classID = _f[0], fnPtr = _f[1];
+                        dummyClassid = classID;
+                        str.push("\t\tcase " + classID.toString() + ": return ");
+                        str.push(fnPtr.toString() + ";\n");
+                    }
+                }
+                catch (e_4_1) { e_4 = { error: e_4_1 }; }
+                finally {
+                    try {
+                        if (classes_1_1 && !classes_1_1.done && (_b = classes_1.return)) _b.call(classes_1);
+                    }
+                    finally { if (e_4) throw e_4.error; }
+                }
+                str.push("\t}");
+                str.push("\n}");
+                methodIDCases.push(str.join(""));
+            }
+        }
+        catch (e_3_1) { e_3 = { error: e_3_1 }; }
+        finally {
+            try {
+                if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
+            }
+            finally { if (e_3) throw e_3.error; }
+        }
+        var funcSourc = "\n      @global\n      function virtual(methodID: usize, classID: usize): usize {\n        switch (methodID){\n           " + methodIDCases.join("") + "\n        }\n        unreachable();\n        return 0;\n      }\n      virtual(" + dummyMethodId + ", " + dummyClassid + ");\n      ";
+        this.parser.parseFile(funcSourc, "~lib/virtual", false);
+        this.parser.program.initialize(this.compiler.options);
+        var sources = this.parser.program.sources;
+        var file = new assemblyscript_1.File(this.parser.program, sources[sources.length - 1]);
+        this.parser.program.initializeFunction(file.source.statements[0], file);
+        this.compiler.compileFile(file);
+        // this.compiler.module.removeFunction("~lib/virtual");
+    };
+    Virtualizer.prototype.write = function (str, newline) {
+        if (newline === void 0) { newline = false; }
+        if (this.log) {
+            this.writer.write(str + (newline ? "\n" : " "));
+        }
+    };
+    Virtualizer.prototype.visitFunctionPrototype = function (node) {
+        if (node.isBound) {
+            var _class = node.parent;
+            var signature = node.signature;
+            var id = this.interfaceMethods.get(signature);
+            if (id != null) {
+                var classId = _class.id;
+                this.write("Parent: " + _class.name, true);
+                this.write("visiting function " + node.internalName, false);
+                this.write(signature + " has methodID: " + id, true);
+                var fnPtr = this.compiler.functionTable.length;
+                this.compiler.functionTable.push(node.internalName);
+                var entry = [classId, fnPtr];
+                this.classIds.get(id).push(entry);
+                // let funcPtr = this.compiler.ensureFunctionTableEntry(this.compiler.program.instancesByName)
+            }
+        }
+    };
+    Virtualizer.prototype.visitFunction = function (node) {
+        this.write("visiting function: " + node.name);
+        this.write(node.signature.toString(), true);
+    };
+    Virtualizer.prototype.visitFunctionTarget = function (node) { };
+    Virtualizer.prototype.visitFieldPrototype = function (node) { };
+    Virtualizer.prototype.visitField = function (node) { };
+    Virtualizer.prototype.visitPropertyPrototype = function (node) { };
+    Virtualizer.prototype.visitProperty = function (node) { };
+    Virtualizer.prototype.visitClassPrototype = function (node) { };
+    Virtualizer.prototype.visitClass = function (node) {
+        var e_5, _a;
+        this.write(node.name);
+        // this.write(node.members!.size.toString());
+        var interfaces = node.declaration.implementsTypes;
+        if (interfaces) {
+            this.write("implements " + interfaces.join(", "));
+        }
+        this.write("", true);
+        try {
+            for (var _b = __values(node.members.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var mem = _c.value;
+                mem.visit(this);
+            }
+        }
+        catch (e_5_1) { e_5 = { error: e_5_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_5) throw e_5.error; }
+        }
+    };
+    Virtualizer.prototype.visitInterfacePrototype = function (node) {
+        var e_6, _a;
+        this.write("Interface Prototype", true);
+        this.write(node.name);
+        try {
+            for (var _b = __values(node.instanceMembers.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
+                if (value instanceof assemblyscript_1.FunctionPrototype) {
+                    this.write(key + " " + value.toString());
+                    var id = this.interfaceMethods.size;
+                    if (!this.interfaceMethods.has(value.signature)) {
+                        this.interfaceMethods.set(value.signature, id);
+                        this.classIds.set(id, []);
+                        this.write(value.signature, true);
+                    }
+                }
+            }
+        }
+        catch (e_6_1) { e_6 = { error: e_6_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_6) throw e_6.error; }
+        }
+        this.write("", true);
+    };
+    Virtualizer.prototype.visitInterface = function (node) {
+        var e_7, _a;
+        this.write(node.name);
+        try {
+            for (var _b = __values(node.members.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
+                this.write(key + " " + value.toString());
+            }
+        }
+        catch (e_7_1) { e_7 = { error: e_7_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_7) throw e_7.error; }
+        }
+    };
+    return Virtualizer;
+}(element_1.BaseElementVisitor));
+exports.default = Virtualizer;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnN0YW5jZXMvdmlydHVhbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlEQStCd0I7QUFDeEIsc0NBQWdEO0FBQ2hELDJDQUE4QztBQVU5QztJQUF5QywrQkFBa0I7SUFNekQscUJBQVksTUFBYyxFQUFFLFFBQWtCLEVBQUUsTUFBYztRQUE5RCxZQUNFLGtCQUFNLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLFNBRWhDO1FBUEQsc0JBQWdCLEdBQTBCLElBQUksR0FBRyxFQUFFLENBQUM7UUFDcEQsY0FBUSxHQUFtQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ3JELFNBQUcsR0FBRyxLQUFLLENBQUM7UUFJVixRQUFRLENBQUM7O0lBQ1gsQ0FBQztJQUVELDJCQUFLLEdBQUw7UUFBQSxpQkEyRUM7O1FBMUVDLElBQUksUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDN0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLDJCQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFakMsSUFBSSxjQUFjLEdBQUcsRUFBRSxDQUFDOztZQUN4QixLQUFtQixJQUFBLEtBQUEsU0FBQSxRQUFRLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsQ0FBQSxnQkFBQSw0QkFBRTtnQkFBeEQsSUFBSSxNQUFNLFdBQUE7Z0JBQ2IsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElB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ZCxVQUFlLElBQWU7O1FBQzVCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDOztZQUN0QixLQUF5QixJQUFBLEtBQUEsU0FBQSxJQUFJLENBQUMsT0FBUSxDQUFDLE9BQU8sRUFBRSxDQUFBLGdCQUFBLDRCQUFFO2dCQUF6QyxJQUFBLHdCQUFZLEVBQVgsV0FBRyxFQUFFLGFBQUs7Z0JBQ2xCLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQzthQUMxQzs7Ozs7Ozs7O0lBQ0gsQ0FBQztJQUNILGtCQUFDO0FBQUQsQ0FBQyxBQXhNRCxDQUF5Qyw0QkFBa0IsR0F3TTFEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRWxlbWVudFZpc2l0b3IsXG4gIEZpbGUsXG4gIFR5cGVEZWZpbml0aW9uLFxuICBOYW1lc3BhY2UsXG4gIEVudW0sXG4gIEVudW1WYWx1ZSxcbiAgR2xvYmFsLFxuICBMb2NhbCxcbiAgRnVuY3Rpb25Qcm90b3R5cGUsXG4gIEZ1bmN0aW9uVGFyZ2V0LFxuICBGaWVsZFByb3RvdHlwZSxcbiAgRmllbGQsXG4gIFByb3BlcnR5UHJvdG90eXBlLFxuICBQcm9wZXJ0eSxcbiAgQ2xhc3NQcm90b3R5cGUsXG4gIENsYXNzLFxuICBJbnRlcmZhY2VQcm90b3R5cGUsXG4gIEludGVyZmFjZSxcbiAgRnVuY3Rpb24sXG4gIFByb2dyYW0sXG4gIENvbXBpbGVyLFxuICBJZGVudGlmaWVyRXhwcmVzc2lvbixcbiAgRnVuY3Rpb25EZWNsYXJhdGlvbixcbiAgQ2xhc3NEZWNsYXJhdGlvbixcbiAgUGFyc2VyLFxuICBCaW5hcnlPcCxcbiAgTmF0aXZlVHlwZSxcbiAgU2lnbmF0dXJlLFxuICBFbGVtZW50S2luZCxcbiAgVHlwZUZsYWdzXG59IGZyb20gXCJhc3NlbWJseXNjcmlwdFwiO1xuaW1wb3J0IHsgQmFzZUVsZW1lbnRWaXNpdG9yIH0gZnJvbSBcIi4uL2VsZW1lbnRcIjtcbmltcG9ydCB7IFByaW50ZXJWaXNpdG9yIH0gZnJvbSBcIi4vYXN0UHJpbnRlclwiO1xuaW1wb3J0IHsgQVNUVmlzaXRvciB9IGZyb20gXCIuLi9hc3RcIjtcbmltcG9ydCB7IFdyaXRlciB9IGZyb20gXCIuLlwiO1xuXG50eXBlIG1lbWJlcmlkID0gbnVtYmVyO1xudHlwZSBjbGFzc2lkID0gbnVtYmVyO1xudHlwZSBmblB0ciA9IG51bWJlcjtcblxudHlwZSB2aXJ0dWFsTWV0aG9kID0gW2NsYXNzaWQsIGZuUHRyXTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmlydHVhbGl6ZXIgZXh0ZW5kcyBCYXNlRWxlbWVudFZpc2l0b3JcbiAgaW1wbGVtZW50cyBFbGVtZW50VmlzaXRvciB7XG4gIGludGVyZmFjZU1ldGhvZHM6IE1hcDxzdHJpbmcsIG1lbWJlcmlkPiA9IG5ldyBNYXAoKTtcbiAgY2xhc3NJZHM6IE1hcDxtZW1iZXJpZCwgdmlydHVhbE1ldGhvZFtdPiA9IG5ldyBNYXAoKTtcbiAgbG9nID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocGFyc2VyOiBQYXJzZXIsIGNvbXBpbGVyOiBDb21waWxlciwgd3JpdGVyOiBXcml0ZXIpIHtcbiAgICBzdXBlcihwYXJzZXIsIGNvbXBpbGVyLCB3cml0ZXIpO1xuICAgIGRlYnVnZ2VyO1xuICB9XG5cbiAgc3RhcnQoKTogdm9pZCB7XG4gICAgdmFyIGNvbXBpbGVyID0gdGhpcy5jb21waWxlcjtcbiAgICB0aGlzLmFzdFZpc2l0b3IgPSBuZXcgUHJpbnRlclZpc2l0b3IodGhpcy5wYXJzZXIsIHRoaXMud3JpdGVyKTtcbiAgICB0aGlzLnZpc2l0SW50ZXJmYWNlcyh0aGlzLmZpbGVzKTtcblxuICAgIHZhciBtYW5hZ2VkQ2xhc3NlcyA9IFtdO1xuICAgIGZvciAobGV0IF9jbGFzcyBvZiBjb21waWxlci5wcm9ncmFtLm1hbmFnZWRDbGFzc2VzLnZhbHVlcygpKSB7XG4gICAgICBtYW5hZ2VkQ2xhc3Nlcy5wdXNoKF9jbGFzcy5pZCk7XG4gICAgICBpZiAoIV9jbGFzcy5maWxlLm5hbWUuc3RhcnRzV2l0aChcIn5cIikgJiYgX2NsYXNzLnByb3RvdHlwZS5pbXBsZW1lbnRzTm9kZXMgIT0gbnVsbCkge1xuICAgICAgICBfY2xhc3MudmlzaXQodGhpcyk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMud3JpdGUodGhpcy5jb21waWxlci5mdW5jdGlvblRhYmxlLmpvaW4oXCIgXCIpLCB0cnVlKTtcbiAgICB0aGlzLmNyZWF0ZVZpdHVhbEZ1bmN0aW9uKCk7XG4gICAgdmFyIG1vZHVsZSA9IGNvbXBpbGVyLm1vZHVsZTtcblxuICAgIGNvbnN0IHVwZGF0ZUludGVyZmFjZU1ldGhvZHMgPSAoaTogSW50ZXJmYWNlUHJvdG90eXBlKTogdm9pZCA9PiB7XG4gICAgICBpZiAoaS5pbnN0YW5jZU1lbWJlcnMgPT0gbnVsbCkgcmV0dXJuO1xuICAgICAgZm9yIChsZXQgbWVtYmVyIG9mIGkuaW5zdGFuY2VNZW1iZXJzLnZhbHVlcygpKSB7XG4gICAgICAgIGlmIChtZW1iZXIua2luZCAhPSBFbGVtZW50S2luZC5GVU5DVElPTl9QUk9UT1RZUEUpIGNvbnRpbnVlO1xuICAgICAgICBsZXQgZnVuYzogRnVuY3Rpb24gPSB0aGlzLmdldEZ1bmN0aW9uQnlOYW1lKG1lbWJlci5pbnRlcm5hbE5hbWUpO1xuICAgICAgICBsZXQgc2lnbmF0dXJlID0gZnVuYy5zaWduYXR1cmU7XG4gICAgICAgIGxldCBfdHlwZSA9IHRoaXMuY29tcGlsZXIuZW5zdXJlRnVuY3Rpb25UeXBlKFxuICAgICAgICAgIHNpZ25hdHVyZS5wYXJhbWV0ZXJUeXBlcyxcbiAgICAgICAgICBzaWduYXR1cmUucmV0dXJuVHlwZSxcbiAgICAgICAgICBzaWduYXR1cmUudGhpc1R5cGVcbiAgICAgICAgKTtcbiAgICAgICAgbGV0IGxvYWRNZXRob2RJRCA9IG1vZHVsZS5pMzIoXG4gICAgICAgICAgdGhpcy5pbnRlcmZhY2VNZXRob2RzLmdldChmdW5jLnByb3RvdHlwZS5zaWduYXR1cmUpIVxuICAgICAgICApO1xuICAgICAgICAvLyBsZXQgdGFyZ2V0ID0gdGhpcy5jb21waWxlci5wcm9ncmFtLmluc3RhbmNlc0J5TmFtZShcInZpcnR1YWxcIik7XG4gICAgICAgIGxldCBsb2FkQ2xhc3MgPSBtb2R1bGUubG9hZChcbiAgICAgICAgICA0LFxuICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgIG1vZHVsZS5iaW5hcnkoXG4gICAgICAgICAgICBCaW5hcnlPcC5TdWJJMzIsXG4gICAgICAgICAgICBtb2R1bGUubG9jYWxfZ2V0KDAsIE5hdGl2ZVR5cGUuSTMyKSxcbiAgICAgICAgICAgIG1vZHVsZS5pMzIoOClcbiAgICAgICAgICApLFxuICAgICAgICAgIE5hdGl2ZVR5cGUuSTMyXG4gICAgICAgICk7XG4gICAgICAgIGxldCBjYWxsVmlydHVhbCA9IG1vZHVsZS5jYWxsKFxuICAgICAgICAgIFwifmxpYi92aXJ0dWFsL3ZpcnR1YWxcIixcbiAgICAgICAgICBbbG9hZE1ldGhvZElELCBsb2FkQ2xhc3NdLFxuICAgICAgICAgIE5hdGl2ZVR5cGUuSTMyXG4gICAgICAgICk7XG4gICAgICAgIG1vZHVsZS5yZW1vdmVGdW5jdGlvbihtZW1iZXIuaW50ZXJuYWxOYW1lKTtcbiAgICAgICAgXG4gICAgICAgIGxldCBjYWxsSW5kaXJlY3QgPSBtb2R1bGUuY2FsbF9pbmRpcmVjdChcbiAgICAgICAgICBjYWxsVmlydHVhbCxcbiAgICAgICAgICBmdW5jLmxvY2Fsc0J5SW5kZXgubWFwPG51bWJlcj4obG9jYWwgPT4gbW9kdWxlLmxvY2FsX2dldChsb2NhbC5pbmRleCwgbG9jYWwudHlwZS50b05hdGl2ZVR5cGUoKSkpLFxuXG4gICAgICAgICAgU2lnbmF0dXJlLm1ha2VTaWduYXR1cmVTdHJpbmcoXG4gICAgICAgICAgICBmdW5jLnNpZ25hdHVyZS5wYXJhbWV0ZXJUeXBlcyxcbiAgICAgICAgICAgIGZ1bmMuc2lnbmF0dXJlLnJldHVyblR5cGUsXG4gICAgICAgICAgICBmdW5jLnNpZ25hdHVyZS50aGlzVHlwZVxuICAgICAgICAgICkpO1xuXG4gICAgICAgIGxldCBib2R5ID0gbW9kdWxlLmJsb2NrKG51bGwgLFsgY2FsbEluZGlyZWN0IF0sIGZ1bmMuc2lnbmF0dXJlLnJldHVyblR5cGUudG9OYXRpdmVUeXBlKCkpO1xuXG4gICAgICAgIG1vZHVsZS5hZGRGdW5jdGlvbihcbiAgICAgICAgICBtZW1iZXIuaW50ZXJuYWxOYW1lLFxuICAgICAgICAgIF90eXBlLFxuICAgICAgICAgIG51bGwsXG4gICAgICAgICAgYm9keVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgZGVidWdnZXI7XG4gICAgfTtcblxuICAgIHRyeSB7XG4gICAgICB0aGlzLnZpc2l0SW50ZXJmYWNlcyh0aGlzLmZpbGVzLCB1cGRhdGVJbnRlcmZhY2VNZXRob2RzKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLndyaXRlKGUudG9TdHJpbmcoKSk7XG4gICAgfVxuICB9XG5cbiAgY3JlYXRlVml0dWFsRnVuY3Rpb24oKTogdm9pZCB7XG4gICAgdmFyIG1vZHVsZSA9IHRoaXMuY29tcGlsZXIubW9kdWxlO1xuICAgIHZhciBmdW5jdGlvblRhYmxlID0gdGhpcy5jb21waWxlci5mdW5jdGlvblRhYmxlO1xuICAgIG1vZHVsZS5zZXRGdW5jdGlvblRhYmxlKGZ1bmN0aW9uVGFibGUubGVuZ3RoLCAweGZmZmZmZmZmLCBmdW5jdGlvblRhYmxlKTtcbiAgICB0aGlzLndyaXRlKGZ1bmN0aW9uVGFibGUuam9pbihcIlxcblwiKSwgdHJ1ZSk7XG4gICAgbGV0IG1ldGhvZElEQ2FzZXMgPSBbXTtcbiAgICBsZXQgZHVtbXlNZXRob2RJZDogbnVtYmVyPTAsIGR1bW15Q2xhc3NpZCA6IG51bWJlciA9IDA7XG4gICAgZm9yIChsZXQgW2lkLCBjbGFzc2VzXSBvZiB0aGlzLmNsYXNzSWRzLmVudHJpZXMoKSkge1xuICAgICAgbGV0IHN0ciA9IFtcImNhc2UgXCIsIGlkLnRvU3RyaW5nKCksIFwiOiB7XFxuXFx0c3dpdGNoIChjbGFzc0lEKSB7XFxuXCJdO1xuICAgICAgZHVtbXlNZXRob2RJZCA9IGlkO1xuICAgICAgZm9yIChsZXQgW2NsYXNzSUQsIGZuUHRyXSBvZiBjbGFzc2VzKSB7XG4gICAgICAgIGR1bW15Q2xhc3NpZCA9IGNsYXNzSUQ7XG4gICAgICAgIHN0ci5wdXNoKFwiXFx0XFx0Y2FzZSBcIiArIGNsYXNzSUQudG9TdHJpbmcoKSArIFwiOiByZXR1cm4gXCIpO1xuICAgICAgICBzdHIucHVzaChmblB0ci50b1N0cmluZygpICsgXCI7XFxuXCIpO1xuICAgICAgfVxuICAgICAgc3RyLnB1c2goXCJcXHR9XCIpO1xuICAgICAgc3RyLnB1c2goXCJcXG59XCIpO1xuICAgICAgbWV0aG9kSURDYXNlcy5wdXNoKHN0ci5qb2luKFwiXCIpKTtcbiAgICB9XG5cbiAgICB2YXIgZnVuY1NvdXJjID0gYFxuICAgICAgQGdsb2JhbFxuICAgICAgZnVuY3Rpb24gdmlydHVhbChtZXRob2RJRDogdXNpemUsIGNsYXNzSUQ6IHVzaXplKTogdXNpemUge1xuICAgICAgICBzd2l0Y2ggKG1ldGhvZElEKXtcbiAgICAgICAgICAgJHttZXRob2RJRENhc2VzLmpvaW4oXCJcIil9XG4gICAgICAgIH1cbiAgICAgICAgdW5yZWFjaGFibGUoKTtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgICB9XG4gICAgICB2aXJ0dWFsKCR7ZHVtbXlNZXRob2RJZH0sICR7ZHVtbXlDbGFzc2lkfSk7XG4gICAgICBgO1xuICAgIHRoaXMucGFyc2VyLnBhcnNlRmlsZShmdW5jU291cmMsIFwifmxpYi92aXJ0dWFsXCIsIGZhbHNlKTtcbiAgICB0aGlzLnBhcnNlci5wcm9ncmFtLmluaXRpYWxpemUodGhpcy5jb21waWxlci5vcHRpb25zKTtcbiAgICB2YXIgc291cmNlcyA9IHRoaXMucGFyc2VyLnByb2dyYW0uc291cmNlcztcbiAgICB2YXIgZmlsZTogRmlsZSA9IG5ldyBGaWxlKHRoaXMucGFyc2VyLnByb2dyYW0sIHNvdXJjZXNbc291cmNlcy5sZW5ndGggLSAxXSk7XG4gICAgdGhpcy5wYXJzZXIucHJvZ3JhbS5pbml0aWFsaXplRnVuY3Rpb24oXG4gICAgICA8RnVuY3Rpb25EZWNsYXJhdGlvbj5maWxlLnNvdXJjZS5zdGF0ZW1lbnRzWzBdLFxuICAgICAgZmlsZVxuICAgICk7XG4gICAgdGhpcy5jb21waWxlci5jb21waWxlRmlsZShmaWxlKTtcbiAgICAvLyB0aGlzLmNvbXBpbGVyLm1vZHVsZS5yZW1vdmVGdW5jdGlvbihcIn5saWIvdmlydHVhbFwiKTtcbiAgfVxuXG4gIHdyaXRlKHN0cjogc3RyaW5nLCBuZXdsaW5lOiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5sb2cpIHtcbiAgICAgIHRoaXMud3JpdGVyLndyaXRlKHN0ciArIChuZXdsaW5lID8gXCJcXG5cIiA6IFwiIFwiKSk7XG4gICAgfVxuICB9XG5cbiAgdmlzaXRGdW5jdGlvblByb3RvdHlwZShub2RlOiBGdW5jdGlvblByb3RvdHlwZSk6IHZvaWQge1xuICAgIGlmIChub2RlLmlzQm91bmQpIHtcbiAgICAgIGxldCBfY2xhc3MgPSA8Q2xhc3M+IG5vZGUucGFyZW50O1xuICAgICAgbGV0IHNpZ25hdHVyZSA9IG5vZGUuc2lnbmF0dXJlO1xuICAgICAgbGV0IGlkID0gdGhpcy5pbnRlcmZhY2VNZXRob2RzLmdldChzaWduYXR1cmUpO1xuICAgICAgaWYgKGlkICE9IG51bGwpIHtcbiAgICAgICAgbGV0IGNsYXNzSWQgPSBfY2xhc3MuaWQ7XG4gICAgICAgIHRoaXMud3JpdGUoXCJQYXJlbnQ6IFwiICsgX2NsYXNzLm5hbWUsIHRydWUpO1xuICAgICAgICB0aGlzLndyaXRlKFwidmlzaXRpbmcgZnVuY3Rpb24gXCIgKyBub2RlLmludGVybmFsTmFtZSwgZmFsc2UpO1xuICAgICAgICB0aGlzLndyaXRlKHNpZ25hdHVyZSArIFwiIGhhcyBtZXRob2RJRDogXCIgKyBpZCwgdHJ1ZSk7XG4gICAgICAgIGxldCBmblB0ciA9IHRoaXMuY29tcGlsZXIuZnVuY3Rpb25UYWJsZS5sZW5ndGg7XG4gICAgICAgIHRoaXMuY29tcGlsZXIuZnVuY3Rpb25UYWJsZS5wdXNoKG5vZGUuaW50ZXJuYWxOYW1lKTtcbiAgICAgICAgbGV0IGVudHJ5OiB2aXJ0dWFsTWV0aG9kID0gW2NsYXNzSWQsIGZuUHRyXTtcbiAgICAgICAgdGhpcy5jbGFzc0lkcy5nZXQoaWQpIS5wdXNoKGVudHJ5KTtcbiAgICAgICAgLy8gbGV0IGZ1bmNQdHIgPSB0aGlzLmNvbXBpbGVyLmVuc3VyZUZ1bmN0aW9uVGFibGVFbnRyeSh0aGlzLmNvbXBpbGVyLnByb2dyYW0uaW5zdGFuY2VzQnlOYW1lKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICB2aXNpdEZ1bmN0aW9uKG5vZGU6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcInZpc2l0aW5nIGZ1bmN0aW9uOiBcIiArIG5vZGUubmFtZSk7XG4gICAgdGhpcy53cml0ZShub2RlLnNpZ25hdHVyZS50b1N0cmluZygpLCB0cnVlKTtcbiAgfVxuICB2aXNpdEZ1bmN0aW9uVGFyZ2V0KG5vZGU6IEZ1bmN0aW9uVGFyZ2V0KTogdm9pZCB7fVxuICB2aXNpdEZpZWxkUHJvdG90eXBlKG5vZGU6IEZpZWxkUHJvdG90eXBlKTogdm9pZCB7fVxuICB2aXNpdEZpZWxkKG5vZGU6IEZpZWxkKTogdm9pZCB7fVxuICB2aXNpdFByb3BlcnR5UHJvdG90eXBlKG5vZGU6IFByb3BlcnR5UHJvdG90eXBlKTogdm9pZCB7fVxuICB2aXNpdFByb3BlcnR5KG5vZGU6IFByb3BlcnR5KTogdm9pZCB7fVxuICB2aXNpdENsYXNzUHJvdG90eXBlKG5vZGU6IENsYXNzUHJvdG90eXBlKTogdm9pZCB7fVxuICB2aXNpdENsYXNzKG5vZGU6IENsYXNzKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShub2RlLm5hbWUpO1xuICAgIC8vIHRoaXMud3JpdGUobm9kZS5tZW1iZXJzIS5zaXplLnRvU3RyaW5nKCkpO1xuICAgIHZhciBpbnRlcmZhY2VzID0gKDxDbGFzc0RlY2xhcmF0aW9uPm5vZGUuZGVjbGFyYXRpb24pLmltcGxlbWVudHNUeXBlcztcbiAgICBpZiAoaW50ZXJmYWNlcykge1xuICAgICAgdGhpcy53cml0ZShcImltcGxlbWVudHMgXCIgKyBpbnRlcmZhY2VzLmpvaW4oXCIsIFwiKSk7XG4gICAgfVxuICAgIHRoaXMud3JpdGUoXCJcIiwgdHJ1ZSk7XG4gICAgZm9yIChsZXQgbWVtIG9mIG5vZGUubWVtYmVycyEudmFsdWVzKCkpIHtcbiAgICAgIG1lbS52aXNpdCh0aGlzKTtcbiAgICB9XG4gIH1cbiAgdmlzaXRJbnRlcmZhY2VQcm90b3R5cGUobm9kZTogSW50ZXJmYWNlUHJvdG90eXBlKTogdm9pZCB7XG4gICAgdGhpcy53cml0ZShcIkludGVyZmFjZSBQcm90b3R5cGVcIiwgdHJ1ZSk7XG4gICAgdGhpcy53cml0ZShub2RlLm5hbWUpO1xuICAgIGZvciAobGV0IFtrZXksIHZhbHVlXSBvZiBub2RlLmluc3RhbmNlTWVtYmVycyEuZW50cmllcygpKSB7XG4gICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvblByb3RvdHlwZSkge1xuICAgICAgICB0aGlzLndyaXRlKGtleSArIFwiIFwiICsgdmFsdWUudG9TdHJpbmcoKSk7XG4gICAgICAgIGxldCBpZCA9IHRoaXMuaW50ZXJmYWNlTWV0aG9kcy5zaXplO1xuICAgICAgICBpZiAoIXRoaXMuaW50ZXJmYWNlTWV0aG9kcy5oYXModmFsdWUuc2lnbmF0dXJlKSkge1xuICAgICAgICAgIHRoaXMuaW50ZXJmYWNlTWV0aG9kcy5zZXQodmFsdWUuc2lnbmF0dXJlLCBpZCk7XG4gICAgICAgICAgdGhpcy5jbGFzc0lkcy5zZXQoaWQsIFtdKTtcbiAgICAgICAgICB0aGlzLndyaXRlKHZhbHVlLnNpZ25hdHVyZSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy53cml0ZShcIlwiLCB0cnVlKTtcbiAgfVxuXG4gIHZpc2l0SW50ZXJmYWNlKG5vZGU6IEludGVyZmFjZSk6IHZvaWQge1xuICAgIHRoaXMud3JpdGUobm9kZS5uYW1lKTtcbiAgICBmb3IgKGxldCBba2V5LCB2YWx1ZV0gb2Ygbm9kZS5tZW1iZXJzIS5lbnRyaWVzKCkpIHtcbiAgICAgIHRoaXMud3JpdGUoa2V5ICsgXCIgXCIgKyB2YWx1ZS50b1N0cmluZygpKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/src/ast/base.js b/lib/visitor/dist/src/ast/base.js
new file mode 100644
index 0000000000..a9249a2a03
--- /dev/null
+++ b/lib/visitor/dist/src/ast/base.js
@@ -0,0 +1,400 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var __values = (this && this.__values) || function (o) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+    if (m) return m.call(o);
+    return {
+        next: function () {
+            if (o && i >= o.length) o = void 0;
+            return { value: o && o[i++], done: !o };
+        }
+    };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var visitor_1 = require("../visitor");
+var BaseVisitor = /** @class */ (function (_super) {
+    __extends(BaseVisitor, _super);
+    function BaseVisitor() {
+        var _this = _super !== null && _super.apply(this, arguments) || this;
+        _this.depth = 0;
+        return _this;
+    }
+    // /** Visits each node in an array if array exists. */
+    // visitArray(array: Node[] | null): void {
+    //   if (array) {
+    //     array.map(node => {
+    //       if (node) node.visit(this);
+    //     });
+    //   }
+    // }
+    BaseVisitor.prototype.visitSource = function (node) {
+        var e_1, _a;
+        try {
+            for (var _b = __values(node.statements), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var stmt = _c.value;
+                this.depth++;
+                stmt.visit(this);
+                this.depth--;
+            }
+        }
+        catch (e_1_1) { e_1 = { error: e_1_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_1) throw e_1.error; }
+        }
+    };
+    BaseVisitor.prototype.visitTypeNode = function (node) { };
+    BaseVisitor.prototype.visitTypeName = function (node) {
+        node.identifier.visit(this);
+        if (node.next) {
+            node.visit(this);
+        }
+    };
+    BaseVisitor.prototype.visitNamedTypeNode = function (node) {
+        node.name.visit(this);
+        this.visit(node.typeArguments);
+    };
+    BaseVisitor.prototype.visitFunctionTypeNode = function (node) {
+        var e_2, _a;
+        try {
+            for (var _b = __values(node.parameters), _c = _b.next(); !_c.done; _c = _b.next()) {
+                var param = _c.value;
+                param.visit(this);
+            }
+        }
+        catch (e_2_1) { e_2 = { error: e_2_1 }; }
+        finally {
+            try {
+                if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
+            }
+            finally { if (e_2) throw e_2.error; }
+        }
+        node.returnType.visit(this);
+    };
+    BaseVisitor.prototype.visitTypeParameter = function (node) {
+        node.name.visit(this);
+        if (node.extendsType)
+            node.extendsType.visit(this);
+        if (node.defaultType)
+            node.defaultType.visit(this);
+    };
+    BaseVisitor.prototype.visitIdentifierExpression = function (node) { };
+    BaseVisitor.prototype.visitArrayLiteralExpression = function (node) {
+        var _this = this;
+        node.elementExpressions.map(function (e) {
+            if (e)
+                e.visit(_this);
+        });
+    };
+    BaseVisitor.prototype.visitObjectLiteralExpression = function (node) {
+        if (node.values && node.names) {
+            assert(node.values.length == node.names.length);
+            for (var i = 0; i < node.values.length; i++) {
+                node.names[i].visit(this);
+                node.values[i].visit(this);
+            }
+        }
+    };
+    BaseVisitor.prototype.visitAssertionExpression = function (node) {
+        if (node.toType)
+            node.toType.visit(this);
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitBinaryExpression = function (node) {
+        node.left.visit(this);
+        node.right.visit(this);
+    };
+    BaseVisitor.prototype.visitCallExpression = function (node) {
+        node.expression.visit(this);
+        this.visit(node.typeArguments);
+        this.visit(node.arguments);
+    };
+    BaseVisitor.prototype.visitClassExpression = function (node) {
+        node.declaration.visit(this);
+    };
+    BaseVisitor.prototype.visitCommaExpression = function (node) {
+        this.visit(node.expressions);
+    };
+    BaseVisitor.prototype.visitElementAccessExpression = function (node) {
+        node.elementExpression.visit(this);
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitFunctionExpression = function (node) {
+        node.declaration.visit(this);
+    };
+    BaseVisitor.prototype.visitLiteralExpression = function (node) {
+        // node.
+    };
+    BaseVisitor.prototype.visitFloatLiteralExpression = function (node) { };
+    BaseVisitor.prototype.visitInstanceOfExpression = function (node) {
+        node.expression.visit(this);
+        node.isType.visit(this);
+    };
+    BaseVisitor.prototype.visitIntegerLiteralExpression = function (node) { };
+    BaseVisitor.prototype.visitStringLiteral = function (str, singleQuoted) { };
+    BaseVisitor.prototype.visitStringLiteralExpression = function (node) { };
+    BaseVisitor.prototype.visitRegexpLiteralExpression = function (node) { };
+    BaseVisitor.prototype.visitNewExpression = function (node) {
+        node.expression.visit(this);
+        this.visit(node.typeArguments);
+        this.visit(node.arguments);
+    };
+    BaseVisitor.prototype.visitParenthesizedExpression = function (node) {
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitPropertyAccessExpression = function (node) {
+        node.property.visit(this);
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitTernaryExpression = function (node) {
+        node.condition.visit(this);
+        node.ifThen.visit(this);
+        node.ifElse.visit(this);
+    };
+    BaseVisitor.prototype.visitUnaryExpression = function (node) {
+        node.operand.visit(this);
+    };
+    BaseVisitor.prototype.visitUnaryPostfixExpression = function (node) {
+        node.operand.visit(this);
+    };
+    BaseVisitor.prototype.visitUnaryPrefixExpression = function (node) {
+        node.operand.visit(this);
+    };
+    BaseVisitor.prototype.visitSuperExpression = function (node) { };
+    BaseVisitor.prototype.visitFalseExpression = function (node) { };
+    BaseVisitor.prototype.visitTrueExpression = function (node) { };
+    BaseVisitor.prototype.visitThisExpression = function (node) { };
+    BaseVisitor.prototype.visitNullExperssion = function (node) { };
+    BaseVisitor.prototype.visitConstructorExpression = function (node) { };
+    BaseVisitor.prototype.visitNodeAndTerminate = function (statement) { };
+    BaseVisitor.prototype.visitBlockStatement = function (node) {
+        this.depth++;
+        this.visit(node.statements);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitBreakStatement = function (node) {
+        if (node.label) {
+            node.label.visit(this);
+        }
+    };
+    BaseVisitor.prototype.visitContinueStatement = function (node) {
+        if (node.label) {
+            node.label.visit(this);
+        }
+    };
+    BaseVisitor.prototype.visitClassDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        this.depth++;
+        this.visit(node.decorators);
+        assert(node.isGeneric ? node.typeParameters != null : node.typeParameters == null);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+        }
+        if (node.extendsType) {
+            node.extendsType.visit(this);
+        }
+        this.visit(node.implementsTypes);
+        this.visit(node.members);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitDoStatement = function (node) {
+        node.condition.visit(this);
+        node.statement.visit(this);
+    };
+    BaseVisitor.prototype.visitEmptyStatement = function (node) { };
+    BaseVisitor.prototype.visitEnumDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        this.visit(node.decorators);
+        this.visit(node.values);
+    };
+    BaseVisitor.prototype.visitEnumValueDeclaration = function (node) {
+        node.name.visit(this);
+        if (node.initializer) {
+            node.initializer.visit(this);
+        }
+    };
+    BaseVisitor.prototype.visitExportImportStatement = function (node) {
+        node.name.visit(this);
+        node.externalName.visit(this);
+    };
+    BaseVisitor.prototype.visitExportMember = function (node) {
+        node.localName.visit(this);
+        node.exportedName.visit(this);
+    };
+    BaseVisitor.prototype.visitExportStatement = function (node) {
+        if (node.path) {
+            node.path.visit(this);
+        }
+        this.visit(node.members);
+    };
+    BaseVisitor.prototype.visitExportDefaultStatement = function (node) {
+        node.declaration.visit(this);
+    };
+    BaseVisitor.prototype.visitExpressionStatement = function (node) {
+        node.expression.visit(this);
+    };
+    BaseVisitor.prototype.visitFieldDeclaration = function (node) {
+        node.name.visit(this);
+        if (node.type) {
+            node.type.visit(this);
+        }
+        if (node.initializer) {
+            node.initializer.visit(this);
+        }
+        this.visit(node.decorators);
+    };
+    BaseVisitor.prototype.visitForStatement = function (node) {
+        if (node.initializer)
+            node.initializer.visit(this);
+        if (node.condition)
+            node.condition.visit(this);
+        if (node.incrementor)
+            node.incrementor.visit(this);
+        node.statement.visit(this);
+    };
+    BaseVisitor.prototype.visitFunctionDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        this.visit(node.decorators);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+        }
+        node.signature.visit(this);
+        this.depth++;
+        if (node.body)
+            node.body.visit(this);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitFunctionCommon = function (node) {
+        // node.name.visit(this)
+    };
+    BaseVisitor.prototype.visitIfStatement = function (node) {
+        node.condition.visit(this);
+        node.ifTrue.visit(this);
+        if (node.ifFalse)
+            node.ifFalse.visit(this);
+    };
+    BaseVisitor.prototype.visitImportDeclaration = function (node) {
+        node.foreignName.visit(this);
+        node.name.visit(this);
+        this.visit(node.decorators);
+    };
+    BaseVisitor.prototype.visitImportStatement = function (node) {
+        if (node.namespaceName)
+            node.namespaceName.visit(this);
+        this.visit(node.declarations);
+    };
+    BaseVisitor.prototype.visitIndexSignatureDeclaration = function (node) {
+        // node.name.visit(this);
+        // node.keyType.visit(this);
+        // node.valueType.visit(this);
+    };
+    BaseVisitor.prototype.visitInterfaceDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+        }
+        this.visit(node.implementsTypes);
+        if (node.extendsType)
+            node.extendsType.visit(this);
+        this.depth++;
+        this.visit(node.members);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitMethodDeclaration = function (node) {
+        node.name.visit(this);
+        if (node.isGeneric) {
+            this.visit(node.typeParameters);
+        }
+        node.signature.visit(this);
+        this.visit(node.decorators);
+        this.depth++;
+        if (node.body)
+            node.body.visit(this);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitNamespaceDeclaration = function (node, isDefault) {
+        node.name.visit(this);
+        this.visit(node.decorators);
+        this.visit(node.members);
+    };
+    BaseVisitor.prototype.visitReturnStatement = function (node) {
+        if (node.value)
+            node.value.visit(this);
+    };
+    BaseVisitor.prototype.visitSwitchCase = function (node) {
+        if (node.label)
+            node.label.visit(this);
+        this.visit(node.statements);
+    };
+    BaseVisitor.prototype.visitSwitchStatement = function (node) {
+        node.condition.visit(this);
+        this.depth++;
+        this.visit(node.cases);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitThrowStatement = function (node) {
+        node.value.visit(this);
+    };
+    BaseVisitor.prototype.visitTryStatement = function (node) {
+        this.visit(node.statements);
+        if (node.catchVariable)
+            node.catchVariable.visit(this);
+        this.visit(node.catchStatements);
+        this.visit(node.finallyStatements);
+    };
+    BaseVisitor.prototype.visitTypeDeclaration = function (node) {
+        node.name.visit(this);
+        this.visit(node.decorators);
+        node.type.visit(this);
+        this.visit(node.typeParameters);
+    };
+    BaseVisitor.prototype.visitVariableDeclaration = function (node) {
+        node.name.visit(this);
+        if (node.type)
+            node.type.visit(this);
+        if (node.initializer)
+            node.initializer.visit(this);
+    };
+    BaseVisitor.prototype.visitVariableStatement = function (node) {
+        this.visit(node.decorators);
+        this.visit(node.declarations);
+    };
+    BaseVisitor.prototype.visitWhileStatement = function (node) {
+        node.condition.visit(this);
+        this.depth++;
+        node.statement.visit(this);
+        this.depth--;
+    };
+    BaseVisitor.prototype.visitVoidStatement = function (node) { };
+    BaseVisitor.prototype.visitComment = function (node) { };
+    BaseVisitor.prototype.visitDecoratorNode = function (node) {
+        node.name.visit(this);
+        this.visit(node.arguments);
+    };
+    BaseVisitor.prototype.visitParameter = function (node) {
+        node.name.visit(this);
+        if (node.implicitFieldDeclaration) {
+            node.implicitFieldDeclaration.visit(this);
+        }
+        if (node.initializer)
+            node.initializer.visit(this);
+        node.type.visit(this);
+    };
+    return BaseVisitor;
+}(visitor_1.AbstractVisitor));
+exports.BaseVisitor = BaseVisitor;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hc3QvYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNEVBLHNDQUE2QztBQUk3QztJQUFpQywrQkFBcUI7SUFBdEQ7UUFBQSxxRUEwWkM7UUF6WkMsV0FBSyxHQUFXLENBQUMsQ0FBQzs7SUF5WnBCLENBQUM7SUF2WkMsdURBQXVEO0lBQ3ZELDJDQUEyQztJQUMzQyxpQkFBaUI7SUFDakIsMEJBQTBCO0lBQzFCLG9DQUFvQztJQUNwQyxVQUFVO0lBQ1YsTUFBTTtJQUNOLElBQUk7SUFFSixpQ0FBVyxHQUFYLFVBQVksSUFBWTs7O1lBQ3RCLEtBQW1CLElBQUEsS0FBQSxTQUFBLElBQUksQ0FBQyxVQUFVLENBQUEsZ0JBQUEsNEJBQUU7Z0JBQS9CLElBQU0sSUFBSSxXQUFBO2dCQUNiLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDYixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNqQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7YUFDZDs7Ozs7Ozs7O0lBQ0gsQ0FBQztJQUVELG1DQUFhLEdBQWIsVUFBYyxJQUFjLElBQVMsQ0FBQztJQUV0QyxtQ0FBYSxHQUFiLFVBQWMsSUFBYztRQUMxQixJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QixJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDYixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ2xCO0lBQ0gsQ0FBQztJQUVELHdDQUFrQixHQUFsQixVQUFtQixJQUFtQjtRQUNwQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lB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VyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuRCxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBQ0gsa0JBQUM7QUFBRCxDQUFDLEFBMVpELENBQWlDLHlCQUFlLEdBMFovQztBQTFaWSxrQ0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIFNvdXJjZSxcbiAgVHlwZU5vZGUsXG4gIFR5cGVOYW1lLFxuICBOYW1lZFR5cGVOb2RlLFxuICBGdW5jdGlvblR5cGVOb2RlLFxuICBUeXBlUGFyYW1ldGVyTm9kZSxcbiAgSWRlbnRpZmllckV4cHJlc3Npb24sXG4gIEFycmF5TGl0ZXJhbEV4cHJlc3Npb24sXG4gIE9iamVjdExpdGVyYWxFeHByZXNzaW9uLFxuICBBc3NlcnRpb25FeHByZXNzaW9uLFxuICBCaW5hcnlFeHByZXNzaW9uLFxuICBDYWxsRXhwcmVzc2lvbixcbiAgQ2xhc3NFeHByZXNzaW9uLFxuICBDb21tYUV4cHJlc3Npb24sXG4gIEVsZW1lbnRBY2Nlc3NFeHByZXNzaW9uLFxuICBGdW5jdGlvbkV4cHJlc3Npb24sXG4gIExpdGVyYWxFeHByZXNzaW9uLFxuICBGbG9hdExpdGVyYWxFeHByZXNzaW9uLFxuICBJbnN0YW5jZU9mRXhwcmVzc2lvbixcbiAgSW50ZWdlckxpdGVyYWxFeHByZXNzaW9uLFxuICBTdHJpbmdMaXRlcmFsRXhwcmVzc2lvbixcbiAgUmVnZXhwTGl0ZXJhbEV4cHJlc3Npb24sXG4gIE5ld0V4cHJlc3Npb24sXG4gIFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uLFxuICBQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24sXG4gIFRlcm5hcnlFeHByZXNzaW9uLFxuICBVbmFyeUV4cHJlc3Npb24sXG4gIFVuYXJ5UG9zdGZpeEV4cHJlc3Npb24sXG4gIFVuYXJ5UHJlZml4RXhwcmVzc2lvbixcbiAgU3VwZXJFeHByZXNzaW9uLFxuICBGYWxzZUV4cHJlc3Npb24sXG4gIFRydWVFeHByZXNzaW9uLFxuICBUaGlzRXhwcmVzc2lvbixcbiAgTnVsbEV4cHJlc3Npb24sXG4gIENvbnN0cnVjdG9yRXhwcmVzc2lvbixcbiAgU3RhdGVtZW50LFxuICBCbG9ja1N0YXRlbWVudCxcbiAgQnJlYWtTdGF0ZW1lbnQsXG4gIENvbnRpbnVlU3RhdGVtZW50LFxuICBDbGFzc0RlY2xhcmF0aW9uLFxuICBEb1N0YXRlbWVudCxcbiAgRW1wdHlTdGF0ZW1lbnQsXG4gIEVudW1EZWNsYXJhdGlvbixcbiAgRW51bVZhbHVlRGVjbGFyYXRpb24sXG4gIEV4cG9ydEltcG9ydFN0YXRlbWVudCxcbiAgRXhwb3J0TWVtYmVyLFxuICBFeHBvcnRTdGF0ZW1lbnQsXG4gIEV4cG9ydERlZmF1bHRTdGF0ZW1lbnQsXG4gIEV4cHJlc3Npb25TdGF0ZW1lbnQsXG4gIEZpZWxkRGVjbGFyYXRpb24sXG4gIEZvclN0YXRlbWVudCxcbiAgRnVuY3Rpb25EZWNsYXJhdGlvbixcbiAgSWZTdGF0ZW1lbnQsXG4gIEltcG9ydERlY2xhcmF0aW9uLFxuICBJbXBvcnRTdGF0ZW1lbnQsXG4gIEluZGV4U2lnbmF0dXJlRGVjbGFyYXRpb24sXG4gIEludGVyZmFjZURlY2xhcmF0aW9uLFxuICBNZXRob2REZWNsYXJhdGlvbixcbiAgTmFtZXNwYWNlRGVjbGFyYXRpb24sXG4gIFJldHVyblN0YXRlbWVudCxcbiAgU3dpdGNoQ2FzZSxcbiAgU3dpdGNoU3RhdGVtZW50LFxuICBUaHJvd1N0YXRlbWVudCxcbiAgVHJ5U3RhdGVtZW50LFxuICBUeXBlRGVjbGFyYXRpb24sXG4gIFZhcmlhYmxlRGVjbGFyYXRpb24sXG4gIFZhcmlhYmxlU3RhdGVtZW50LFxuICBXaGlsZVN0YXRlbWVudCxcbiAgVm9pZFN0YXRlbWVudCxcbiAgQ29tbWVudE5vZGUsXG4gIERlY29yYXRvck5vZGUsXG4gIFBhcmFtZXRlck5vZGUsXG4gIE5vZGVcbn0gZnJvbSBcImFzc2VtYmx5c2NyaXB0XCI7XG5cbmltcG9ydCB7IEFic3RyYWN0VmlzaXRvciB9IGZyb20gXCIuLi92aXNpdG9yXCI7XG5pbXBvcnQgeyBBU1RWaXNpdG9yIH0gZnJvbSBcIi5cIjtcblxuXG5leHBvcnQgY2xhc3MgQmFzZVZpc2l0b3IgZXh0ZW5kcyBBYnN0cmFjdFZpc2l0b3I8Tm9kZT4gaW1wbGVtZW50cyBBU1RWaXNpdG9yIHtcbiAgZGVwdGg6IG51bWJlciA9IDA7XG5cbiAgLy8gLyoqIFZpc2l0cyBlYWNoIG5vZGUgaW4gYW4gYXJyYXkgaWYgYXJyYXkgZXhpc3RzLiAqL1xuICAvLyB2aXNpdEFycmF5KGFycmF5OiBOb2RlW10gfCBudWxsKTogdm9pZCB7XG4gIC8vICAgaWYgKGFycmF5KSB7XG4gIC8vICAgICBhcnJheS5tYXAobm9kZSA9PiB7XG4gIC8vICAgICAgIGlmIChub2RlKSBub2RlLnZpc2l0KHRoaXMpO1xuICAvLyAgICAgfSk7XG4gIC8vICAgfVxuICAvLyB9XG5cbiAgdmlzaXRTb3VyY2Uobm9kZTogU291cmNlKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBzdG10IG9mIG5vZGUuc3RhdGVtZW50cykge1xuICAgICAgdGhpcy5kZXB0aCsrO1xuICAgICAgc3RtdC52aXNpdCh0aGlzKTtcbiAgICAgIHRoaXMuZGVwdGgtLTtcbiAgICB9XG4gIH1cblxuICB2aXNpdFR5cGVOb2RlKG5vZGU6IFR5cGVOb2RlKTogdm9pZCB7fVxuXG4gIHZpc2l0VHlwZU5hbWUobm9kZTogVHlwZU5hbWUpOiB2b2lkIHtcbiAgICBub2RlLmlkZW50aWZpZXIudmlzaXQodGhpcyk7XG4gICAgaWYgKG5vZGUubmV4dCkge1xuICAgICAgbm9kZS52aXNpdCh0aGlzKTtcbiAgICB9XG4gIH1cblxuICB2aXNpdE5hbWVkVHlwZU5vZGUobm9kZTogTmFtZWRUeXBlTm9kZSk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUudHlwZUFyZ3VtZW50cyk7XG4gIH1cblxuICB2aXNpdEZ1bmN0aW9uVHlwZU5vZGUobm9kZTogRnVuY3Rpb25UeXBlTm9kZSk6IHZvaWQge1xuICAgIGZvciAobGV0IHBhcmFtIG9mIG5vZGUucGFyYW1ldGVycykge1xuICAgICAgcGFyYW0udmlzaXQodGhpcyk7XG4gICAgfVxuICAgIG5vZGUucmV0dXJuVHlwZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0VHlwZVBhcmFtZXRlcihub2RlOiBUeXBlUGFyYW1ldGVyTm9kZSk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICBpZiAobm9kZS5leHRlbmRzVHlwZSkgbm9kZS5leHRlbmRzVHlwZS52aXNpdCh0aGlzKTtcbiAgICBpZiAobm9kZS5kZWZhdWx0VHlwZSkgbm9kZS5kZWZhdWx0VHlwZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0SWRlbnRpZmllckV4cHJlc3Npb24obm9kZTogSWRlbnRpZmllckV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRBcnJheUxpdGVyYWxFeHByZXNzaW9uKG5vZGU6IEFycmF5TGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLmVsZW1lbnRFeHByZXNzaW9ucy5tYXAoZSA9PiB7XG4gICAgICBpZiAoZSkgZS52aXNpdCh0aGlzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHZpc2l0T2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24obm9kZTogT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBpZiAobm9kZS52YWx1ZXMgJiYgbm9kZS5uYW1lcykge1xuICAgICAgYXNzZXJ0KG5vZGUudmFsdWVzLmxlbmd0aCA9PSBub2RlLm5hbWVzLmxlbmd0aCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGUudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG5vZGUubmFtZXNbaV0udmlzaXQodGhpcyk7XG4gICAgICAgIG5vZGUudmFsdWVzW2ldLnZpc2l0KHRoaXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZpc2l0QXNzZXJ0aW9uRXhwcmVzc2lvbihub2RlOiBBc3NlcnRpb25FeHByZXNzaW9uKTogdm9pZCB7XG4gICAgaWYgKG5vZGUudG9UeXBlKSBub2RlLnRvVHlwZS52aXNpdCh0aGlzKTtcbiAgICBub2RlLmV4cHJlc3Npb24udmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEJpbmFyeUV4cHJlc3Npb24obm9kZTogQmluYXJ5RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUubGVmdC52aXNpdCh0aGlzKTtcbiAgICBub2RlLnJpZ2h0LnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRDYWxsRXhwcmVzc2lvbihub2RlOiBDYWxsRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUuZXhwcmVzc2lvbi52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUudHlwZUFyZ3VtZW50cyk7XG4gICAgdGhpcy52aXNpdChub2RlLmFyZ3VtZW50cyk7XG4gIH1cblxuICB2aXNpdENsYXNzRXhwcmVzc2lvbihub2RlOiBDbGFzc0V4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLmRlY2xhcmF0aW9uLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRDb21tYUV4cHJlc3Npb24obm9kZTogQ29tbWFFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy52aXNpdChub2RlLmV4cHJlc3Npb25zKTtcbiAgfVxuXG4gIHZpc2l0RWxlbWVudEFjY2Vzc0V4cHJlc3Npb24obm9kZTogRWxlbWVudEFjY2Vzc0V4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLmVsZW1lbnRFeHByZXNzaW9uLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUuZXhwcmVzc2lvbi52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0RnVuY3Rpb25FeHByZXNzaW9uKG5vZGU6IEZ1bmN0aW9uRXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUuZGVjbGFyYXRpb24udmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdExpdGVyYWxFeHByZXNzaW9uKG5vZGU6IExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgLy8gbm9kZS5cbiAgfVxuXG4gIHZpc2l0RmxvYXRMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBGbG9hdExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7fVxuXG4gIHZpc2l0SW5zdGFuY2VPZkV4cHJlc3Npb24obm9kZTogSW5zdGFuY2VPZkV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLmV4cHJlc3Npb24udmlzaXQodGhpcyk7XG4gICAgbm9kZS5pc1R5cGUudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEludGVnZXJMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBJbnRlZ2VyTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRTdHJpbmdMaXRlcmFsKHN0cjogc3RyaW5nLCBzaW5nbGVRdW90ZWQ/OiBib29sZWFuKTogdm9pZCB7fVxuXG4gIHZpc2l0U3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogU3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRSZWdleHBMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBSZWdleHBMaXRlcmFsRXhwcmVzc2lvbik6IHZvaWQge31cblxuICB2aXNpdE5ld0V4cHJlc3Npb24obm9kZTogTmV3RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUuZXhwcmVzc2lvbi52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUudHlwZUFyZ3VtZW50cyk7XG4gICAgdGhpcy52aXNpdChub2RlLmFyZ3VtZW50cyk7XG4gIH1cblxuICB2aXNpdFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uKG5vZGU6IFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgbm9kZS5leHByZXNzaW9uLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24obm9kZTogUHJvcGVydHlBY2Nlc3NFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgbm9kZS5wcm9wZXJ0eS52aXNpdCh0aGlzKTtcbiAgICBub2RlLmV4cHJlc3Npb24udmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdFRlcm5hcnlFeHByZXNzaW9uKG5vZGU6IFRlcm5hcnlFeHByZXNzaW9uKTogdm9pZCB7XG4gICAgbm9kZS5jb25kaXRpb24udmlzaXQodGhpcyk7XG4gICAgbm9kZS5pZlRoZW4udmlzaXQodGhpcyk7XG4gICAgbm9kZS5pZkVsc2UudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdFVuYXJ5RXhwcmVzc2lvbihub2RlOiBVbmFyeUV4cHJlc3Npb24pOiB2b2lkIHtcbiAgICBub2RlLm9wZXJhbmQudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdFVuYXJ5UG9zdGZpeEV4cHJlc3Npb24obm9kZTogVW5hcnlQb3N0Zml4RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUub3BlcmFuZC52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0VW5hcnlQcmVmaXhFeHByZXNzaW9uKG5vZGU6IFVuYXJ5UHJlZml4RXhwcmVzc2lvbik6IHZvaWQge1xuICAgIG5vZGUub3BlcmFuZC52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0U3VwZXJFeHByZXNzaW9uKG5vZGU6IFN1cGVyRXhwcmVzc2lvbik6IHZvaWQge31cblxuICB2aXNpdEZhbHNlRXhwcmVzc2lvbihub2RlOiBGYWxzZUV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRUcnVlRXhwcmVzc2lvbihub2RlOiBUcnVlRXhwcmVzc2lvbik6IHZvaWQge31cblxuICB2aXNpdFRoaXNFeHByZXNzaW9uKG5vZGU6IFRoaXNFeHByZXNzaW9uKTogdm9pZCB7fVxuXG4gIHZpc2l0TnVsbEV4cGVyc3Npb24obm9kZTogTnVsbEV4cHJlc3Npb24pOiB2b2lkIHt9XG5cbiAgdmlzaXRDb25zdHJ1Y3RvckV4cHJlc3Npb24obm9kZTogQ29uc3RydWN0b3JFeHByZXNzaW9uKTogdm9pZCB7fVxuXG4gIHZpc2l0Tm9kZUFuZFRlcm1pbmF0ZShzdGF0ZW1lbnQ6IFN0YXRlbWVudCk6IHZvaWQge31cblxuICB2aXNpdEJsb2NrU3RhdGVtZW50KG5vZGU6IEJsb2NrU3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy5kZXB0aCsrO1xuICAgIHRoaXMudmlzaXQobm9kZS5zdGF0ZW1lbnRzKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cblxuICB2aXNpdEJyZWFrU3RhdGVtZW50KG5vZGU6IEJyZWFrU3RhdGVtZW50KTogdm9pZCB7XG4gICAgaWYgKG5vZGUubGFiZWwpIHtcbiAgICAgIG5vZGUubGFiZWwudmlzaXQodGhpcyk7XG4gICAgfVxuICB9XG5cbiAgdmlzaXRDb250aW51ZVN0YXRlbWVudChub2RlOiBDb250aW51ZVN0YXRlbWVudCk6IHZvaWQge1xuICAgIGlmIChub2RlLmxhYmVsKSB7XG4gICAgICBub2RlLmxhYmVsLnZpc2l0KHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHZpc2l0Q2xhc3NEZWNsYXJhdGlvbihub2RlOiBDbGFzc0RlY2xhcmF0aW9uLCBpc0RlZmF1bHQ/OiBib29sZWFuKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIHRoaXMuZGVwdGgrKztcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgYXNzZXJ0KFxuICAgICAgbm9kZS5pc0dlbmVyaWMgPyBub2RlLnR5cGVQYXJhbWV0ZXJzICE9IG51bGwgOiBub2RlLnR5cGVQYXJhbWV0ZXJzID09IG51bGxcbiAgICApO1xuICAgIGlmIChub2RlLmlzR2VuZXJpYykge1xuICAgICAgdGhpcy52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJzKTtcbiAgICB9XG4gICAgaWYgKG5vZGUuZXh0ZW5kc1R5cGUpIHtcbiAgICAgIG5vZGUuZXh0ZW5kc1R5cGUudmlzaXQodGhpcyk7XG4gICAgfVxuICAgIHRoaXMudmlzaXQobm9kZS5pbXBsZW1lbnRzVHlwZXMpO1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cblxuICB2aXNpdERvU3RhdGVtZW50KG5vZGU6IERvU3RhdGVtZW50KTogdm9pZCB7XG4gICAgbm9kZS5jb25kaXRpb24udmlzaXQodGhpcyk7XG4gICAgbm9kZS5zdGF0ZW1lbnQudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEVtcHR5U3RhdGVtZW50KG5vZGU6IEVtcHR5U3RhdGVtZW50KTogdm9pZCB7fVxuXG4gIHZpc2l0RW51bURlY2xhcmF0aW9uKG5vZGU6IEVudW1EZWNsYXJhdGlvbiwgaXNEZWZhdWx0PzogYm9vbGVhbik6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgdGhpcy52aXNpdChub2RlLnZhbHVlcyk7XG4gIH1cblxuICB2aXNpdEVudW1WYWx1ZURlY2xhcmF0aW9uKG5vZGU6IEVudW1WYWx1ZURlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmluaXRpYWxpemVyKSB7XG4gICAgICBub2RlLmluaXRpYWxpemVyLnZpc2l0KHRoaXMpO1xuICAgIH1cbiAgfVxuXG4gIHZpc2l0RXhwb3J0SW1wb3J0U3RhdGVtZW50KG5vZGU6IEV4cG9ydEltcG9ydFN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICBub2RlLmV4dGVybmFsTmFtZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0RXhwb3J0TWVtYmVyKG5vZGU6IEV4cG9ydE1lbWJlcik6IHZvaWQge1xuICAgIG5vZGUubG9jYWxOYW1lLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUuZXhwb3J0ZWROYW1lLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRFeHBvcnRTdGF0ZW1lbnQobm9kZTogRXhwb3J0U3RhdGVtZW50KTogdm9pZCB7XG4gICAgaWYgKG5vZGUucGF0aCkge1xuICAgICAgbm9kZS5wYXRoLnZpc2l0KHRoaXMpO1xuICAgIH1cbiAgICB0aGlzLnZpc2l0KG5vZGUubWVtYmVycyk7XG4gIH1cblxuICB2aXNpdEV4cG9ydERlZmF1bHRTdGF0ZW1lbnQobm9kZTogRXhwb3J0RGVmYXVsdFN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUuZGVjbGFyYXRpb24udmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEV4cHJlc3Npb25TdGF0ZW1lbnQobm9kZTogRXhwcmVzc2lvblN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUuZXhwcmVzc2lvbi52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0RmllbGREZWNsYXJhdGlvbihub2RlOiBGaWVsZERlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLnR5cGUpIHtcbiAgICAgIG5vZGUudHlwZS52aXNpdCh0aGlzKTtcbiAgICB9XG4gICAgaWYgKG5vZGUuaW5pdGlhbGl6ZXIpIHtcbiAgICAgIG5vZGUuaW5pdGlhbGl6ZXIudmlzaXQodGhpcyk7XG4gICAgfVxuICAgIHRoaXMudmlzaXQobm9kZS5kZWNvcmF0b3JzKTtcbiAgfVxuXG4gIHZpc2l0Rm9yU3RhdGVtZW50KG5vZGU6IEZvclN0YXRlbWVudCk6IHZvaWQge1xuICAgIGlmIChub2RlLmluaXRpYWxpemVyKSBub2RlLmluaXRpYWxpemVyLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmNvbmRpdGlvbikgbm9kZS5jb25kaXRpb24udmlzaXQodGhpcyk7XG4gICAgaWYgKG5vZGUuaW5jcmVtZW50b3IpIG5vZGUuaW5jcmVtZW50b3IudmlzaXQodGhpcyk7XG4gICAgbm9kZS5zdGF0ZW1lbnQudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEZ1bmN0aW9uRGVjbGFyYXRpb24oXG4gICAgbm9kZTogRnVuY3Rpb25EZWNsYXJhdGlvbixcbiAgICBpc0RlZmF1bHQ/OiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgaWYgKG5vZGUuaXNHZW5lcmljKSB7XG4gICAgICB0aGlzLnZpc2l0KG5vZGUudHlwZVBhcmFtZXRlcnMpO1xuICAgIH1cbiAgICBub2RlLnNpZ25hdHVyZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLmRlcHRoKys7XG4gICAgaWYgKG5vZGUuYm9keSkgbm9kZS5ib2R5LnZpc2l0KHRoaXMpO1xuICAgIHRoaXMuZGVwdGgtLTtcbiAgfVxuXG4gIHZpc2l0RnVuY3Rpb25Db21tb24obm9kZTogRnVuY3Rpb25EZWNsYXJhdGlvbik6IHZvaWQge1xuICAgIC8vIG5vZGUubmFtZS52aXNpdCh0aGlzKVxuICB9XG5cbiAgdmlzaXRJZlN0YXRlbWVudChub2RlOiBJZlN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUuY29uZGl0aW9uLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUuaWZUcnVlLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmlmRmFsc2UpIG5vZGUuaWZGYWxzZS52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0SW1wb3J0RGVjbGFyYXRpb24obm9kZTogSW1wb3J0RGVjbGFyYXRpb24pOiB2b2lkIHtcbiAgICBub2RlLmZvcmVpZ25OYW1lLnZpc2l0KHRoaXMpO1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gIH1cblxuICB2aXNpdEltcG9ydFN0YXRlbWVudChub2RlOiBJbXBvcnRTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICBpZiAobm9kZS5uYW1lc3BhY2VOYW1lKSBub2RlLm5hbWVzcGFjZU5hbWUudmlzaXQodGhpcyk7XG4gICAgdGhpcy52aXNpdChub2RlLmRlY2xhcmF0aW9ucyk7XG4gIH1cblxuICB2aXNpdEluZGV4U2lnbmF0dXJlRGVjbGFyYXRpb24obm9kZTogSW5kZXhTaWduYXR1cmVEZWNsYXJhdGlvbik6IHZvaWQge1xuICAgIC8vIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICAvLyBub2RlLmtleVR5cGUudmlzaXQodGhpcyk7XG4gICAgLy8gbm9kZS52YWx1ZVR5cGUudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdEludGVyZmFjZURlY2xhcmF0aW9uKFxuICAgIG5vZGU6IEludGVyZmFjZURlY2xhcmF0aW9uLFxuICAgIGlzRGVmYXVsdD86IGJvb2xlYW5cbiAgKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmlzR2VuZXJpYykge1xuICAgICAgdGhpcy52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJzKTtcbiAgICB9XG4gICAgdGhpcy52aXNpdChub2RlLmltcGxlbWVudHNUeXBlcyk7XG4gICAgaWYgKG5vZGUuZXh0ZW5kc1R5cGUpIG5vZGUuZXh0ZW5kc1R5cGUudmlzaXQodGhpcyk7XG4gICAgdGhpcy5kZXB0aCsrO1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgICB0aGlzLmRlcHRoLS07XG4gIH1cblxuICB2aXNpdE1ldGhvZERlY2xhcmF0aW9uKG5vZGU6IE1ldGhvZERlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLmlzR2VuZXJpYykge1xuICAgICAgdGhpcy52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJzKTtcbiAgICB9XG4gICAgbm9kZS5zaWduYXR1cmUudmlzaXQodGhpcyk7XG4gICAgdGhpcy52aXNpdChub2RlLmRlY29yYXRvcnMpO1xuICAgIHRoaXMuZGVwdGgrKztcbiAgICBpZiAobm9kZS5ib2R5KSBub2RlLmJvZHkudmlzaXQodGhpcyk7XG4gICAgdGhpcy5kZXB0aC0tO1xuICB9XG5cbiAgdmlzaXROYW1lc3BhY2VEZWNsYXJhdGlvbihcbiAgICBub2RlOiBOYW1lc3BhY2VEZWNsYXJhdGlvbixcbiAgICBpc0RlZmF1bHQ/OiBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgdGhpcy52aXNpdChub2RlLm1lbWJlcnMpO1xuICB9XG5cbiAgdmlzaXRSZXR1cm5TdGF0ZW1lbnQobm9kZTogUmV0dXJuU3RhdGVtZW50KTogdm9pZCB7XG4gICAgaWYgKG5vZGUudmFsdWUpIG5vZGUudmFsdWUudmlzaXQodGhpcyk7XG4gIH1cblxuICB2aXNpdFN3aXRjaENhc2Uobm9kZTogU3dpdGNoQ2FzZSk6IHZvaWQge1xuICAgIGlmIChub2RlLmxhYmVsKSBub2RlLmxhYmVsLnZpc2l0KHRoaXMpO1xuICAgIHRoaXMudmlzaXQobm9kZS5zdGF0ZW1lbnRzKTtcbiAgfVxuXG4gIHZpc2l0U3dpdGNoU3RhdGVtZW50KG5vZGU6IFN3aXRjaFN0YXRlbWVudCk6IHZvaWQge1xuICAgIG5vZGUuY29uZGl0aW9uLnZpc2l0KHRoaXMpO1xuICAgIHRoaXMuZGVwdGgrKztcbiAgICB0aGlzLnZpc2l0KG5vZGUuY2FzZXMpO1xuICAgIHRoaXMuZGVwdGgtLTtcbiAgfVxuXG4gIHZpc2l0VGhyb3dTdGF0ZW1lbnQobm9kZTogVGhyb3dTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICBub2RlLnZhbHVlLnZpc2l0KHRoaXMpO1xuICB9XG5cbiAgdmlzaXRUcnlTdGF0ZW1lbnQobm9kZTogVHJ5U3RhdGVtZW50KTogdm9pZCB7XG4gICAgdGhpcy52aXNpdChub2RlLnN0YXRlbWVudHMpO1xuICAgIGlmIChub2RlLmNhdGNoVmFyaWFibGUpIG5vZGUuY2F0Y2hWYXJpYWJsZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuY2F0Y2hTdGF0ZW1lbnRzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZmluYWxseVN0YXRlbWVudHMpO1xuICB9XG5cbiAgdmlzaXRUeXBlRGVjbGFyYXRpb24obm9kZTogVHlwZURlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIHRoaXMudmlzaXQobm9kZS5kZWNvcmF0b3JzKTtcbiAgICBub2RlLnR5cGUudmlzaXQodGhpcyk7XG4gICAgdGhpcy52aXNpdChub2RlLnR5cGVQYXJhbWV0ZXJzKTtcbiAgfVxuXG4gIHZpc2l0VmFyaWFibGVEZWNsYXJhdGlvbihub2RlOiBWYXJpYWJsZURlY2xhcmF0aW9uKTogdm9pZCB7XG4gICAgbm9kZS5uYW1lLnZpc2l0KHRoaXMpO1xuICAgIGlmIChub2RlLnR5cGUpIG5vZGUudHlwZS52aXNpdCh0aGlzKTtcbiAgICBpZiAobm9kZS5pbml0aWFsaXplcikgbm9kZS5pbml0aWFsaXplci52aXNpdCh0aGlzKTtcbiAgfVxuXG4gIHZpc2l0VmFyaWFibGVTdGF0ZW1lbnQobm9kZTogVmFyaWFibGVTdGF0ZW1lbnQpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZGVjb3JhdG9ycyk7XG4gICAgdGhpcy52aXNpdChub2RlLmRlY2xhcmF0aW9ucyk7XG4gIH1cblxuICB2aXNpdFdoaWxlU3RhdGVtZW50KG5vZGU6IFdoaWxlU3RhdGVtZW50KTogdm9pZCB7XG4gICAgbm9kZS5jb25kaXRpb24udmlzaXQodGhpcyk7XG4gICAgdGhpcy5kZXB0aCsrO1xuICAgIG5vZGUuc3RhdGVtZW50LnZpc2l0KHRoaXMpO1xuICAgIHRoaXMuZGVwdGgtLTtcbiAgfVxuXG4gIHZpc2l0Vm9pZFN0YXRlbWVudChub2RlOiBWb2lkU3RhdGVtZW50KTogdm9pZCB7fVxuXG4gIHZpc2l0Q29tbWVudChub2RlOiBDb21tZW50Tm9kZSk6IHZvaWQge31cblxuICB2aXNpdERlY29yYXRvck5vZGUobm9kZTogRGVjb3JhdG9yTm9kZSk6IHZvaWQge1xuICAgIG5vZGUubmFtZS52aXNpdCh0aGlzKTtcbiAgICB0aGlzLnZpc2l0KG5vZGUuYXJndW1lbnRzKTtcbiAgfVxuXG4gIHZpc2l0UGFyYW1ldGVyKG5vZGU6IFBhcmFtZXRlck5vZGUpOiB2b2lkIHtcbiAgICBub2RlLm5hbWUudmlzaXQodGhpcyk7XG4gICAgaWYgKG5vZGUuaW1wbGljaXRGaWVsZERlY2xhcmF0aW9uKSB7XG4gICAgICBub2RlLmltcGxpY2l0RmllbGREZWNsYXJhdGlvbi52aXNpdCh0aGlzKTtcbiAgICB9XG4gICAgaWYgKG5vZGUuaW5pdGlhbGl6ZXIpIG5vZGUuaW5pdGlhbGl6ZXIudmlzaXQodGhpcyk7XG4gICAgbm9kZS50eXBlLnZpc2l0KHRoaXMpO1xuICB9XG59XG4iXX0=
\ No newline at end of file
diff --git a/lib/visitor/dist/src/ast/empty.js b/lib/visitor/dist/src/ast/empty.js
new file mode 100644
index 0000000000..2d6eb056b4
--- /dev/null
+++ b/lib/visitor/dist/src/ast/empty.js
@@ -0,0 +1,83 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var EmptyVisitor = /** @class */ (function () {
+    function EmptyVisitor() {
+    }
+    EmptyVisitor.prototype.visitSource = function (node) { };
+    EmptyVisitor.prototype.visitTypeNode = function (node) { };
+    EmptyVisitor.prototype.visitTypeName = function (node) { };
+    EmptyVisitor.prototype.visitNamedTypeNode = function (node) { };
+    EmptyVisitor.prototype.visitFunctionTypeNode = function (node) { };
+    EmptyVisitor.prototype.visitTypeParameter = function (node) { };
+    EmptyVisitor.prototype.visitIdentifierExpression = function (node) { };
+    EmptyVisitor.prototype.visitArrayLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitObjectLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitAssertionExpression = function (node) { };
+    EmptyVisitor.prototype.visitBinaryExpression = function (node) { };
+    EmptyVisitor.prototype.visitCallExpression = function (node) { };
+    EmptyVisitor.prototype.visitClassExpression = function (node) { };
+    EmptyVisitor.prototype.visitCommaExpression = function (node) { };
+    EmptyVisitor.prototype.visitElementAccessExpression = function (node) { };
+    EmptyVisitor.prototype.visitFunctionExpression = function (node) { };
+    EmptyVisitor.prototype.visitLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitFloatLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitInstanceOfExpression = function (node) { };
+    EmptyVisitor.prototype.visitIntegerLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitStringLiteral = function (str, singleQuoted) { };
+    EmptyVisitor.prototype.visitStringLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitRegexpLiteralExpression = function (node) { };
+    EmptyVisitor.prototype.visitNewExpression = function (node) { };
+    EmptyVisitor.prototype.visitParenthesizedExpression = function (node) { };
+    EmptyVisitor.prototype.visitPropertyAccessExpression = function (node) { };
+    EmptyVisitor.prototype.visitTernaryExpression = function (node) { };
+    EmptyVisitor.prototype.visitUnaryExpression = function (node) { };
+    EmptyVisitor.prototype.visitUnaryPostfixExpression = function (node) { };
+    EmptyVisitor.prototype.visitUnaryPrefixExpression = function (node) { };
+    EmptyVisitor.prototype.visitSuperExpression = function (node) { };
+    EmptyVisitor.prototype.visitFalseExpression = function (node) { };
+    EmptyVisitor.prototype.visitTrueExpression = function (node) { };
+    EmptyVisitor.prototype.visitThisExpression = function (node) { };
+    EmptyVisitor.prototype.visitNullExperssion = function (node) { };
+    EmptyVisitor.prototype.visitConstructorExpression = function (node) { };
+    EmptyVisitor.prototype.visitNodeAndTerminate = function (statement) { };
+    EmptyVisitor.prototype.visitBlockStatement = function (node) { };
+    EmptyVisitor.prototype.visitBreakStatement = function (node) { };
+    EmptyVisitor.prototype.visitContinueStatement = function (node) { };
+    EmptyVisitor.prototype.visitClassDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitDoStatement = function (node) { };
+    EmptyVisitor.prototype.visitEmptyStatement = function (node) { };
+    EmptyVisitor.prototype.visitEnumDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitEnumValueDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitExportImportStatement = function (node) { };
+    EmptyVisitor.prototype.visitExportMember = function (node) { };
+    EmptyVisitor.prototype.visitExportStatement = function (node) { };
+    EmptyVisitor.prototype.visitExportDefaultStatement = function (node) { };
+    EmptyVisitor.prototype.visitExpressionStatement = function (node) { };
+    EmptyVisitor.prototype.visitFieldDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitForStatement = function (node) { };
+    EmptyVisitor.prototype.visitFunctionDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitFunctionCommon = function (node) { };
+    EmptyVisitor.prototype.visitIfStatement = function (node) { };
+    EmptyVisitor.prototype.visitImportDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitImportStatement = function (node) { };
+    EmptyVisitor.prototype.visitIndexSignatureDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitInterfaceDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitMethodDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitNamespaceDeclaration = function (node, isDefault) { };
+    EmptyVisitor.prototype.visitReturnStatement = function (node) { };
+    EmptyVisitor.prototype.visitSwitchCase = function (node) { };
+    EmptyVisitor.prototype.visitSwitchStatement = function (node) { };
+    EmptyVisitor.prototype.visitThrowStatement = function (node) { };
+    EmptyVisitor.prototype.visitTryStatement = function (node) { };
+    EmptyVisitor.prototype.visitTypeDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitVariableDeclaration = function (node) { };
+    EmptyVisitor.prototype.visitVariableStatement = function (node) { };
+    EmptyVisitor.prototype.visitWhileStatement = function (node) { };
+    EmptyVisitor.prototype.visitVoidStatement = function (node) { };
+    EmptyVisitor.prototype.visitComment = function (node) { };
+    EmptyVisitor.prototype.visitDecoratorNode = function (node) { };
+    EmptyVisitor.prototype.visitParameter = function (node) { };
+    return EmptyVisitor;
+}());
+exports.EmptyVisitor = EmptyVisitor;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1wdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXN0L2VtcHR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBNEVBO0lBQUE7SUFvRkEsQ0FBQztJQW5GQyxrQ0FBVyxHQUFYLFVBQVksSUFBWSxJQUFTLENBQUM7SUFDbEMsb0NBQWEsR0FBYixVQUFjLElBQWMsSUFBUyxDQUFDO0lBQ3RDLG9DQUFhLEdBQWIsVUFBYyxJQUFjLElBQVMsQ0FBQztJQUN0Qyx5Q0FBa0IsR0FBbEIsVUFBbUIsSUFBbUIsSUFBUyxDQUFDO0lBQ2hELDRDQUFxQixHQUFyQixVQUFzQixJQUFzQixJQUFTLENBQUM7SUFDdEQseUNBQWtCLEdBQWxCLFVBQW1CLElBQXVCLElBQVMsQ0FBQztJQUNwRCxnREFBeUIsR0FBekIsVUFBMEIsSUFBMEIsSUFBUyxDQUFDO0lBQzlELGtEQUEyQixHQUEzQixVQUE0QixJQUE0QixJQUFTLENBQUM7SUFDbEUsbURBQTRCLEdBQTVCLFVBQTZCLElBQTZCLElBQVMsQ0FBQztJQUNwRSwrQ0FBd0IsR0FBeEIsVUFBeUIsSUFBeUIsSUFBUyxDQUFDO0lBQzVELDRDQUFxQixHQUFyQixVQUFzQixJQUFzQixJQUFTLENBQUM7SUFDdEQsMENBQW1CLEdBQW5CLFVBQW9CLElBQW9CLElBQVMsQ0FBQztJQUNsRCwyQ0FBb0IsR0FBcEIsVUFBcUIsSUFBcUIsSUFBUyxDQUFDO0lBQ3BELDJDQUFvQixHQUFwQixVQUFxQixJQUFxQixJQUFTLENBQUM7SUFDcEQsbURBQTRCLEdBQTVCLFVBQTZCLElBQTZCLElBQVMsQ0FBQztJQUNwRSw4Q0FBdUIsR0FBdkIsVUFBd0IsSUFBd0IsSUFBUyxDQUFDO0lBQzFELDZDQUFzQixHQUF0QixVQUF1QixJQUF1QixJQUFTLENBQUM7SUFDeEQsa0RBQTJCLEdBQTNCLFVBQTRCLElBQTRCLElBQVMsQ0FBQztJQUNsRSxnREFBeUIsR0FBekIsVUFBMEIsSUFBMEIsSUFBUyxDQUFD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QXBCLFVBQXFCLElBQXFCLElBQVMsQ0FBQztJQUNwRCxzQ0FBZSxHQUFmLFVBQWdCLElBQWdCLElBQVMsQ0FBQztJQUMxQywyQ0FBb0IsR0FBcEIsVUFBcUIsSUFBcUIsSUFBUyxDQUFDO0lBQ3BELDBDQUFtQixHQUFuQixVQUFvQixJQUFvQixJQUFTLENBQUM7SUFDbEQsd0NBQWlCLEdBQWpCLFVBQWtCLElBQWtCLElBQVMsQ0FBQztJQUM5QywyQ0FBb0IsR0FBcEIsVUFBcUIsSUFBcUIsSUFBUyxDQUFDO0lBQ3BELCtDQUF3QixHQUF4QixVQUF5QixJQUF5QixJQUFTLENBQUM7SUFDNUQsNkNBQXNCLEdBQXRCLFVBQXVCLElBQXVCLElBQVMsQ0FBQztJQUN4RCwwQ0FBbUIsR0FBbkIsVUFBb0IsSUFBb0IsSUFBUyxDQUFDO0lBQ2xELHlDQUFrQixHQUFsQixVQUFtQixJQUFtQixJQUFTLENBQUM7SUFDaEQsbUNBQVksR0FBWixVQUFhLElBQWlCLElBQVMsQ0FBQztJQUN4Qyx5Q0FBa0IsR0FBbEIsVUFBbUIsSUFBbUIsSUFBUyxDQUFDO0lBQ2hELHFDQUFjLEdBQWQsVUFBZSxJQUFtQixJQUFTLENBQUM7SUFDOUMsbUJBQUM7QUFBRCxDQUFDLEFBcEZELElBb0ZDO0FBcEZZLG9DQUFZIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQVNUVmlzaXRvcixcbiAgU291cmNlLFxuICBUeXBlTm9kZSxcbiAgVHlwZU5hbWUsXG4gIE5hbWVkVHlwZU5vZGUsXG4gIEZ1bmN0aW9uVHlwZU5vZGUsXG4gIFR5cGVQYXJhbWV0ZXJOb2RlLFxuICBJZGVudGlmaWVyRXhwcmVzc2lvbixcbiAgQXJyYXlMaXRlcmFsRXhwcmVzc2lvbixcbiAgT2JqZWN0TGl0ZXJhbEV4cHJlc3Npb24sXG4gIEFzc2VydGlvbkV4cHJlc3Npb24sXG4gIEJpbmFyeUV4cHJlc3Npb24sXG4gIENhbGxFeHByZXNzaW9uLFxuICBDbGFzc0V4cHJlc3Npb24sXG4gIENvbW1hRXhwcmVzc2lvbixcbiAgRWxlbWVudEFjY2Vzc0V4cHJlc3Npb24sXG4gIEZ1bmN0aW9uRXhwcmVzc2lvbixcbiAgTGl0ZXJhbEV4cHJlc3Npb24sXG4gIEZsb2F0TGl0ZXJhbEV4cHJlc3Npb24sXG4gIEluc3RhbmNlT2ZFeHByZXNzaW9uLFxuICBJbnRlZ2VyTGl0ZXJhbEV4cHJlc3Npb24sXG4gIFN0cmluZ0xpdGVyYWxFeHByZXNzaW9uLFxuICBSZWdleHBMaXRlcmFsRXhwcmVzc2lvbixcbiAgTmV3RXhwcmVzc2lvbixcbiAgUGFyZW50aGVzaXplZEV4cHJlc3Npb24sXG4gIFByb3BlcnR5QWNjZXNzRXhwcmVzc2lvbixcbiAgVGVybmFyeUV4cHJlc3Npb24sXG4gIFVuYXJ5RXhwcmVzc2lvbixcbiAgVW5hcnlQb3N0Zml4RXhwcmVzc2lvbixcbiAgVW5hcnlQcmVmaXhFeHByZXNzaW9uLFxuICBTdXBlckV4cHJlc3Npb24sXG4gIEZhbHNlRXhwcmVzc2lvbixcbiAgVHJ1ZUV4cHJlc3Npb24sXG4gIFRoaXNFeHByZXNzaW9uLFxuICBOdWxsRXhwcmVzc2lvbixcbiAgQ29uc3RydWN0b3JFeHByZXNzaW9uLFxuICBTdGF0ZW1lbnQsXG4gIEJsb2NrU3RhdGVtZW50LFxuICBCcmVha1N0YXRlbWVudCxcbiAgQ29udGludWVTdGF0ZW1lbnQsXG4gIENsYXNzRGVjbGFyYXRpb24sXG4gIERvU3RhdGVtZW50LFxuICBFbXB0eVN0YXRlbWVudCxcbiAgRW51bURlY2xhcmF0aW9uLFxuICBFbnVtVmFsdWVEZWNsYXJhdGlvbixcbiAgRXhwb3J0SW1wb3J0U3RhdGVtZW50LFxuICBFeHBvcnRNZW1iZXIsXG4gIEV4cG9ydFN0YXRlbWVudCxcbiAgRXhwb3J0RGVmYXVsdFN0YXRlbWVudCxcbiAgRXhwcmVzc2lvblN0YXRlbWVudCxcbiAgRmllbGREZWNsYXJhdGlvbixcbiAgRm9yU3RhdGVtZW50LFxuICBGdW5jdGlvbkRlY2xhcmF0aW9uLFxuICBJZlN0YXRlbWVudCxcbiAgSW1wb3J0RGVjbGFyYXRpb24sXG4gIEltcG9ydFN0YXRlbWVudCxcbiAgSW5kZXhTaWduYXR1cmVEZWNsYXJhdGlvbixcbiAgSW50ZXJmYWNlRGVjbGFyYXRpb24sXG4gIE1ldGhvZERlY2xhcmF0aW9uLFxuICBOYW1lc3BhY2VEZWNsYXJhdGlvbixcbiAgUmV0dXJuU3RhdGVtZW50LFxuICBTd2l0Y2hDYXNlLFxuICBTd2l0Y2hTdGF0ZW1lbnQsXG4gIFRocm93U3RhdGVtZW50LFxuICBUcnlTdGF0ZW1lbnQsXG4gIFR5cGVEZWNsYXJhdGlvbixcbiAgVmFyaWFibGVEZWNsYXJhdGlvbixcbiAgVmFyaWFibGVTdGF0ZW1lbnQsXG4gIFdoaWxlU3RhdGVtZW50LFxuICBWb2lkU3RhdGVtZW50LFxuICBDb21tZW50Tm9kZSxcbiAgRGVjb3JhdG9yTm9kZSxcbiAgUGFyYW1ldGVyTm9kZVxufSBmcm9tIFwiYXNzZW1ibHlzY3JpcHRcIjtcblxuZXhwb3J0IGNsYXNzIEVtcHR5VmlzaXRvciBpbXBsZW1lbnRzIEFTVFZpc2l0b3Ige1xuICB2aXNpdFNvdXJjZShub2RlOiBTb3VyY2UpOiB2b2lkIHt9XG4gIHZpc2l0VHlwZU5vZGUobm9kZTogVHlwZU5vZGUpOiB2b2lkIHt9XG4gIHZpc2l0VHlwZU5hbWUobm9kZTogVHlwZU5hbWUpOiB2b2lkIHt9XG4gIHZpc2l0TmFtZWRUeXBlTm9kZShub2RlOiBOYW1lZFR5cGVOb2RlKTogdm9pZCB7fVxuICB2aXNpdEZ1bmN0aW9uVHlwZU5vZGUobm9kZTogRnVuY3Rpb25UeXBlTm9kZSk6IHZvaWQge31cbiAgdmlzaXRUeXBlUGFyYW1ldGVyKG5vZGU6IFR5cGVQYXJhbWV0ZXJOb2RlKTogdm9pZCB7fVxuICB2aXNpdElkZW50aWZpZXJFeHByZXNzaW9uKG5vZGU6IElkZW50aWZpZXJFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdEFycmF5TGl0ZXJhbEV4cHJlc3Npb24obm9kZTogQXJyYXlMaXRlcmFsRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRPYmplY3RMaXRlcmFsRXhwcmVzc2lvbihub2RlOiBPYmplY3RMaXRlcmFsRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRBc3NlcnRpb25FeHByZXNzaW9uKG5vZGU6IEFzc2VydGlvbkV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0QmluYXJ5RXhwcmVzc2lvbihub2RlOiBCaW5hcnlFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdENhbGxFeHByZXNzaW9uKG5vZGU6IENhbGxFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdENsYXNzRXhwcmVzc2lvbihub2RlOiBDbGFzc0V4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0Q29tbWFFeHByZXNzaW9uKG5vZGU6IENvbW1hRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRFbGVtZW50QWNjZXNzRXhwcmVzc2lvbihub2RlOiBFbGVtZW50QWNjZXNzRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRGdW5jdGlvbkV4cHJlc3Npb24obm9kZTogRnVuY3Rpb25FeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdExpdGVyYWxFeHByZXNzaW9uKG5vZGU6IExpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdEZsb2F0TGl0ZXJhbEV4cHJlc3Npb24obm9kZTogRmxvYXRMaXRlcmFsRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRJbnN0YW5jZU9mRXhwcmVzc2lvbihub2RlOiBJbnN0YW5jZU9mRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRJbnRlZ2VyTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogSW50ZWdlckxpdGVyYWxFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdFN0cmluZ0xpdGVyYWwoc3RyOiBzdHJpbmcsIHNpbmdsZVF1b3RlZD86IGJvb2xlYW4pOiB2b2lkIHt9XG4gIHZpc2l0U3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogU3RyaW5nTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0UmVnZXhwTGl0ZXJhbEV4cHJlc3Npb24obm9kZTogUmVnZXhwTGl0ZXJhbEV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0TmV3RXhwcmVzc2lvbihub2RlOiBOZXdFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uKG5vZGU6IFBhcmVudGhlc2l6ZWRFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdFByb3BlcnR5QWNjZXNzRXhwcmVzc2lvbihub2RlOiBQcm9wZXJ0eUFjY2Vzc0V4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VGVybmFyeUV4cHJlc3Npb24obm9kZTogVGVybmFyeUV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VW5hcnlFeHByZXNzaW9uKG5vZGU6IFVuYXJ5RXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRVbmFyeVBvc3RmaXhFeHByZXNzaW9uKG5vZGU6IFVuYXJ5UG9zdGZpeEV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VW5hcnlQcmVmaXhFeHByZXNzaW9uKG5vZGU6IFVuYXJ5UHJlZml4RXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXRTdXBlckV4cHJlc3Npb24obm9kZTogU3VwZXJFeHByZXNzaW9uKTogdm9pZCB7fVxuICB2aXNpdEZhbHNlRXhwcmVzc2lvbihub2RlOiBGYWxzZUV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VHJ1ZUV4cHJlc3Npb24obm9kZTogVHJ1ZUV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0VGhpc0V4cHJlc3Npb24obm9kZTogVGhpc0V4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0TnVsbEV4cGVyc3Npb24obm9kZTogTnVsbEV4cHJlc3Npb24pOiB2b2lkIHt9XG4gIHZpc2l0Q29uc3RydWN0b3JFeHByZXNzaW9uKG5vZGU6IENvbnN0cnVjdG9yRXhwcmVzc2lvbik6IHZvaWQge31cbiAgdmlzaXROb2RlQW5kVGVybWluYXRlKHN0YXRlbWVudDogU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdEJsb2NrU3RhdGVtZW50KG5vZGU6IEJsb2NrU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdEJyZWFrU3RhdGVtZW50KG5vZGU6IEJyZWFrU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdENvbnRpbnVlU3RhdGVtZW50KG5vZGU6IENvbnRpbnVlU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdENsYXNzRGVjbGFyYXRpb24obm9kZTogQ2xhc3NEZWNsYXJhdGlvbiwgaXNEZWZhdWx0PzogYm9vbGVhbik6IHZvaWQge31cbiAgdmlzaXREb1N0YXRlbWVudChub2RlOiBEb1N0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRFbXB0eVN0YXRlbWVudChub2RlOiBFbXB0eVN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRFbnVtRGVjbGFyYXRpb24obm9kZTogRW51bURlY2xhcmF0aW9uLCBpc0RlZmF1bHQ/OiBib29sZWFuKTogdm9pZCB7fVxuICB2aXNpdEVudW1WYWx1ZURlY2xhcmF0aW9uKG5vZGU6IEVudW1WYWx1ZURlY2xhcmF0aW9uKTogdm9pZCB7fVxuICB2aXNpdEV4cG9ydEltcG9ydFN0YXRlbWVudChub2RlOiBFeHBvcnRJbXBvcnRTdGF0ZW1lbnQpOiB2b2lkIHt9XG4gIHZpc2l0RXhwb3J0TWVtYmVyKG5vZGU6IEV4cG9ydE1lbWJlcik6IHZvaWQge31cbiAgdmlzaXRFeHBvcnRTdGF0ZW1lbnQobm9kZTogRXhwb3J0U3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdEV4cG9ydERlZmF1bHRTdGF0ZW1lbnQobm9kZTogRXhwb3J0RGVmYXVsdFN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRFeHByZXNzaW9uU3RhdGVtZW50KG5vZGU6IEV4cHJlc3Npb25TdGF0ZW1lbnQpOiB2b2lkIHt9XG4gIHZpc2l0RmllbGREZWNsYXJhdGlvbihub2RlOiBGaWVsZERlY2xhcmF0aW9uKTogdm9pZCB7fVxuICB2aXNpdEZvclN0YXRlbWVudChub2RlOiBGb3JTdGF0ZW1lbnQpOiB2b2lkIHt9XG4gIHZpc2l0RnVuY3Rpb25EZWNsYXJhdGlvbihcbiAgICBub2RlOiBGdW5jdGlvbkRlY2xhcmF0aW9uLFxuICAgIGlzRGVmYXVsdD86IGJvb2xlYW5cbiAgKTogdm9pZCB7fVxuICB2aXNpdEZ1bmN0aW9uQ29tbW9uKG5vZGU6IEZ1bmN0aW9uRGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0SWZTdGF0ZW1lbnQobm9kZTogSWZTdGF0ZW1lbnQpOiB2b2lkIHt9XG4gIHZpc2l0SW1wb3J0RGVjbGFyYXRpb24obm9kZTogSW1wb3J0RGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0SW1wb3J0U3RhdGVtZW50KG5vZGU6IEltcG9ydFN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRJbmRleFNpZ25hdHVyZURlY2xhcmF0aW9uKG5vZGU6IEluZGV4U2lnbmF0dXJlRGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0SW50ZXJmYWNlRGVjbGFyYXRpb24oXG4gICAgbm9kZTogSW50ZXJmYWNlRGVjbGFyYXRpb24sXG4gICAgaXNEZWZhdWx0PzogYm9vbGVhblxuICApOiB2b2lkIHt9XG4gIHZpc2l0TWV0aG9kRGVjbGFyYXRpb24obm9kZTogTWV0aG9kRGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0TmFtZXNwYWNlRGVjbGFyYXRpb24oXG4gICAgbm9kZTogTmFtZXNwYWNlRGVjbGFyYXRpb24sXG4gICAgaXNEZWZhdWx0PzogYm9vbGVhblxuICApOiB2b2lkIHt9XG4gIHZpc2l0UmV0dXJuU3RhdGVtZW50KG5vZGU6IFJldHVyblN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRTd2l0Y2hDYXNlKG5vZGU6IFN3aXRjaENhc2UpOiB2b2lkIHt9XG4gIHZpc2l0U3dpdGNoU3RhdGVtZW50KG5vZGU6IFN3aXRjaFN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRUaHJvd1N0YXRlbWVudChub2RlOiBUaHJvd1N0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRUcnlTdGF0ZW1lbnQobm9kZTogVHJ5U3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdFR5cGVEZWNsYXJhdGlvbihub2RlOiBUeXBlRGVjbGFyYXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0VmFyaWFibGVEZWNsYXJhdGlvbihub2RlOiBWYXJpYWJsZURlY2xhcmF0aW9uKTogdm9pZCB7fVxuICB2aXNpdFZhcmlhYmxlU3RhdGVtZW50KG5vZGU6IFZhcmlhYmxlU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdFdoaWxlU3RhdGVtZW50KG5vZGU6IFdoaWxlU3RhdGVtZW50KTogdm9pZCB7fVxuICB2aXNpdFZvaWRTdGF0ZW1lbnQobm9kZTogVm9pZFN0YXRlbWVudCk6IHZvaWQge31cbiAgdmlzaXRDb21tZW50KG5vZGU6IENvbW1lbnROb2RlKTogdm9pZCB7fVxuICB2aXNpdERlY29yYXRvck5vZGUobm9kZTogRGVjb3JhdG9yTm9kZSk6IHZvaWQge31cbiAgdmlzaXRQYXJhbWV0ZXIobm9kZTogUGFyYW1ldGVyTm9kZSk6IHZvaWQge31cbn1cbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/src/ast/index.js b/lib/visitor/dist/src/ast/index.js
new file mode 100644
index 0000000000..f73b1281cb
--- /dev/null
+++ b/lib/visitor/dist/src/ast/index.js
@@ -0,0 +1,8 @@
+"use strict";
+function __export(m) {
+    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+Object.defineProperty(exports, "__esModule", { value: true });
+__export(require("./base"));
+__export(require("./empty"));
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXN0L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBS0EsNEJBQXVCO0FBQ3ZCLDZCQUF3QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFTVFZpc2l0b3IgYXMgSVZpc2l0b3IsIE5vZGUgfSBmcm9tIFwiYXNzZW1ibHlzY3JpcHRcIjtcbmltcG9ydCB7IFZpc2l0b3IgfSBmcm9tIFwiLi4vdmlzaXRvclwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFTVFZpc2l0b3IgZXh0ZW5kcyBJVmlzaXRvciwgVmlzaXRvcjxOb2RlPnt9XG5cbmV4cG9ydCAqIGZyb20gXCIuL2Jhc2VcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2VtcHR5XCI7Il19
\ No newline at end of file
diff --git a/lib/visitor/dist/src/element/base.js b/lib/visitor/dist/src/element/base.js
new file mode 100644
index 0000000000..b535d632cc
--- /dev/null
+++ b/lib/visitor/dist/src/element/base.js
@@ -0,0 +1,156 @@
+"use strict";
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var __values = (this && this.__values) || function (o) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+    if (m) return m.call(o);
+    return {
+        next: function () {
+            if (o && i >= o.length) o = void 0;
+            return { value: o && o[i++], done: !o };
+        }
+    };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var assemblyscript_1 = require("assemblyscript");
+var visitor_1 = require("../visitor");
+var assemblyscript_2 = require("assemblyscript");
+var BaseElementVisitor = /** @class */ (function (_super) {
+    __extends(BaseElementVisitor, _super);
+    function BaseElementVisitor() {
+        return _super !== null && _super.apply(this, arguments) || this;
+    }
+    BaseElementVisitor.prototype.visitFile = function (node) {
+        console.log(node.name + "-----");
+        var declares;
+        debugger;
+        declares = node.source.statements.filter(function (s) { return s instanceof assemblyscript_2.DeclarationStatement; });
+        this.visit(declares.map(function (stmt) { return node.program.elementsByDeclaration.get(stmt); }));
+        // this.visit(node.members);
+        // this.visit(node.program.elementsByName);
+        debugger;
+    };
+    BaseElementVisitor.prototype.visitNode = function (node) {
+        this.astVisitor.visit(node);
+    };
+    // visit(element: Element | Element[] | null ): void {
+    //   if (element) {
+    //     if (element instanceof Element) {
+    //       element.visit(this);
+    //     }else {
+    //       element.map(this.visit);
+    //     }
+    //   }
+    // }
+    // visitMemebers(map: Map<any, Element> | null): void {
+    //   if (map) {
+    //     for (let element of map.values()) {
+    //       element.visit(this);
+    //     }
+    //   }
+    // }
+    BaseElementVisitor.prototype.visitInterfaces = function (files) {
+        var e_1, _a, e_2, _b;
+        try {
+            for (var files_1 = __values(files), files_1_1 = files_1.next(); !files_1_1.done; files_1_1 = files_1.next()) {
+                var file = files_1_1.value;
+                if (!file.name.startsWith("~lib"))
+                    if (file.members) {
+                        try {
+                            for (var _c = __values(file.members.values()), _d = _c.next(); !_d.done; _d = _c.next()) {
+                                var element = _d.value;
+                                if (element.kind === assemblyscript_1.ElementKind.INTERFACE
+                                    || element.kind === assemblyscript_1.ElementKind.INTERFACE_PROTOTYPE) {
+                                    element.visit(this);
+                                }
+                            }
+                        }
+                        catch (e_2_1) { e_2 = { error: e_2_1 }; }
+                        finally {
+                            try {
+                                if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
+                            }
+                            finally { if (e_2) throw e_2.error; }
+                        }
+                    }
+            }
+        }
+        catch (e_1_1) { e_1 = { error: e_1_1 }; }
+        finally {
+            try {
+                if (files_1_1 && !files_1_1.done && (_a = files_1.return)) _a.call(files_1);
+            }
+            finally { if (e_1) throw e_1.error; }
+        }
+    };
+    BaseElementVisitor.prototype.visitTypeDefinition = function (node) { };
+    BaseElementVisitor.prototype.visitNamespace = function (node) {
+        this.visit(node.members);
+    };
+    BaseElementVisitor.prototype.visitEnum = function (node) {
+        this.visit(node.members);
+    };
+    BaseElementVisitor.prototype.visitEnumValue = function (node) { };
+    BaseElementVisitor.prototype.visitGlobal = function (node) { };
+    BaseElementVisitor.prototype.visitLocal = function (node) { };
+    BaseElementVisitor.prototype.visitFunctionPrototype = function (node) {
+        if (node.parent instanceof assemblyscript_1.Function) {
+            node.parent.visit(this);
+        }
+        else {
+            this.visit(node.members);
+        }
+    };
+    BaseElementVisitor.prototype.visitFunction = function (node) {
+        this.visit(node.members);
+    };
+    BaseElementVisitor.prototype.visitFunctionTarget = function (node) { };
+    BaseElementVisitor.prototype.visitFieldPrototype = function (node) {
+        if (node.parent instanceof assemblyscript_1.Field) {
+            node.parent.visit(this);
+        }
+    };
+    BaseElementVisitor.prototype.visitField = function (node) { };
+    BaseElementVisitor.prototype.visitPropertyPrototype = function (node) {
+        if (node.parent instanceof assemblyscript_1.Property) {
+            node.parent.visit(this);
+        }
+        else {
+            this.visit(node.getterPrototype);
+            this.visit(node.setterPrototype);
+        }
+    };
+    BaseElementVisitor.prototype.visitProperty = function (node) {
+        this.visit(node.getterInstance);
+        this.visit(node.setterInstance);
+    };
+    BaseElementVisitor.prototype.visitClassPrototype = function (node) {
+        if (node.parent instanceof assemblyscript_1.Class) {
+            node.parent.visit(this);
+        }
+        else {
+            this.visit(node.instanceMembers);
+        }
+    };
+    BaseElementVisitor.prototype.visitClass = function (node) {
+        this.visit(node.members);
+    };
+    BaseElementVisitor.prototype.visitInterfacePrototype = function (node) { };
+    BaseElementVisitor.prototype.visitInterface = function (node) {
+        this.visit(node.prototype.instanceMembers);
+    };
+    return BaseElementVisitor;
+}(visitor_1.AbstractVisitor));
+exports.BaseElementVisitor = BaseElementVisitor;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lbGVtZW50L2Jhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlEQXdCd0I7QUFFeEIsc0NBQWtFO0FBRWxFLGlEQUFzRDtBQUt0RDtJQUF3QyxzQ0FBd0I7SUFBaEU7O0lBMEdBLENBQUM7SUF0R0Msc0NBQVMsR0FBVCxVQUFVLElBQVU7UUFDbEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFBO1FBQ2hDLElBQUksUUFBZ0MsQ0FBQztRQUNyQyxRQUFRLENBQUM7UUFDVCxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFVBQUEsQ0FBQyxJQUFJLE9BQUEsQ0FBQyxZQUFZLHFDQUFvQixFQUFqQyxDQUFpQyxDQUEyQixDQUFDO1FBQzNHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxVQUFBLElBQUksSUFBSSxPQUFBLElBQUksQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUE1QyxDQUE0QyxDQUFzQixDQUFDLENBQUM7UUFDcEcsNEJBQTRCO1FBQzVCLDJDQUEyQztRQUMzQyxRQUFRLENBQUM7SUFDWCxDQUFDO0lBSUQsc0NBQVMsR0FBVCxVQUFVLElBQXNCO1FBQzlCLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRCxzREFBc0Q7SUFDdEQsbUJBQW1CO0lBQ25CLHdDQUF3QztJQUN4Qyw2QkFBNkI7SUFDN0IsY0FBYztJQUNkLGlDQUFpQztJQUNqQyxRQUFRO0lBQ1IsTUFBTTtJQUNOLElBQUk7SUFFSix1REFBdUQ7SUFDdkQsZUFBZTtJQUNmLDBDQUEwQztJQUMxQyw2QkFBNkI7SUFDN0Is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aEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDekI7YUFBTTtZQUNMLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1NBQ2xDO0lBQ0gsQ0FBQztJQUNELHVDQUFVLEdBQVYsVUFBVyxJQUFXO1FBQ3BCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFDRCxvREFBdUIsR0FBdkIsVUFBd0IsSUFBd0IsSUFBUyxDQUFDO0lBQzFELDJDQUFjLEdBQWQsVUFBZSxJQUFlO1FBQzVCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBQ0gseUJBQUM7QUFBRCxDQUFDLEFBMUdELENBQXdDLHlCQUFlLEdBMEd0RDtBQTFHWSxnREFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBFbGVtZW50VmlzaXRvciBhcyBJVmlzaXRvcixcbiAgRmlsZSxcbiAgVHlwZURlZmluaXRpb24sXG4gIE5hbWVzcGFjZSxcbiAgRW51bSxcbiAgRW51bVZhbHVlLFxuICBHbG9iYWwsXG4gIExvY2FsLFxuICBGdW5jdGlvblByb3RvdHlwZSxcbiAgRnVuY3Rpb24sXG4gIEZ1bmN0aW9uVGFyZ2V0LFxuICBGaWVsZFByb3RvdHlwZSxcbiAgRmllbGQsXG4gIFByb3BlcnR5UHJvdG90eXBlLFxuICBQcm9wZXJ0eSxcbiAgQ2xhc3NQcm90b3R5cGUsXG4gIENsYXNzLFxuICBJbnRlcmZhY2VQcm90b3R5cGUsXG4gIEludGVyZmFjZSxcbiAgRWxlbWVudCxcbiAgTm9kZSxcbiAgTm9kZUtpbmQsXG4gIEVsZW1lbnRLaW5kXG59IGZyb20gXCJhc3NlbWJseXNjcmlwdFwiO1xuXG5pbXBvcnQgeyBWaXNpdG9yLCBBYnN0cmFjdFZpc2l0b3IsIENvbGxlY3Rpb24gfSBmcm9tIFwiLi4vdmlzaXRvclwiO1xuaW1wb3J0IHsgQVNUVmlzaXRvciB9IGZyb20gXCIuLi9hc3QvaW5kZXhcIjtcbmltcG9ydCB7IERlY2xhcmF0aW9uU3RhdGVtZW50IH0gZnJvbSAnYXNzZW1ibHlzY3JpcHQnO1xuaW1wb3J0IHsgRGVjbGFyZWRFbGVtZW50IH0gZnJvbSAnYXNzZW1ibHlzY3JpcHQnO1xuXG5pbnRlcmZhY2UgRWxlbWVudFZpc2l0b3IgZXh0ZW5kcyBWaXNpdG9yPEVsZW1lbnQ+LCBJVmlzaXRvciB7fVxuXG5leHBvcnQgY2xhc3MgQmFzZUVsZW1lbnRWaXNpdG9yIGV4dGVuZHMgQWJzdHJhY3RWaXNpdG9yPEVsZW1lbnQ+XG4gIGltcGxlbWVudHMgRWxlbWVudFZpc2l0b3Ige1xuICBhc3RWaXNpdG9yOiBBU1RWaXNpdG9yO1xuICBcbiAgdmlzaXRGaWxlKG5vZGU6IEZpbGUpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZyhub2RlLm5hbWUgKyBcIi0tLS0tXCIpXG4gICAgbGV0IGRlY2xhcmVzOiBEZWNsYXJhdGlvblN0YXRlbWVudFtdO1xuICAgIGRlYnVnZ2VyO1xuICAgIGRlY2xhcmVzID0gbm9kZS5zb3VyY2Uuc3RhdGVtZW50cy5maWx0ZXIocyA9PiBzIGluc3RhbmNlb2YgRGVjbGFyYXRpb25TdGF0ZW1lbnQpIGFzIERlY2xhcmF0aW9uU3RhdGVtZW50W107XG4gICAgdGhpcy52aXNpdChkZWNsYXJlcy5tYXAoc3RtdCA9PiBub2RlLnByb2dyYW0uZWxlbWVudHNCeURlY2xhcmF0aW9uLmdldChzdG10KSkgYXMgRGVjbGFyZWRFbGVtZW50W10pO1xuICAgIC8vIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgICAvLyB0aGlzLnZpc2l0KG5vZGUucHJvZ3JhbS5lbGVtZW50c0J5TmFtZSk7XG4gICAgZGVidWdnZXI7XG4gIH1cblxuXG5cbiAgdmlzaXROb2RlKG5vZGU6IENvbGxlY3Rpb248Tm9kZT4pOiB2b2lkIHtcbiAgICB0aGlzLmFzdFZpc2l0b3IudmlzaXQobm9kZSk7XG4gIH1cblxuICAvLyB2aXNpdChlbGVtZW50OiBFbGVtZW50IHwgRWxlbWVudFtdIHwgbnVsbCApOiB2b2lkIHtcbiAgLy8gICBpZiAoZWxlbWVudCkge1xuICAvLyAgICAgaWYgKGVsZW1lbnQgaW5zdGFuY2VvZiBFbGVtZW50KSB7XG4gIC8vICAgICAgIGVsZW1lbnQudmlzaXQodGhpcyk7XG4gIC8vICAgICB9ZWxzZSB7XG4gIC8vICAgICAgIGVsZW1lbnQubWFwKHRoaXMudmlzaXQpO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuXG4gIC8vIHZpc2l0TWVtZWJlcnMobWFwOiBNYXA8YW55LCBFbGVtZW50PiB8IG51bGwpOiB2b2lkIHtcbiAgLy8gICBpZiAobWFwKSB7XG4gIC8vICAgICBmb3IgKGxldCBlbGVtZW50IG9mIG1hcC52YWx1ZXMoKSkge1xuICAvLyAgICAgICBlbGVtZW50LnZpc2l0KHRoaXMpO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuXG4gIHZpc2l0SW50ZXJmYWNlcyhmaWxlczogSXRlcmFibGU8RmlsZT4pOiB2b2lkIHtcbiAgICBmb3IgKGxldCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgICBpZiAoIWZpbGUubmFtZS5zdGFydHNXaXRoKFwifmxpYlwiKSlcbiAgICAgIGlmIChmaWxlLm1lbWJlcnMpIHtcbiAgICAgICAgZm9yIChsZXQgZWxlbWVudCBvZiBmaWxlLm1lbWJlcnMudmFsdWVzKCkpIHtcbiAgICAgICAgICBpZiAoZWxlbWVudC5raW5kID09PSBFbGVtZW50S2luZC5JTlRFUkZBQ0UgXG4gICAgICAgICAgICB8fCBlbGVtZW50LmtpbmQgPT09IEVsZW1lbnRLaW5kLklOVEVSRkFDRV9QUk9UT1RZUEUgKSB7XG4gICAgICAgICAgICBlbGVtZW50LnZpc2l0KHRoaXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHZpc2l0VHlwZURlZmluaXRpb24obm9kZTogVHlwZURlZmluaXRpb24pOiB2b2lkIHt9XG4gIHZpc2l0TmFtZXNwYWNlKG5vZGU6IE5hbWVzcGFjZSk6IHZvaWQge1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgfVxuICB2aXNpdEVudW0obm9kZTogRW51bSk6IHZvaWQge1xuICAgIHRoaXMudmlzaXQobm9kZS5tZW1iZXJzKTtcbiAgfVxuICB2aXNpdEVudW1WYWx1ZShub2RlOiBFbnVtVmFsdWUpOiB2b2lkIHt9XG4gIHZpc2l0R2xvYmFsKG5vZGU6IEdsb2JhbCk6IHZvaWQge31cbiAgdmlzaXRMb2NhbChub2RlOiBMb2NhbCk6IHZvaWQge31cbiAgdmlzaXRGdW5jdGlvblByb3RvdHlwZShub2RlOiBGdW5jdGlvblByb3RvdHlwZSk6IHZvaWQge1xuICAgIGlmIChub2RlLnBhcmVudCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBub2RlLnBhcmVudC52aXNpdCh0aGlzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52aXNpdChub2RlLm1lbWJlcnMpO1xuICAgIH1cbiAgfVxuICB2aXNpdEZ1bmN0aW9uKG5vZGU6IEZ1bmN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy52aXNpdChub2RlLm1lbWJlcnMpO1xuICB9XG4gIHZpc2l0RnVuY3Rpb25UYXJnZXQobm9kZTogRnVuY3Rpb25UYXJnZXQpOiB2b2lkIHt9XG4gIHZpc2l0RmllbGRQcm90b3R5cGUobm9kZTogRmllbGRQcm90b3R5cGUpOiB2b2lkIHtcbiAgICBpZiAobm9kZS5wYXJlbnQgaW5zdGFuY2VvZiBGaWVsZCkge1xuICAgICAgbm9kZS5wYXJlbnQudmlzaXQodGhpcyk7XG4gICAgfVxuICB9XG4gIHZpc2l0RmllbGQobm9kZTogRmllbGQpOiB2b2lkIHt9XG4gIHZpc2l0UHJvcGVydHlQcm90b3R5cGUobm9kZTogUHJvcGVydHlQcm90b3R5cGUpOiB2b2lkIHtcbiAgICBpZiAobm9kZS5wYXJlbnQgaW5zdGFuY2VvZiBQcm9wZXJ0eSkge1xuICAgICAgbm9kZS5wYXJlbnQudmlzaXQodGhpcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudmlzaXQobm9kZS5nZXR0ZXJQcm90b3R5cGUpO1xuICAgICAgdGhpcy52aXNpdChub2RlLnNldHRlclByb3RvdHlwZSk7XG4gICAgfVxuICB9XG4gIHZpc2l0UHJvcGVydHkobm9kZTogUHJvcGVydHkpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KG5vZGUuZ2V0dGVySW5zdGFuY2UpO1xuICAgIHRoaXMudmlzaXQobm9kZS5zZXR0ZXJJbnN0YW5jZSk7XG4gIH1cbiAgdmlzaXRDbGFzc1Byb3RvdHlwZShub2RlOiBDbGFzc1Byb3RvdHlwZSk6IHZvaWQge1xuICAgIGlmIChub2RlLnBhcmVudCBpbnN0YW5jZW9mIENsYXNzKSB7XG4gICAgICBub2RlLnBhcmVudC52aXNpdCh0aGlzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy52aXNpdChub2RlLmluc3RhbmNlTWVtYmVycyk7XG4gICAgfVxuICB9XG4gIHZpc2l0Q2xhc3Mobm9kZTogQ2xhc3MpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KG5vZGUubWVtYmVycyk7XG4gIH1cbiAgdmlzaXRJbnRlcmZhY2VQcm90b3R5cGUobm9kZTogSW50ZXJmYWNlUHJvdG90eXBlKTogdm9pZCB7fVxuICB2aXNpdEludGVyZmFjZShub2RlOiBJbnRlcmZhY2UpOiB2b2lkIHtcbiAgICB0aGlzLnZpc2l0KG5vZGUucHJvdG90eXBlLmluc3RhbmNlTWVtYmVycyk7XG4gIH1cbn1cbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/src/element/index.js b/lib/visitor/dist/src/element/index.js
new file mode 100644
index 0000000000..59fbe36d1f
--- /dev/null
+++ b/lib/visitor/dist/src/element/index.js
@@ -0,0 +1,7 @@
+"use strict";
+function __export(m) {
+    for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
+}
+Object.defineProperty(exports, "__esModule", { value: true });
+__export(require("./base"));
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZWxlbWVudC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDRCQUF1QiIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gXCIuL2Jhc2VcIjtcbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/src/visitor.js b/lib/visitor/dist/src/visitor.js
new file mode 100644
index 0000000000..2d01530f9b
--- /dev/null
+++ b/lib/visitor/dist/src/visitor.js
@@ -0,0 +1,82 @@
+"use strict";
+var __values = (this && this.__values) || function (o) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+    if (m) return m.call(o);
+    return {
+        next: function () {
+            if (o && i >= o.length) o = void 0;
+            return { value: o && o[i++], done: !o };
+        }
+    };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+var AbstractVisitor = /** @class */ (function () {
+    function AbstractVisitor() {
+    }
+    AbstractVisitor.prototype.visit = function (node) {
+        var _this = this;
+        var e_1, _a;
+        if (node) {
+            if (node instanceof Array) {
+                node.map(function (node) { return _this.visit(node); });
+            }
+            else if (node instanceof Map) {
+                this.visit(node.values());
+            }
+            else if (node.next) {
+                try {
+                    //TODO: Find better way to test if iterable
+                    for (var node_1 = __values(node), node_1_1 = node_1.next(); !node_1_1.done; node_1_1 = node_1.next()) {
+                        var n = node_1_1.value;
+                        this.visit(n);
+                    }
+                }
+                catch (e_1_1) { e_1 = { error: e_1_1 }; }
+                finally {
+                    try {
+                        if (node_1_1 && !node_1_1.done && (_a = node_1.return)) _a.call(node_1);
+                    }
+                    finally { if (e_1) throw e_1.error; }
+                }
+            }
+            else {
+                node.visit(this);
+            }
+        }
+    };
+    return AbstractVisitor;
+}());
+exports.AbstractVisitor = AbstractVisitor;
+// interface NodeVisitor extends Visit<testNode> {
+//     visitNode(t: testNode):void
+// }
+// class testNode implements Visit<testNode> {
+//   constructor(private name: string) {}
+//   visit(visitor: NodeVisitor): void {
+//     // console.log("in" + this.name);
+//     debugger;
+//     visitor.visitNode(this)
+//   }
+// }
+// class Base extends AbstractVisitor<testNode> implements NodeVisitor {
+//     visitNode(t: testNode): void {
+//         console.log("in super")
+//     }
+// }
+// class Sub extends Base implements NodeVisitor {
+//     visitNode(t: testNode): void {
+//         console.log("in child");
+//         super.visitNode(t);
+//     }
+// }
+// let test = new Sub();
+// let node = new testNode("one");
+// let node2 = new testNode("two");
+// let node3 = new testNode("three");
+// let map = new Map([["one", node], ["two", node2], ["three", node3]]);
+// let values = map.values();
+// debugger;
+// test.visit([node, node2, node3]);
+// test.visit(map);
+// test.visit(values);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzaXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92aXNpdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQVNBO0lBQUE7SUFpQkEsQ0FBQztJQWhCQywrQkFBSyxHQUFMLFVBQU0sSUFBbUI7UUFBekIsaUJBZUM7O1FBZEMsSUFBSSxJQUFJLEVBQUU7WUFDUixJQUFJLElBQUksWUFBWSxLQUFLLEVBQUU7Z0JBQ3pCLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBQSxJQUFJLElBQUksT0FBQSxLQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFoQixDQUFnQixDQUFDLENBQUM7YUFDcEM7aUJBQU0sSUFBSSxJQUFJLFlBQVksR0FBRyxFQUFFO2dCQUM5QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO2FBQzNCO2lCQUFNLElBQVUsSUFBSyxDQUFDLElBQUksRUFBRTs7b0JBQ3pCLDJDQUEyQztvQkFDN0MsS0FBYyxJQUFBLFNBQUEsU0FBQSxJQUFJLENBQUEsMEJBQUEsNENBQUU7d0JBQWYsSUFBSSxDQUFDLGlCQUFBO3dCQUNOLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7cUJBQ2Y7Ozs7Ozs7OzthQUNKO2lCQUFLO2dCQUNBLElBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDdkI7U0FDRjtJQUNILENBQUM7SUFDSCxzQkFBQztBQUFELENBQUMsQUFqQkQsSUFpQkM7QUFqQlksMENBQWU7QUFtQjVCLGtEQUFrRDtBQUNsRCxrQ0FBa0M7QUFDbEMsSUFBSTtBQUVKLDhDQUE4QztBQUM5Qyx5Q0FBeUM7QUFFekMsd0NBQXdDO0FBQ3hDLHdDQUF3QztBQUN4QyxnQkFBZ0I7QUFDaEIsOEJBQThCO0FBQzlCLE1BQU07QUFDTixJQUFJO0FBR0osd0VBQXdFO0FBQ3hFLHFDQUFxQztBQUNyQyxrQ0FBa0M7QUFDbEMsUUFBUTtBQUNSLElBQUk7QUFFSixrREFBa0Q7QUFDbEQscUNBQXFDO0FBQ3JDLG1DQUFtQztBQUNuQyw4QkFBOEI7QUFDOUIsUUFBUTtBQUNSLElBQUk7QUFHSix3QkFBd0I7QUFDeEIsa0NBQWtDO0FBQ2xDLG1DQUFtQztBQUNuQyxxQ0FBcUM7QUFFckMsd0VBQXdFO0FBQ3hFLDZCQUE2QjtBQUM3QixZQUFZO0FBQ1osb0NBQW9DO0FBQ3BDLG1CQUFtQjtBQUNuQixzQkFBc0IiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgaW50ZXJmYWNlIFZpc2l0b3I8VD4ge1xuICB2aXNpdCh0OiBDb2xsZWN0aW9uPFQ+KTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIFZpc2l0PFQ+IHtcbiAgICB2aXNpdCh2aXNpdG9yOiBhbnkpOiB2b2lkO1xufVxuZXhwb3J0IHR5cGUgQ29sbGVjdGlvbjxUPiA9IFQgfCBUW10gfCBNYXA8c3RyaW5nLCBUPiB8IEl0ZXJhYmxlPFQ+IHwgbnVsbDtcblxuZXhwb3J0IGNsYXNzIEFic3RyYWN0VmlzaXRvcjxUIGV4dGVuZHMgVmlzaXQ8VD4+IHtcbiAgdmlzaXQobm9kZTogQ29sbGVjdGlvbjxUPik6IHZvaWQge1xuICAgIGlmIChub2RlKSB7XG4gICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgIG5vZGUubWFwKG5vZGUgPT4gdGhpcy52aXNpdChub2RlKSk7XG4gICAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgdGhpcy52aXNpdChub2RlLnZhbHVlcygpKTtcbiAgICAgIH0gZWxzZSBpZiAoKDxhbnk+bm9kZSkubmV4dCkgeyBcbiAgICAgICAgICAvL1RPRE86IEZpbmQgYmV0dGVyIHdheSB0byB0ZXN0IGlmIGl0ZXJhYmxlXG4gICAgICAgIGZvciAobGV0IG4gb2Ygbm9kZSkge1xuICAgICAgICAgICAgdGhpcy52aXNpdChuKTtcbiAgICAgICAgICB9XG4gICAgICB9ZWxzZSB7XG4gICAgICAgICg8VD5ub2RlKS52aXNpdCh0aGlzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLy8gaW50ZXJmYWNlIE5vZGVWaXNpdG9yIGV4dGVuZHMgVmlzaXQ8dGVzdE5vZGU+IHtcbi8vICAgICB2aXNpdE5vZGUodDogdGVzdE5vZGUpOnZvaWRcbi8vIH1cblxuLy8gY2xhc3MgdGVzdE5vZGUgaW1wbGVtZW50cyBWaXNpdDx0ZXN0Tm9kZT4ge1xuLy8gICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5hbWU6IHN0cmluZykge31cblxuLy8gICB2aXNpdCh2aXNpdG9yOiBOb2RlVmlzaXRvcik6IHZvaWQge1xuLy8gICAgIC8vIGNvbnNvbGUubG9nKFwiaW5cIiArIHRoaXMubmFtZSk7XG4vLyAgICAgZGVidWdnZXI7XG4vLyAgICAgdmlzaXRvci52aXNpdE5vZGUodGhpcylcbi8vICAgfVxuLy8gfVxuXG5cbi8vIGNsYXNzIEJhc2UgZXh0ZW5kcyBBYnN0cmFjdFZpc2l0b3I8dGVzdE5vZGU+IGltcGxlbWVudHMgTm9kZVZpc2l0b3Ige1xuLy8gICAgIHZpc2l0Tm9kZSh0OiB0ZXN0Tm9kZSk6IHZvaWQge1xuLy8gICAgICAgICBjb25zb2xlLmxvZyhcImluIHN1cGVyXCIpXG4vLyAgICAgfVxuLy8gfVxuXG4vLyBjbGFzcyBTdWIgZXh0ZW5kcyBCYXNlIGltcGxlbWVudHMgTm9kZVZpc2l0b3Ige1xuLy8gICAgIHZpc2l0Tm9kZSh0OiB0ZXN0Tm9kZSk6IHZvaWQge1xuLy8gICAgICAgICBjb25zb2xlLmxvZyhcImluIGNoaWxkXCIpO1xuLy8gICAgICAgICBzdXBlci52aXNpdE5vZGUodCk7XG4vLyAgICAgfVxuLy8gfVxuXG5cbi8vIGxldCB0ZXN0ID0gbmV3IFN1YigpO1xuLy8gbGV0IG5vZGUgPSBuZXcgdGVzdE5vZGUoXCJvbmVcIik7XG4vLyBsZXQgbm9kZTIgPSBuZXcgdGVzdE5vZGUoXCJ0d29cIik7XG4vLyBsZXQgbm9kZTMgPSBuZXcgdGVzdE5vZGUoXCJ0aHJlZVwiKTtcblxuLy8gbGV0IG1hcCA9IG5ldyBNYXAoW1tcIm9uZVwiLCBub2RlXSwgW1widHdvXCIsIG5vZGUyXSwgW1widGhyZWVcIiwgbm9kZTNdXSk7XG4vLyBsZXQgdmFsdWVzID0gbWFwLnZhbHVlcygpO1xuLy8gZGVidWdnZXI7XG4vLyB0ZXN0LnZpc2l0KFtub2RlLCBub2RlMiwgbm9kZTNdKTtcbi8vIHRlc3QudmlzaXQobWFwKTtcbi8vIHRlc3QudmlzaXQodmFsdWVzKTtcbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/dist/visitor.js b/lib/visitor/dist/visitor.js
new file mode 100644
index 0000000000..c399990654
--- /dev/null
+++ b/lib/visitor/dist/visitor.js
@@ -0,0 +1,91 @@
+"use strict";
+var __values = (this && this.__values) || function (o) {
+    var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
+    if (m) return m.call(o);
+    return {
+        next: function () {
+            if (o && i >= o.length) o = void 0;
+            return { value: o && o[i++], done: !o };
+        }
+    };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+function id(t) {
+    return t;
+}
+var isIterable = function (object) {
+    //@ts-ignore
+    return object != null && typeof object[Symbol.iterator] === "function";
+};
+var AbstractVisitor = /** @class */ (function () {
+    function AbstractVisitor(func) {
+        if (func === void 0) { func = id; }
+        this.func = func;
+    }
+    AbstractVisitor.prototype.visit = function (node) {
+        var _this = this;
+        var e_1, _a;
+        if (node) {
+            if (node instanceof Array) {
+                node.map(function (node) { return _this.visit(node); });
+            }
+            else if (node instanceof Map) {
+                this.visit(node.values());
+            }
+            else if (isIterable(node)) {
+                try {
+                    //TODO: Find better way to test if iterable
+                    for (var node_1 = __values(node), node_1_1 = node_1.next(); !node_1_1.done; node_1_1 = node_1.next()) {
+                        var n = node_1_1.value;
+                        this.visit(n);
+                    }
+                }
+                catch (e_1_1) { e_1 = { error: e_1_1 }; }
+                finally {
+                    try {
+                        if (node_1_1 && !node_1_1.done && (_a = node_1.return)) _a.call(node_1);
+                    }
+                    finally { if (e_1) throw e_1.error; }
+                }
+            }
+            else {
+                node.visit(this);
+            }
+        }
+    };
+    return AbstractVisitor;
+}());
+exports.AbstractVisitor = AbstractVisitor;
+// interface NodeVisitor extends Visit<testNode> {
+//     visitNode(t: testNode):void
+// }
+// class testNode implements Visit<testNode> {
+//   constructor(private name: string) {}
+//   visit(visitor: NodeVisitor): void {
+//     // console.log("in" + this.name);
+//     debugger;
+//     visitor.visitNode(this)
+//   }
+// }
+// class Base extends AbstractVisitor<testNode> implements NodeVisitor {
+//     visitNode(t: testNode): void {
+//         console.log("in super")
+//     }
+// }
+// class Sub extends Base implements NodeVisitor {
+//     visitNode(t: testNode): void {
+//         console.log("in child");
+//         super.visitNode(t);
+//     }
+// }
+// let test = new Sub();
+// let node = new testNode("one");
+// let node2 = new testNode("two");
+// let node3 = new testNode("three");
+// let map = new Map([["one", node], ["two", node2], ["three", node3]]);
+// let values = map.values();
+// debugger;
+// test.visit([node, node2, node3]);
+// test.visit(map);
+// test.visit(values);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzaXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy92aXNpdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQVVBLFNBQVMsRUFBRSxDQUFJLENBQUk7SUFDakIsT0FBTyxDQUFDLENBQUM7QUFDWCxDQUFDO0FBSUQsSUFBTSxVQUFVLEdBQUcsVUFBQyxNQUFjO0lBQ2hDLFlBQVk7SUFDWixPQUFBLE1BQU0sSUFBSSxJQUFJLElBQUksT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLFVBQVU7QUFBL0QsQ0FBK0QsQ0FBQztBQUVsRTtJQUVFLHlCQUFvQixJQUFxQjtRQUFyQixxQkFBQSxFQUFBLFNBQXFCO1FBQXJCLFNBQUksR0FBSixJQUFJLENBQWlCO0lBQUcsQ0FBQztJQUU3QywrQkFBSyxHQUFMLFVBQU0sSUFBbUI7UUFBekIsaUJBZUM7O1FBZEMsSUFBSSxJQUFJLEVBQUU7WUFDUixJQUFJLElBQUksWUFBWSxLQUFLLEVBQUU7Z0JBQ3pCLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBQSxJQUFJLElBQUksT0FBQSxLQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFoQixDQUFnQixDQUFDLENBQUM7YUFDcEM7aUJBQU0sSUFBSSxJQUFJLFlBQVksR0FBRyxFQUFFO2dCQUM5QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO2FBQzNCO2lCQUFNLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFOztvQkFDekIsMkNBQTJDO29CQUM3QyxLQUFjLElBQUEsU0FBQSxTQUFBLElBQUksQ0FBQSwwQkFBQSw0Q0FBRTt3QkFBZixJQUFJLENBQUMsaUJBQUE7d0JBQ04sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztxQkFDZjs7Ozs7Ozs7O2FBQ0o7aUJBQUs7Z0JBQ0EsSUFBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUN2QjtTQUNGO0lBQ0gsQ0FBQztJQUlILHNCQUFDO0FBQUQsQ0FBQyxBQXZCRCxJQXVCQztBQXZCcUIsMENBQWU7QUF5QnJDLGtEQUFrRDtBQUNsRCxrQ0FBa0M7QUFDbEMsSUFBSTtBQUVKLDhDQUE4QztBQUM5Qyx5Q0FBeUM7QUFFekMsd0NBQXdDO0FBQ3hDLHdDQUF3QztBQUN4QyxnQkFBZ0I7QUFDaEIsOEJBQThCO0FBQzlCLE1BQU07QUFDTixJQUFJO0FBR0osd0VBQXdFO0FBQ3hFLHFDQUFxQztBQUNyQyxrQ0FBa0M7QUFDbEMsUUFBUTtBQUNSLElBQUk7QUFFSixrREFBa0Q7QUFDbEQscUNBQXFDO0FBQ3JDLG1DQUFtQztBQUNuQyw4QkFBOEI7QUFDOUIsUUFBUTtBQUNSLElBQUk7QUFHSix3QkFBd0I7QUFDeEIsa0NBQWtDO0FBQ2xDLG1DQUFtQztBQUNuQyxxQ0FBcUM7QUFFckMsd0VBQXdFO0FBQ3hFLDZCQUE2QjtBQUM3QixZQUFZO0FBQ1osb0NBQW9DO0FBQ3BDLG1CQUFtQjtBQUNuQixzQkFBc0IiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgaW50ZXJmYWNlIFZpc2l0b3I8VD4ge1xuICB2aXNpdCh0OiBDb2xsZWN0aW9uPFQ+KTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIFZpc2l0PFQ+IHtcbiAgICB2aXNpdCh2aXNpdG9yOiBhbnkpOiB2b2lkO1xufVxuXG50eXBlIEZ1bmN0b3I8VD4gPSAobm9kZTogVCkgPT4gVDtcblxuZnVuY3Rpb24gaWQ8VD4odDogVCk6IFR7XG4gIHJldHVybiB0O1xufVxuXG5leHBvcnQgdHlwZSBDb2xsZWN0aW9uPFQ+ID0gVCB8IFRbXSB8IE1hcDxzdHJpbmcsIFQ+IHwgSXRlcmFibGU8VD4gfCBudWxsO1xuXG5jb25zdCBpc0l0ZXJhYmxlID0gKG9iamVjdDogb2JqZWN0KTogYm9vbGVhbiA9PlxuICAvL0B0cy1pZ25vcmVcbiAgb2JqZWN0ICE9IG51bGwgJiYgdHlwZW9mIG9iamVjdFtTeW1ib2wuaXRlcmF0b3JdID09PSBcImZ1bmN0aW9uXCI7XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBBYnN0cmFjdFZpc2l0b3I8VCBleHRlbmRzIFZpc2l0PFQ+PiB7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBmdW5jOiBGdW5jdG9yPFQ+ID0gaWQpIHt9XG5cbiAgdmlzaXQobm9kZTogQ29sbGVjdGlvbjxUPik6IHZvaWQge1xuICAgIGlmIChub2RlKSB7XG4gICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICAgIG5vZGUubWFwKG5vZGUgPT4gdGhpcy52aXNpdChub2RlKSk7XG4gICAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgdGhpcy52aXNpdChub2RlLnZhbHVlcygpKTtcbiAgICAgIH0gZWxzZSBpZiAoaXNJdGVyYWJsZShub2RlKSkge1xuICAgICAgICAgIC8vVE9ETzogRmluZCBiZXR0ZXIgd2F5IHRvIHRlc3QgaWYgaXRlcmFibGVcbiAgICAgICAgZm9yIChsZXQgbiBvZiBub2RlKSB7XG4gICAgICAgICAgICB0aGlzLnZpc2l0KG4pO1xuICAgICAgICAgIH1cbiAgICAgIH1lbHNlIHtcbiAgICAgICAgKDxUPm5vZGUpLnZpc2l0KHRoaXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGFic3RyYWN0IHN0YXJ0KCk6IHZvaWQ7XG5cbn1cblxuLy8gaW50ZXJmYWNlIE5vZGVWaXNpdG9yIGV4dGVuZHMgVmlzaXQ8dGVzdE5vZGU+IHtcbi8vICAgICB2aXNpdE5vZGUodDogdGVzdE5vZGUpOnZvaWRcbi8vIH1cblxuLy8gY2xhc3MgdGVzdE5vZGUgaW1wbGVtZW50cyBWaXNpdDx0ZXN0Tm9kZT4ge1xuLy8gICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5hbWU6IHN0cmluZykge31cblxuLy8gICB2aXNpdCh2aXNpdG9yOiBOb2RlVmlzaXRvcik6IHZvaWQge1xuLy8gICAgIC8vIGNvbnNvbGUubG9nKFwiaW5cIiArIHRoaXMubmFtZSk7XG4vLyAgICAgZGVidWdnZXI7XG4vLyAgICAgdmlzaXRvci52aXNpdE5vZGUodGhpcylcbi8vICAgfVxuLy8gfVxuXG5cbi8vIGNsYXNzIEJhc2UgZXh0ZW5kcyBBYnN0cmFjdFZpc2l0b3I8dGVzdE5vZGU+IGltcGxlbWVudHMgTm9kZVZpc2l0b3Ige1xuLy8gICAgIHZpc2l0Tm9kZSh0OiB0ZXN0Tm9kZSk6IHZvaWQge1xuLy8gICAgICAgICBjb25zb2xlLmxvZyhcImluIHN1cGVyXCIpXG4vLyAgICAgfVxuLy8gfVxuXG4vLyBjbGFzcyBTdWIgZXh0ZW5kcyBCYXNlIGltcGxlbWVudHMgTm9kZVZpc2l0b3Ige1xuLy8gICAgIHZpc2l0Tm9kZSh0OiB0ZXN0Tm9kZSk6IHZvaWQge1xuLy8gICAgICAgICBjb25zb2xlLmxvZyhcImluIGNoaWxkXCIpO1xuLy8gICAgICAgICBzdXBlci52aXNpdE5vZGUodCk7XG4vLyAgICAgfVxuLy8gfVxuXG5cbi8vIGxldCB0ZXN0ID0gbmV3IFN1YigpO1xuLy8gbGV0IG5vZGUgPSBuZXcgdGVzdE5vZGUoXCJvbmVcIik7XG4vLyBsZXQgbm9kZTIgPSBuZXcgdGVzdE5vZGUoXCJ0d29cIik7XG4vLyBsZXQgbm9kZTMgPSBuZXcgdGVzdE5vZGUoXCJ0aHJlZVwiKTtcblxuLy8gbGV0IG1hcCA9IG5ldyBNYXAoW1tcIm9uZVwiLCBub2RlXSwgW1widHdvXCIsIG5vZGUyXSwgW1widGhyZWVcIiwgbm9kZTNdXSk7XG4vLyBsZXQgdmFsdWVzID0gbWFwLnZhbHVlcygpO1xuLy8gZGVidWdnZXI7XG4vLyB0ZXN0LnZpc2l0KFtub2RlLCBub2RlMiwgbm9kZTNdKTtcbi8vIHRlc3QudmlzaXQobWFwKTtcbi8vIHRlc3QudmlzaXQodmFsdWVzKTtcbiJdfQ==
\ No newline at end of file
diff --git a/lib/visitor/package-lock.json b/lib/visitor/package-lock.json
new file mode 100644
index 0000000000..673dbb4f10
--- /dev/null
+++ b/lib/visitor/package-lock.json
@@ -0,0 +1,192 @@
+{
+    "name": "visitor",
+    "version": "1.0.0",
+    "lockfileVersion": 1,
+    "requires": true,
+    "dependencies": {
+        "@as-pect/assembly": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/@as-pect/assembly/-/assembly-2.3.1.tgz",
+            "integrity": "sha512-KYBhyTEnaVcJjN/1EpzLhpbUHKT3pJjCPxm+Mdc7obnZ9EdVz6vN/lw+BQjeL4cUi1YLsnvgl8ftXcup5jVbQA=="
+        },
+        "@as-pect/cli": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/@as-pect/cli/-/cli-2.3.1.tgz",
+            "integrity": "sha512-ipcxrXnK9Xj1Foy92nSRsganapB+yxFe4HJ/RuwnjRQ9s8bqu0UwH12XbiHktcK7bJMs1H77/sqbQVxqoYHQcA==",
+            "requires": {
+                "@as-pect/assembly": "^2.3.1",
+                "@as-pect/core": "^2.3.1",
+                "chalk": "^2.4.2",
+                "glob": "^7.1.4"
+            }
+        },
+        "@as-pect/core": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/@as-pect/core/-/core-2.3.1.tgz",
+            "integrity": "sha512-iwd4MkGuO1wZqo9/sPlT567XYK0PkMLzBvwfkXOM2zq1wwuc5GZQrKoofgYorA40KI0edJW39djtOmPwIhx2vA==",
+            "requires": {
+                "@as-pect/assembly": "^2.3.1",
+                "chalk": "^2.4.2",
+                "csv-stringify": "^5.3.0",
+                "long": "^4.0.0"
+            }
+        },
+        "ansi-styles": {
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+            "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+            "requires": {
+                "color-convert": "^1.9.0"
+            }
+        },
+        "assemblyscript": {
+            "version": "file:../..",
+            "requires": {
+                "@protobufjs/utf8": "^1.1.0",
+                "binaryen": "87.0.0-nightly.20190716",
+                "glob": "^7.1.4",
+                "long": "^4.0.0",
+                "opencollective-postinstall": "^2.0.0",
+                "source-map-support": "^0.5.12"
+            }
+        },
+        "balanced-match": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+            "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+        },
+        "brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "chalk": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+            "requires": {
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
+            }
+        },
+        "color-convert": {
+            "version": "1.9.3",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+            "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+            "requires": {
+                "color-name": "1.1.3"
+            }
+        },
+        "color-name": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+            "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+        },
+        "concat-map": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+        },
+        "csv-stringify": {
+            "version": "5.3.0",
+            "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.3.0.tgz",
+            "integrity": "sha512-VMYPbE8zWz475smwqb9VbX9cj0y4J0PBl59UdcqzLkzXHZZ8dh4Rmbb0ZywsWEtUml4A96Hn7Q5MW9ppVghYzg==",
+            "optional": true,
+            "requires": {
+                "lodash.get": "~4.4.2"
+            }
+        },
+        "escape-string-regexp": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+        },
+        "fs.realpath": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+        },
+        "glob": {
+            "version": "7.1.4",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+            "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+            "requires": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.0.4",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+            }
+        },
+        "has-flag": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+            "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+        },
+        "inflight": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+            "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+            "requires": {
+                "once": "^1.3.0",
+                "wrappy": "1"
+            }
+        },
+        "inherits": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+            "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+        },
+        "lodash.get": {
+            "version": "4.4.2",
+            "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+            "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
+            "optional": true
+        },
+        "long": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
+            "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
+        },
+        "minimatch": {
+            "version": "3.0.4",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+            "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+            "requires": {
+                "brace-expansion": "^1.1.7"
+            }
+        },
+        "once": {
+            "version": "1.4.0",
+            "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+            "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+            "requires": {
+                "wrappy": "1"
+            }
+        },
+        "path-is-absolute": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+            "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+        },
+        "supports-color": {
+            "version": "5.5.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+            "requires": {
+                "has-flag": "^3.0.0"
+            }
+        },
+        "wrappy": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+            "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+        }
+    }
+}
diff --git a/lib/visitor/package.json b/lib/visitor/package.json
new file mode 100644
index 0000000000..da1e0b40e6
--- /dev/null
+++ b/lib/visitor/package.json
@@ -0,0 +1,20 @@
+{
+  "scripts": {
+    "build:visitor": "tsc",
+    "build": "../../bin/asc --runtime none --noEmit assembly/class.ts --postCompile",
+    "test": "npm run build:visitor && npm run asp",
+    "asp:debug": "tsc && node --inspect-brk ./node_modules/.bin/asp",
+    "asp": "asp --verbose"
+  },
+  "dependencies": {
+    "@as-pect/cli": "^2.3.1",
+    "assemblyscript": "file:../.."
+  },
+  "name": "visitor",
+  "version": "1.0.0",
+  "main": "index.js",
+  "devDependencies": {},
+  "author": "",
+  "license": "ISC",
+  "description": ""
+}
diff --git a/lib/visitor/src/ast/base.ts b/lib/visitor/src/ast/base.ts
new file mode 100644
index 0000000000..66322f7711
--- /dev/null
+++ b/lib/visitor/src/ast/base.ts
@@ -0,0 +1,500 @@
+import {
+  Source,
+  TypeNode,
+  TypeName,
+  NamedTypeNode,
+  FunctionTypeNode,
+  TypeParameterNode,
+  IdentifierExpression,
+  ArrayLiteralExpression,
+  ObjectLiteralExpression,
+  AssertionExpression,
+  BinaryExpression,
+  CallExpression,
+  ClassExpression,
+  CommaExpression,
+  ElementAccessExpression,
+  FunctionExpression,
+  LiteralExpression,
+  FloatLiteralExpression,
+  InstanceOfExpression,
+  IntegerLiteralExpression,
+  StringLiteralExpression,
+  RegexpLiteralExpression,
+  NewExpression,
+  ParenthesizedExpression,
+  PropertyAccessExpression,
+  TernaryExpression,
+  UnaryExpression,
+  UnaryPostfixExpression,
+  UnaryPrefixExpression,
+  SuperExpression,
+  FalseExpression,
+  TrueExpression,
+  ThisExpression,
+  NullExpression,
+  ConstructorExpression,
+  Statement,
+  BlockStatement,
+  BreakStatement,
+  ContinueStatement,
+  ClassDeclaration,
+  DoStatement,
+  EmptyStatement,
+  EnumDeclaration,
+  EnumValueDeclaration,
+  ExportImportStatement,
+  ExportMember,
+  ExportStatement,
+  ExportDefaultStatement,
+  ExpressionStatement,
+  FieldDeclaration,
+  ForStatement,
+  FunctionDeclaration,
+  IfStatement,
+  ImportDeclaration,
+  ImportStatement,
+  IndexSignatureDeclaration,
+  InterfaceDeclaration,
+  MethodDeclaration,
+  NamespaceDeclaration,
+  ReturnStatement,
+  SwitchCase,
+  SwitchStatement,
+  ThrowStatement,
+  TryStatement,
+  TypeDeclaration,
+  VariableDeclaration,
+  VariableStatement,
+  WhileStatement,
+  VoidStatement,
+  CommentNode,
+  DecoratorNode,
+  ParameterNode,
+  Node,
+  Parser
+} from "assemblyscript";
+
+import { AbstractVisitor } from "../visitor";
+import { ASTVisitor } from ".";
+import { Writer } from "..";
+
+export class BaseVisitor extends AbstractVisitor<Node> implements ASTVisitor {
+  depth: number = 0;
+
+  constructor(protected parser: Parser, protected writer: Writer) {
+    super();
+  }
+
+  // /** Visits each node in an array if array exists. */
+  // visitArray(array: Node[] | null): void {
+  //   if (array) {
+  //     array.map(node => {
+  //       if (node) node.visit(this);
+  //     });
+  //   }
+  // }
+
+  start(): void {
+    this.visit(this.parser.program.sources);
+  }
+
+  visitSource(node: Source): void {
+    for (const stmt of node.statements) {
+      this.depth++;
+      stmt.visit(this);
+      this.depth--;
+    }
+  }
+
+  visitTypeNode(node: TypeNode): void {}
+
+  visitTypeName(node: TypeName): void {
+    node.identifier.visit(this);
+    if (node.next) {
+      node.visit(this);
+    }
+  }
+
+  visitNamedTypeNode(node: NamedTypeNode): void {
+    this.visit(node.name);
+    this.visit(node.typeArguments);
+  }
+
+  visitFunctionTypeNode(node: FunctionTypeNode): void {
+    for (let param of node.parameters) {
+      param.visit(this);
+    }
+    node.returnType.visit(this);
+  }
+
+  visitTypeParameter(node: TypeParameterNode): void {
+    node.name.visit(this);
+    if (node.extendsType) node.extendsType.visit(this);
+    if (node.defaultType) node.defaultType.visit(this);
+  }
+
+  visitIdentifierExpression(node: IdentifierExpression): void {}
+
+  visitArrayLiteralExpression(node: ArrayLiteralExpression): void {
+    node.elementExpressions.map(e => {
+      if (e) e.visit(this);
+    });
+  }
+
+  visitObjectLiteralExpression(node: ObjectLiteralExpression): void {
+    if (node.values && node.names) {
+      assert(node.values.length == node.names.length);
+      for (let i = 0; i < node.values.length; i++) {
+        node.names[i].visit(this);
+        node.values[i].visit(this);
+      }
+    }
+  }
+
+  visitAssertionExpression(node: AssertionExpression): void {
+    if (node.toType) node.toType.visit(this);
+    node.expression.visit(this);
+  }
+
+  visitBinaryExpression(node: BinaryExpression): void {
+    node.left.visit(this);
+    node.right.visit(this);
+  }
+
+  visitCallExpression(node: CallExpression): void {
+    node.expression.visit(this);
+    this.visit(node.typeArguments);
+    this.visit(node.arguments);
+  }
+
+  visitClassExpression(node: ClassExpression): void {
+    node.declaration.visit(this);
+  }
+
+  visitCommaExpression(node: CommaExpression): void {
+    this.visit(node.expressions);
+  }
+
+  visitElementAccessExpression(node: ElementAccessExpression): void {
+    node.elementExpression.visit(this);
+    node.expression.visit(this);
+  }
+
+  visitFunctionExpression(node: FunctionExpression): void {
+    node.declaration.visit(this);
+  }
+
+  visitLiteralExpression(node: LiteralExpression): void {
+    // node.
+  }
+
+  visitFloatLiteralExpression(node: FloatLiteralExpression): void {}
+
+  visitInstanceOfExpression(node: InstanceOfExpression): void {
+    node.expression.visit(this);
+    node.isType.visit(this);
+  }
+
+  visitIntegerLiteralExpression(node: IntegerLiteralExpression): void {}
+
+  visitStringLiteral(str: string, singleQuoted?: boolean): void {}
+
+  visitStringLiteralExpression(node: StringLiteralExpression): void {}
+
+  visitRegexpLiteralExpression(node: RegexpLiteralExpression): void {}
+
+  visitNewExpression(node: NewExpression): void {
+    node.expression.visit(this);
+    this.visit(node.typeArguments);
+    this.visit(node.arguments);
+  }
+
+  visitParenthesizedExpression(node: ParenthesizedExpression): void {
+    node.expression.visit(this);
+  }
+
+  visitPropertyAccessExpression(node: PropertyAccessExpression): void {
+    node.property.visit(this);
+    node.expression.visit(this);
+  }
+
+  visitTernaryExpression(node: TernaryExpression): void {
+    node.condition.visit(this);
+    node.ifThen.visit(this);
+    node.ifElse.visit(this);
+  }
+
+  visitUnaryExpression(node: UnaryExpression): void {
+    node.operand.visit(this);
+  }
+
+  visitUnaryPostfixExpression(node: UnaryPostfixExpression): void {
+    node.operand.visit(this);
+  }
+
+  visitUnaryPrefixExpression(node: UnaryPrefixExpression): void {
+    node.operand.visit(this);
+  }
+
+  visitSuperExpression(node: SuperExpression): void {}
+
+  visitFalseExpression(node: FalseExpression): void {}
+
+  visitTrueExpression(node: TrueExpression): void {}
+
+  visitThisExpression(node: ThisExpression): void {}
+
+  visitNullExperssion(node: NullExpression): void {}
+
+  visitConstructorExpression(node: ConstructorExpression): void {}
+
+  visitNodeAndTerminate(statement: Statement): void {}
+
+  visitBlockStatement(node: BlockStatement): void {
+    this.depth++;
+    this.visit(node.statements);
+    this.depth--;
+  }
+
+  visitBreakStatement(node: BreakStatement): void {
+    if (node.label) {
+      node.label.visit(this);
+    }
+  }
+
+  visitContinueStatement(node: ContinueStatement): void {
+    if (node.label) {
+      node.label.visit(this);
+    }
+  }
+
+  visitClassDeclaration(node: ClassDeclaration, isDefault?: boolean): void {
+    node.name.visit(this);
+    this.depth++;
+    this.visit(node.decorators);
+    assert(
+      node.isGeneric ? node.typeParameters != null : node.typeParameters == null
+    );
+    if (node.isGeneric) {
+      this.visit(node.typeParameters);
+    }
+    if (node.extendsType) {
+      node.extendsType.visit(this);
+    }
+    this.visit(node.implementsTypes);
+    this.visit(node.members);
+    this.depth--;
+  }
+
+  visitDoStatement(node: DoStatement): void {
+    node.condition.visit(this);
+    node.statement.visit(this);
+  }
+
+  visitEmptyStatement(node: EmptyStatement): void {}
+
+  visitEnumDeclaration(node: EnumDeclaration, isDefault?: boolean): void {
+    node.name.visit(this);
+    this.visit(node.decorators);
+    this.visit(node.values);
+  }
+
+  visitEnumValueDeclaration(node: EnumValueDeclaration): void {
+    node.name.visit(this);
+    if (node.initializer) {
+      node.initializer.visit(this);
+    }
+  }
+
+  visitExportImportStatement(node: ExportImportStatement): void {
+    node.name.visit(this);
+    node.externalName.visit(this);
+  }
+
+  visitExportMember(node: ExportMember): void {
+    node.localName.visit(this);
+    node.exportedName.visit(this);
+  }
+
+  visitExportStatement(node: ExportStatement): void {
+    if (node.path) {
+      node.path.visit(this);
+    }
+    this.visit(node.members);
+  }
+
+  visitExportDefaultStatement(node: ExportDefaultStatement): void {
+    node.declaration.visit(this);
+  }
+
+  visitExpressionStatement(node: ExpressionStatement): void {
+    node.expression.visit(this);
+  }
+
+  visitFieldDeclaration(node: FieldDeclaration): void {
+    node.name.visit(this);
+    if (node.type) {
+      node.type.visit(this);
+    }
+    if (node.initializer) {
+      node.initializer.visit(this);
+    }
+    this.visit(node.decorators);
+  }
+
+  visitForStatement(node: ForStatement): void {
+    if (node.initializer) node.initializer.visit(this);
+    if (node.condition) node.condition.visit(this);
+    if (node.incrementor) node.incrementor.visit(this);
+    node.statement.visit(this);
+  }
+
+  visitFunctionDeclaration(
+    node: FunctionDeclaration,
+    isDefault?: boolean
+  ): void {
+    node.name.visit(this);
+    this.visit(node.decorators);
+    if (node.isGeneric) {
+      this.visit(node.typeParameters);
+    }
+    node.signature.visit(this);
+    this.depth++;
+    if (node.body) node.body.visit(this);
+    this.depth--;
+  }
+
+  visitFunctionCommon(node: FunctionDeclaration): void {
+    // node.name.visit(this)
+  }
+
+  visitIfStatement(node: IfStatement): void {
+    node.condition.visit(this);
+    node.ifTrue.visit(this);
+    if (node.ifFalse) node.ifFalse.visit(this);
+  }
+
+  visitImportDeclaration(node: ImportDeclaration): void {
+    node.foreignName.visit(this);
+    node.name.visit(this);
+    this.visit(node.decorators);
+  }
+
+  visitImportStatement(node: ImportStatement): void {
+    if (node.namespaceName) node.namespaceName.visit(this);
+    this.visit(node.declarations);
+  }
+
+  visitIndexSignatureDeclaration(node: IndexSignatureDeclaration): void {
+    // node.name.visit(this);
+    // node.keyType.visit(this);
+    // node.valueType.visit(this);
+  }
+
+  visitInterfaceDeclaration(
+    node: InterfaceDeclaration,
+    isDefault?: boolean
+  ): void {
+    node.name.visit(this);
+    if (node.isGeneric) {
+      this.visit(node.typeParameters);
+    }
+    this.visit(node.implementsTypes);
+    if (node.extendsType) node.extendsType.visit(this);
+    this.depth++;
+    this.visit(node.members);
+    this.depth--;
+  }
+
+  visitMethodDeclaration(node: MethodDeclaration): void {
+    node.name.visit(this);
+    if (node.isGeneric) {
+      this.visit(node.typeParameters);
+    }
+    node.signature.visit(this);
+    this.visit(node.decorators);
+    this.depth++;
+    if (node.body) node.body.visit(this);
+    this.depth--;
+  }
+
+  visitNamespaceDeclaration(
+    node: NamespaceDeclaration,
+    isDefault?: boolean
+  ): void {
+    node.name.visit(this);
+    this.visit(node.decorators);
+    this.visit(node.members);
+  }
+
+  visitReturnStatement(node: ReturnStatement): void {
+    if (node.value) node.value.visit(this);
+  }
+
+  visitSwitchCase(node: SwitchCase): void {
+    if (node.label) node.label.visit(this);
+    this.visit(node.statements);
+  }
+
+  visitSwitchStatement(node: SwitchStatement): void {
+    node.condition.visit(this);
+    this.depth++;
+    this.visit(node.cases);
+    this.depth--;
+  }
+
+  visitThrowStatement(node: ThrowStatement): void {
+    node.value.visit(this);
+  }
+
+  visitTryStatement(node: TryStatement): void {
+    this.visit(node.statements);
+    if (node.catchVariable) node.catchVariable.visit(this);
+    this.visit(node.catchStatements);
+    this.visit(node.finallyStatements);
+  }
+
+  visitTypeDeclaration(node: TypeDeclaration): void {
+    node.name.visit(this);
+    this.visit(node.decorators);
+    node.type.visit(this);
+    this.visit(node.typeParameters);
+  }
+
+  visitVariableDeclaration(node: VariableDeclaration): void {
+    node.name.visit(this);
+    if (node.type) node.type.visit(this);
+    if (node.initializer) node.initializer.visit(this);
+  }
+
+  visitVariableStatement(node: VariableStatement): void {
+    this.visit(node.decorators);
+    this.visit(node.declarations);
+  }
+
+  visitWhileStatement(node: WhileStatement): void {
+    node.condition.visit(this);
+    this.depth++;
+    node.statement.visit(this);
+    this.depth--;
+  }
+
+  visitVoidStatement(node: VoidStatement): void {}
+
+  visitComment(node: CommentNode): void {}
+
+  visitDecoratorNode(node: DecoratorNode): void {
+    node.name.visit(this);
+    this.visit(node.arguments);
+  }
+
+  visitParameter(node: ParameterNode): void {
+    node.name.visit(this);
+    if (node.implicitFieldDeclaration) {
+      node.implicitFieldDeclaration.visit(this);
+    }
+    if (node.initializer) node.initializer.visit(this);
+    node.type.visit(this);
+  }
+}
diff --git a/lib/visitor/src/ast/empty.ts b/lib/visitor/src/ast/empty.ts
new file mode 100644
index 0000000000..86b68bcaf2
--- /dev/null
+++ b/lib/visitor/src/ast/empty.ts
@@ -0,0 +1,161 @@
+import {
+  ASTVisitor,
+  Source,
+  TypeNode,
+  TypeName,
+  NamedTypeNode,
+  FunctionTypeNode,
+  TypeParameterNode,
+  IdentifierExpression,
+  ArrayLiteralExpression,
+  ObjectLiteralExpression,
+  AssertionExpression,
+  BinaryExpression,
+  CallExpression,
+  ClassExpression,
+  CommaExpression,
+  ElementAccessExpression,
+  FunctionExpression,
+  LiteralExpression,
+  FloatLiteralExpression,
+  InstanceOfExpression,
+  IntegerLiteralExpression,
+  StringLiteralExpression,
+  RegexpLiteralExpression,
+  NewExpression,
+  ParenthesizedExpression,
+  PropertyAccessExpression,
+  TernaryExpression,
+  UnaryExpression,
+  UnaryPostfixExpression,
+  UnaryPrefixExpression,
+  SuperExpression,
+  FalseExpression,
+  TrueExpression,
+  ThisExpression,
+  NullExpression,
+  ConstructorExpression,
+  Statement,
+  BlockStatement,
+  BreakStatement,
+  ContinueStatement,
+  ClassDeclaration,
+  DoStatement,
+  EmptyStatement,
+  EnumDeclaration,
+  EnumValueDeclaration,
+  ExportImportStatement,
+  ExportMember,
+  ExportStatement,
+  ExportDefaultStatement,
+  ExpressionStatement,
+  FieldDeclaration,
+  ForStatement,
+  FunctionDeclaration,
+  IfStatement,
+  ImportDeclaration,
+  ImportStatement,
+  IndexSignatureDeclaration,
+  InterfaceDeclaration,
+  MethodDeclaration,
+  NamespaceDeclaration,
+  ReturnStatement,
+  SwitchCase,
+  SwitchStatement,
+  ThrowStatement,
+  TryStatement,
+  TypeDeclaration,
+  VariableDeclaration,
+  VariableStatement,
+  WhileStatement,
+  VoidStatement,
+  CommentNode,
+  DecoratorNode,
+  ParameterNode
+} from "assemblyscript";
+
+export class EmptyVisitor implements ASTVisitor {
+  visitSource(node: Source): void {}
+  visitTypeNode(node: TypeNode): void {}
+  visitTypeName(node: TypeName): void {}
+  visitNamedTypeNode(node: NamedTypeNode): void {}
+  visitFunctionTypeNode(node: FunctionTypeNode): void {}
+  visitTypeParameter(node: TypeParameterNode): void {}
+  visitIdentifierExpression(node: IdentifierExpression): void {}
+  visitArrayLiteralExpression(node: ArrayLiteralExpression): void {}
+  visitObjectLiteralExpression(node: ObjectLiteralExpression): void {}
+  visitAssertionExpression(node: AssertionExpression): void {}
+  visitBinaryExpression(node: BinaryExpression): void {}
+  visitCallExpression(node: CallExpression): void {}
+  visitClassExpression(node: ClassExpression): void {}
+  visitCommaExpression(node: CommaExpression): void {}
+  visitElementAccessExpression(node: ElementAccessExpression): void {}
+  visitFunctionExpression(node: FunctionExpression): void {}
+  visitLiteralExpression(node: LiteralExpression): void {}
+  visitFloatLiteralExpression(node: FloatLiteralExpression): void {}
+  visitInstanceOfExpression(node: InstanceOfExpression): void {}
+  visitIntegerLiteralExpression(node: IntegerLiteralExpression): void {}
+  visitStringLiteral(str: string, singleQuoted?: boolean): void {}
+  visitStringLiteralExpression(node: StringLiteralExpression): void {}
+  visitRegexpLiteralExpression(node: RegexpLiteralExpression): void {}
+  visitNewExpression(node: NewExpression): void {}
+  visitParenthesizedExpression(node: ParenthesizedExpression): void {}
+  visitPropertyAccessExpression(node: PropertyAccessExpression): void {}
+  visitTernaryExpression(node: TernaryExpression): void {}
+  visitUnaryExpression(node: UnaryExpression): void {}
+  visitUnaryPostfixExpression(node: UnaryPostfixExpression): void {}
+  visitUnaryPrefixExpression(node: UnaryPrefixExpression): void {}
+  visitSuperExpression(node: SuperExpression): void {}
+  visitFalseExpression(node: FalseExpression): void {}
+  visitTrueExpression(node: TrueExpression): void {}
+  visitThisExpression(node: ThisExpression): void {}
+  visitNullExperssion(node: NullExpression): void {}
+  visitConstructorExpression(node: ConstructorExpression): void {}
+  visitNodeAndTerminate(statement: Statement): void {}
+  visitBlockStatement(node: BlockStatement): void {}
+  visitBreakStatement(node: BreakStatement): void {}
+  visitContinueStatement(node: ContinueStatement): void {}
+  visitClassDeclaration(node: ClassDeclaration, isDefault?: boolean): void {}
+  visitDoStatement(node: DoStatement): void {}
+  visitEmptyStatement(node: EmptyStatement): void {}
+  visitEnumDeclaration(node: EnumDeclaration, isDefault?: boolean): void {}
+  visitEnumValueDeclaration(node: EnumValueDeclaration): void {}
+  visitExportImportStatement(node: ExportImportStatement): void {}
+  visitExportMember(node: ExportMember): void {}
+  visitExportStatement(node: ExportStatement): void {}
+  visitExportDefaultStatement(node: ExportDefaultStatement): void {}
+  visitExpressionStatement(node: ExpressionStatement): void {}
+  visitFieldDeclaration(node: FieldDeclaration): void {}
+  visitForStatement(node: ForStatement): void {}
+  visitFunctionDeclaration(
+    node: FunctionDeclaration,
+    isDefault?: boolean
+  ): void {}
+  visitFunctionCommon(node: FunctionDeclaration): void {}
+  visitIfStatement(node: IfStatement): void {}
+  visitImportDeclaration(node: ImportDeclaration): void {}
+  visitImportStatement(node: ImportStatement): void {}
+  visitIndexSignatureDeclaration(node: IndexSignatureDeclaration): void {}
+  visitInterfaceDeclaration(
+    node: InterfaceDeclaration,
+    isDefault?: boolean
+  ): void {}
+  visitMethodDeclaration(node: MethodDeclaration): void {}
+  visitNamespaceDeclaration(
+    node: NamespaceDeclaration,
+    isDefault?: boolean
+  ): void {}
+  visitReturnStatement(node: ReturnStatement): void {}
+  visitSwitchCase(node: SwitchCase): void {}
+  visitSwitchStatement(node: SwitchStatement): void {}
+  visitThrowStatement(node: ThrowStatement): void {}
+  visitTryStatement(node: TryStatement): void {}
+  visitTypeDeclaration(node: TypeDeclaration): void {}
+  visitVariableDeclaration(node: VariableDeclaration): void {}
+  visitVariableStatement(node: VariableStatement): void {}
+  visitWhileStatement(node: WhileStatement): void {}
+  visitVoidStatement(node: VoidStatement): void {}
+  visitComment(node: CommentNode): void {}
+  visitDecoratorNode(node: DecoratorNode): void {}
+  visitParameter(node: ParameterNode): void {}
+}
diff --git a/lib/visitor/src/ast/index.ts b/lib/visitor/src/ast/index.ts
new file mode 100644
index 0000000000..d4ef036810
--- /dev/null
+++ b/lib/visitor/src/ast/index.ts
@@ -0,0 +1,7 @@
+import { ASTVisitor as IVisitor, Node } from "assemblyscript";
+import { Visitor } from "../visitor";
+
+export interface ASTVisitor extends IVisitor, Visitor<Node>{}
+
+export * from "./base";
+export * from "./empty";
\ No newline at end of file
diff --git a/lib/visitor/src/ast/transform.ts b/lib/visitor/src/ast/transform.ts
new file mode 100644
index 0000000000..80a20dc11e
--- /dev/null
+++ b/lib/visitor/src/ast/transform.ts
@@ -0,0 +1,40 @@
+import { BaseVisitor } from './base';
+import { Node, ClassDeclaration, Parser, FieldDeclaration, MethodDeclaration } from 'assemblyscript';
+import { Writer } from '..';
+
+class Transform extends BaseVisitor {
+  currentNode: Node[] = [];
+
+  transfrom<T extends Node>(node: T): T {
+    this.currentNode.push(node);
+    this.visit(node);
+    return <T> this.currentNode.pop();
+  }
+}
+
+type classTransformer = (_class: ClassDeclaration) => ClassDeclaration;
+
+class ClassWriter extends Transform {
+
+  constructor(parser: Parser, writer: Writer, transformer: classTransformer) {
+    super(parser, writer);
+  }
+
+  visitClassDeclaration(_class: ClassDeclaration): void {
+    // tslint:disable-next-line: as-types
+    _class.members = _class.members.map((member) => this.transfrom(member));
+  }
+
+  visitMethodDeclaration(_method: MethodDeclaration): void {
+
+  }
+
+  visitFieldDeclaration(field: FieldDeclaration): void {
+    // field.type!.
+  }
+
+
+
+}
+
+
diff --git a/lib/visitor/src/element/base.ts b/lib/visitor/src/element/base.ts
new file mode 100644
index 0000000000..b6fe8f7721
--- /dev/null
+++ b/lib/visitor/src/element/base.ts
@@ -0,0 +1,168 @@
+import {
+  ElementVisitor as IVisitor,
+  File,
+  TypeDefinition,
+  Namespace,
+  Enum,
+  EnumValue,
+  Global,
+  Local,
+  FunctionPrototype,
+  Function,
+  FunctionTarget,
+  FieldPrototype,
+  Field,
+  PropertyPrototype,
+  Property,
+  ClassPrototype,
+  Class,
+  InterfacePrototype,
+  Interface,
+  Element,
+  Node,
+  NodeKind,
+  ElementKind,
+  Parser,
+  Compiler
+} from "assemblyscript";
+
+import { Visitor, AbstractVisitor, Collection } from "../visitor";
+import { ASTVisitor } from "../ast/index";
+import { DeclarationStatement } from "assemblyscript";
+import { DeclaredElement } from "assemblyscript";
+import { Writer } from "..";
+
+interface ElementVisitor extends Visitor<Element>, IVisitor {}
+
+export abstract class BaseElementVisitor extends AbstractVisitor<Element>
+  implements ElementVisitor {
+
+  astVisitor: ASTVisitor;
+
+  constructor(public parser: Parser, public compiler: Compiler, public writer: Writer) {
+    super();
+  }
+
+  get files(): Iterable<File> {
+    return this.parser.program.filesByName.values();
+  }
+
+  getFunctionByName(name: string): Function {
+    return this.compiler.program.instancesByName.get(name) as Function;
+  }
+
+  start(): void {
+    this.visit(this.files);
+  }
+
+  visitFile(node: File): void {
+    var declares: DeclarationStatement[];
+    // tslint:disable-next-line: as-types
+    declares = node.source.statements.filter(s => s instanceof DeclarationStatement) as DeclarationStatement[];
+    this.visit(declares.map(stmt => node.program.elementsByDeclaration.get(stmt)) as DeclaredElement[]);
+    // this.visit(node.members);
+    // this.visit(node.program.elementsByName);
+  }
+
+  visitNode(node: Collection<Node>): void {
+    this.astVisitor.visit(node);
+  }
+
+  // visit(element: Element | Element[] | null ): void {
+  //   if (element) {
+  //     if (element instanceof Element) {
+  //       element.visit(this);
+  //     }else {
+  //       element.map(this.visit);
+  //     }
+  //   }
+  // }
+
+  // visitMemebers(map: Map<any, Element> | null): void {
+  //   if (map) {
+  //     for (let element of map.values()) {
+  //       element.visit(this);
+  //     }
+  //   }
+  // }
+
+  visitManagedClasses(files: Iterable<File>, visitor?: (c: Class) => void): void {
+    this.visitElements(files, ElementKind.CLASS, visitor);
+  }
+
+  visitInterfaces(files: Iterable<File>, visitor?: ((i: InterfacePrototype) => void)): void {
+    this.visitElements(files, ElementKind.INTERFACE_PROTOTYPE , visitor);
+  }
+
+  private visitElements(files: Iterable<File>, elementKind: ElementKind, visitor?: ((e: DeclaredElement) => void)): void {
+    for (let file of files) {
+      if (!file.name.startsWith("~lib")) {
+        if (file.members) {
+          for (let element of file.members.values()) {
+            if (element.kind == elementKind) {
+              if (visitor) {
+                visitor(element);
+              } else {
+                element.visit(this);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  visitTypeDefinition(node: TypeDefinition): void {}
+  visitNamespace(node: Namespace): void {
+    this.visit(node.members);
+  }
+  visitEnum(node: Enum): void {
+    this.visit(node.members);
+  }
+  visitEnumValue(node: EnumValue): void {}
+  visitGlobal(node: Global): void {}
+  visitLocal(node: Local): void {}
+  visitFunctionPrototype(node: FunctionPrototype): void {
+    if (node.parent instanceof Function) {
+      node.parent.visit(this);
+    } else {
+      this.visit(node.members);
+    }
+  }
+  visitFunction(node: Function): void {
+    this.visit(node.members);
+  }
+  visitFunctionTarget(node: FunctionTarget): void {}
+  visitFieldPrototype(node: FieldPrototype): void {
+    if (node.parent instanceof Field) {
+      node.parent.visit(this);
+    }
+  }
+  visitField(node: Field): void {}
+  visitPropertyPrototype(node: PropertyPrototype): void {
+    if (node.parent instanceof Property) {
+      node.parent.visit(this);
+    } else {
+      this.visit(node.getterPrototype);
+      this.visit(node.setterPrototype);
+    }
+  }
+  visitProperty(node: Property): void {
+    this.visit(node.getterInstance);
+    this.visit(node.setterInstance);
+  }
+  visitClassPrototype(node: ClassPrototype): void {
+    if (node.parent instanceof Class) {
+      node.parent.visit(this);
+    } else {
+      this.visit(node.instanceMembers);
+    }
+  }
+  visitClass(node: Class): void {
+    this.visit(node.members);
+  }
+  visitInterfacePrototype(node: InterfacePrototype): void {}
+  visitInterface(node: Interface): void {
+    this.visit(node.prototype.instanceMembers);
+  }
+}
diff --git a/lib/visitor/src/element/classVisitor.ts b/lib/visitor/src/element/classVisitor.ts
new file mode 100644
index 0000000000..fed1771b45
--- /dev/null
+++ b/lib/visitor/src/element/classVisitor.ts
@@ -0,0 +1,7 @@
+import { BaseElementVisitor } from "./base";
+
+abstract class ClassWriter {}
+
+abstract class ClassVisitor extends BaseElementVisitor {
+
+}
diff --git a/lib/visitor/src/element/empty.ts b/lib/visitor/src/element/empty.ts
new file mode 100644
index 0000000000..e6b4b35315
--- /dev/null
+++ b/lib/visitor/src/element/empty.ts
@@ -0,0 +1,43 @@
+import {
+  ElementVisitor,
+  File,
+  TypeDefinition,
+  Namespace,
+  Enum,
+  EnumValue,
+  Global,
+  Local,
+  FunctionPrototype,
+  Function,
+  FunctionTarget,
+  FieldPrototype,
+  Field,
+  PropertyPrototype,
+  Property,
+  ClassPrototype,
+  Class,
+  InterfacePrototype,
+  Interface,
+  Element
+} from "assemblyscript";
+
+export class EmptyElementVisitor implements ElementVisitor {
+  visitFile(node: File): void {}
+  visitTypeDefinition(node: TypeDefinition): void {}
+  visitNamespace(node: Namespace): void {}
+  visitEnum(node: Enum): void {}
+  visitEnumValue(node: EnumValue): void {}
+  visitGlobal(node: Global): void {}
+  visitLocal(node: Local): void {}
+  visitFunctionPrototype(node: FunctionPrototype): void {}
+  visitFunction(node: Function): void {}
+  visitFunctionTarget(node: FunctionTarget): void {}
+  visitFieldPrototype(node: FieldPrototype): void {}
+  visitField(node: Field): void {}
+  visitPropertyPrototype(node: PropertyPrototype): void {}
+  visitProperty(node: Property): void {}
+  visitClassPrototype(node: ClassPrototype): void {}
+  visitClass(node: Class): void {}
+  visitInterfacePrototype(node: InterfacePrototype): void {}
+  visitInterface(node: Interface): void {}
+}
diff --git a/lib/visitor/src/element/index.ts b/lib/visitor/src/element/index.ts
new file mode 100644
index 0000000000..955fdd1439
--- /dev/null
+++ b/lib/visitor/src/element/index.ts
@@ -0,0 +1 @@
+export * from "./base";
diff --git a/lib/visitor/src/index.ts b/lib/visitor/src/index.ts
new file mode 100644
index 0000000000..f151cee846
--- /dev/null
+++ b/lib/visitor/src/index.ts
@@ -0,0 +1,3 @@
+export interface Writer {
+  write(str: string): void;
+}
diff --git a/lib/visitor/src/instances/astPrinter.ts b/lib/visitor/src/instances/astPrinter.ts
new file mode 100644
index 0000000000..944e810d0e
--- /dev/null
+++ b/lib/visitor/src/instances/astPrinter.ts
@@ -0,0 +1,494 @@
+import {
+  ASTVisitor,
+  Source,
+  TypeNode,
+  TypeName,
+  NamedTypeNode,
+  FunctionTypeNode,
+  TypeParameterNode,
+  IdentifierExpression,
+  ArrayLiteralExpression,
+  ObjectLiteralExpression,
+  AssertionExpression,
+  BinaryExpression,
+  CallExpression,
+  ClassExpression,
+  CommaExpression,
+  ElementAccessExpression,
+  FunctionExpression,
+  LiteralExpression,
+  FloatLiteralExpression,
+  InstanceOfExpression,
+  IntegerLiteralExpression,
+  StringLiteralExpression,
+  RegexpLiteralExpression,
+  NewExpression,
+  ParenthesizedExpression,
+  PropertyAccessExpression,
+  TernaryExpression,
+  UnaryExpression,
+  UnaryPostfixExpression,
+  UnaryPrefixExpression,
+  SuperExpression,
+  FalseExpression,
+  TrueExpression,
+  ThisExpression,
+  NullExpression,
+  ConstructorExpression,
+  Statement,
+  BlockStatement,
+  BreakStatement,
+  ContinueStatement,
+  ClassDeclaration,
+  DoStatement,
+  EmptyStatement,
+  EnumDeclaration,
+  EnumValueDeclaration,
+  ExportImportStatement,
+  ExportMember,
+  ExportStatement,
+  ExportDefaultStatement,
+  ExpressionStatement,
+  FieldDeclaration,
+  ForStatement,
+  FunctionDeclaration,
+  IfStatement,
+  ImportDeclaration,
+  ImportStatement,
+  IndexSignatureDeclaration,
+  InterfaceDeclaration,
+  MethodDeclaration,
+  NamespaceDeclaration,
+  ReturnStatement,
+  SwitchCase,
+  SwitchStatement,
+  ThrowStatement,
+  TryStatement,
+  TypeDeclaration,
+  VariableDeclaration,
+  VariableStatement,
+  WhileStatement,
+  VoidStatement,
+  CommentNode,
+  DecoratorNode,
+  ParameterNode,
+  operatorTokenToString
+} from "assemblyscript";
+import { BaseVisitor } from "../ast";
+
+export class PrinterVisitor extends BaseVisitor implements ASTVisitor {
+  depth: number = 0;
+  sb: string[] = [];
+
+
+  write(str: string, newline: boolean = true): void {
+    this.writer.write("  ".repeat(this.depth) + str + (newline ? "\n" : " "));
+  }
+
+  flush(seperator: string): string {
+    let res = this.sb.join(seperator);
+    this.sb.length = 0;
+    return res;
+  }
+
+  visitSource(node: Source): void {
+    this.write("Source: " + node.normalizedPath);
+    super.visitSource(node);
+  }
+
+  visitTypeNode(node: TypeNode): void {
+    this.write("TypeNode: " + node.kind.toString());
+    super.visitTypeNode(node);
+  }
+
+  visitFunctionTypeNode(node: FunctionTypeNode): void {
+    this.write("FunctionTypeNode: ", false);
+    for (let param of node.parameters) {
+      param.visit(this);
+    }
+    this.write("(" + this.flush(", ") + ") -> ");
+    this.write("return type: ", false);
+    node.returnType.visit(this);
+  }
+
+  visitTypeParameter(node: TypeParameterNode): void {
+    this.write("TypeParameter ", false);
+    node.name.visit(this);
+  }
+
+  visitIdentifierExpression(node: IdentifierExpression): void {
+    this.sb.push(node.symbol);
+    super.visitIdentifierExpression(node);
+  }
+
+  visitArrayLiteralExpression(node: ArrayLiteralExpression): void {
+    this.write("ArrayLiteralExpression: ", false);
+    super.visitArrayLiteralExpression(node);
+    this.write("[" + this.flush(", ") + "]");
+  }
+
+  visitObjectLiteralExpression(node: ObjectLiteralExpression): void {
+    this.write("ObjectLiteralExpression: ");
+    super.visitObjectLiteralExpression(node);
+    this.depth++;
+
+    this.write("{");
+    for (let i = 0; i < this.sb.length; i += 2) {
+      this.write("  " + this.sb[i] + ": " + this.sb[i + 1]);
+    }
+    this.write("}");
+    this.depth--;
+  }
+
+  visitAssertionExpression(node: AssertionExpression): void {
+    this.write("AssertionExpression: ", false);
+    super.visitAssertionExpression(node);
+    this.write(this.flush(" "));
+  }
+
+  visitBinaryExpression(node: BinaryExpression): void {
+    this.write("BinaryExpression: ", false);
+    super.visitBinaryExpression(node);
+    this.sb.push(this.flush(operatorTokenToString(node.operator)));
+  }
+
+  visitCallExpression(node: CallExpression): void {
+    this.write("CallExpression");
+    super.visitCallExpression(node);
+  }
+
+  visitClassExpression(node: ClassExpression): void {
+    this.write("ClassExpression");
+    super.visitClassExpression(node);
+  }
+
+  visitCommaExpression(node: CommaExpression): void {
+    this.write("CommaExpression");
+    super.visitCommaExpression(node);
+  }
+
+  visitElementAccessExpression(node: ElementAccessExpression): void {
+    this.write("ElementAccessExpression");
+    super.visitElementAccessExpression(node);
+  }
+
+  visitFunctionExpression(node: FunctionExpression): void {
+    this.write("FunctionExpression");
+    super.visitFunctionExpression(node);
+  }
+
+  visitLiteralExpression(node: LiteralExpression): void {
+    this.write("LiteralExpression");
+    super.visitLiteralExpression(node);
+  }
+
+  visitFloatLiteralExpression(node: FloatLiteralExpression): void {
+    this.write("FloatLiteralExpression");
+    super.visitFloatLiteralExpression(node);
+  }
+
+  visitInstanceOfExpression(node: InstanceOfExpression): void {
+    this.write("InstanceOfExpression");
+    super.visitInstanceOfExpression(node);
+  }
+
+  visitIntegerLiteralExpression(node: IntegerLiteralExpression): void {
+    this.sb.push(i64_to_string(node.value));
+  }
+
+  visitStringLiteral(str: string, singleQuoted?: boolean): void {
+    this.write("StringLiteral");
+    this.sb.push(str);
+  }
+
+  visitStringLiteralExpression(node: StringLiteralExpression): void {
+    this.write("StringLiteralExpression");
+    super.visitStringLiteralExpression(node);
+  }
+
+  visitRegexpLiteralExpression(node: RegexpLiteralExpression): void {
+    this.write("RegexpLiteralExpression");
+    super.visitRegexpLiteralExpression(node);
+  }
+
+  visitNewExpression(node: NewExpression): void {
+    this.write("NewExpression");
+    super.visitNewExpression(node);
+  }
+
+  visitParenthesizedExpression(node: ParenthesizedExpression): void {
+    this.write("ParenthesizedExpression");
+    super.visitParenthesizedExpression(node);
+  }
+
+  visitPropertyAccessExpression(node: PropertyAccessExpression): void {
+    this.write("PropertyAccessExpression");
+    super.visitPropertyAccessExpression(node);
+  }
+
+  visitTernaryExpression(node: TernaryExpression): void {
+    this.write("TernaryExpression");
+    super.visitTernaryExpression(node);
+  }
+
+  visitUnaryExpression(node: UnaryExpression): void {
+    this.write("UnaryExpression");
+    super.visitUnaryExpression(node);
+  }
+
+  visitUnaryPostfixExpression(node: UnaryPostfixExpression): void {
+    this.write("UnaryPostfixExpression");
+    super.visitUnaryPostfixExpression(node);
+  }
+
+  visitUnaryPrefixExpression(node: UnaryPrefixExpression): void {
+    this.write("UnaryPrefixExpression");
+    super.visitUnaryPrefixExpression(node);
+  }
+
+  visitSuperExpression(node: SuperExpression): void {
+    this.write("SuperExpression: " + node.symbol);
+    super.visitSuperExpression(node);
+  }
+
+  visitFalseExpression(node: FalseExpression): void {
+    this.write("FalseExpression");
+    super.visitFalseExpression(node);
+  }
+
+  visitTrueExpression(node: TrueExpression): void {
+    this.write("TrueExpression");
+    super.visitTrueExpression(node);
+  }
+
+  visitThisExpression(node: ThisExpression): void {
+    this.write("ThisExpression");
+    super.visitThisExpression(node);
+  }
+
+  visitNullExperssion(node: NullExpression): void {
+    this.write("NullExperssion");
+    super.visitNullExperssion(node);
+  }
+
+  visitConstructorExpression(node: ConstructorExpression): void {
+    this.write("ConstructorExpression");
+    super.visitConstructorExpression(node);
+  }
+
+  visitNodeAndTerminate(statement: Statement): void {
+    this.write("NodeAndTerminate");
+  }
+
+  visitBlockStatement(node: BlockStatement): void {
+    this.write("BlockStatement");
+    this.depth++;
+    super.visitBlockStatement(node);
+    this.depth--;
+  }
+
+  visitBreakStatement(node: BreakStatement): void {
+    this.write("BreakStatement");
+    super.visitBreakStatement(node);
+  }
+
+  visitContinueStatement(node: ContinueStatement): void {
+    this.write("ContinueStatement");
+    super.visitContinueStatement(node);
+  }
+
+  visitClassDeclaration(node: ClassDeclaration, isDefault?: boolean): void {
+    this.write("ClassDeclaration: " + node.name.symbol);
+    for (const member of node.members) {
+      this.depth++;
+      member.visit(this);
+      this.depth--;
+    }
+  }
+
+  visitDoStatement(node: DoStatement): void {
+    this.write("DoStatement");
+    super.visitDoStatement(node);
+  }
+
+  visitEmptyStatement(node: EmptyStatement): void {
+    this.write("EmptyStatement");
+    super.visitEmptyStatement(node);
+  }
+
+  visitEnumDeclaration(node: EnumDeclaration, isDefault?: boolean): void {
+    this.write("EnumDeclaration: " + node.name);
+    super.visitEnumDeclaration(node);
+  }
+
+  visitEnumValueDeclaration(node: EnumValueDeclaration): void {
+    this.write("EnumValueDeclaration");
+    super.visitEnumValueDeclaration(node);
+  }
+
+  visitExportImportStatement(node: ExportImportStatement): void {
+    this.write("ExportImportStatement");
+    super.visitExportImportStatement(node);
+  }
+
+  visitExportMember(node: ExportMember): void {
+    this.write("ExportMember");
+    super.visitExportMember(node);
+  }
+
+  visitExportStatement(node: ExportStatement): void {
+    this.write("ExportStatement");
+    super.visitExportStatement(node);
+  }
+
+  visitExportDefaultStatement(node: ExportDefaultStatement): void {
+    this.write("ExportDefaultStatement");
+    super.visitExportDefaultStatement(node);
+  }
+
+  visitExpressionStatement(node: ExpressionStatement): void {
+    this.write("ExpressionStatement: ");
+    super.visitExpressionStatement(node);
+    this.write(this.flush(" "));
+  }
+
+  visitFieldDeclaration(node: FieldDeclaration): void {
+    this.write("FieldDeclaration: ", false);
+    node.name.visit(this);
+    node.type!.visit(this);
+    this.write(this.flush(": "));
+  }
+
+  visitForStatement(node: ForStatement): void {
+    this.write("ForStatement");
+    super.visitForStatement(node);
+  }
+
+  visitFunctionDeclaration(
+    node: FunctionDeclaration,
+    isDefault?: boolean
+  ): void {
+    this.write("FunctionDeclaration: " + node.name.symbol, false);
+    node.signature.visit(this);
+  }
+
+  visitFunctionCommon(node: FunctionDeclaration): void {
+    this.write("FunctionCommon");
+    super.visitFunctionCommon(node);
+  }
+  visitIfStatement(node: IfStatement): void {
+    this.write("IfStatement");
+    super.visitIfStatement(node);
+  }
+
+  visitImportDeclaration(node: ImportDeclaration): void {
+    this.write("ImportDeclaration");
+    super.visitImportDeclaration(node);
+  }
+
+  visitImportStatement(node: ImportStatement): void {
+    this.write("ImportStatement: " + node.internalPath);
+    super.visitImportStatement(node);
+  }
+
+  visitIndexSignatureDeclaration(node: IndexSignatureDeclaration): void {
+    this.write("IndexSignatureDeclaration");
+    super.visitIndexSignatureDeclaration(node);
+  }
+
+  visitInterfaceDeclaration(
+    node: InterfaceDeclaration,
+    isDefault?: boolean
+  ): void {
+    this.write("InterfaceDeclaration", false);
+    node.name.visit(this);
+    this.write(this.flush(""), false);
+    if (node.isGeneric) {
+      this.visit(node.typeParameters);
+      this.write("<" + this.flush(", ") + "> ", false);
+    }
+    this.visit(node.implementsTypes);
+    if (this.sb.length > 0) {
+      this.write("implements " + this.flush(", "));
+    }
+    if (node.extendsType) {
+      node.extendsType.visit(this);
+      this.write("extends " + this.flush(""), false);
+    }
+    this.write("");
+    this.depth++;
+    this.visit(node.members);
+    this.depth--;
+  }
+
+  visitMethodDeclaration(node: MethodDeclaration): void {
+    this.write("MethodDeclaration: " + node.name.symbol);
+    this.depth++;
+    if (node.body) node.body.visit(this);
+    this.depth--;
+  }
+  visitNamespaceDeclaration(
+    node: NamespaceDeclaration,
+    isDefault?: boolean
+  ): void {
+    this.write("NamespaceDeclaration");
+    super.visitNamespaceDeclaration(node);
+  }
+  visitReturnStatement(node: ReturnStatement): void {
+    this.write("ReturnStatement");
+    super.visitReturnStatement(node);
+  }
+  visitSwitchCase(node: SwitchCase): void {
+    this.write("SwitchCase");
+    super.visitSwitchCase(node);
+  }
+  visitSwitchStatement(node: SwitchStatement): void {
+    this.write("SwitchStatement");
+    super.visitSwitchStatement(node);
+  }
+  visitThrowStatement(node: ThrowStatement): void {
+    this.write("ThrowStatement");
+    super.visitThrowStatement(node);
+  }
+  visitTryStatement(node: TryStatement): void {
+    this.write("TryStatement");
+    super.visitTryStatement(node);
+  }
+  visitTypeDeclaration(node: TypeDeclaration): void {
+    this.write("TypeDeclaration");
+    super.visitTypeDeclaration(node);
+  }
+  visitVariableDeclaration(node: VariableDeclaration): void {
+    this.write("VariableDeclaration: ", false);
+    node.name.visit(this);
+    if (node.type) node.type.visit(this);
+    let name = this.flush(": ");
+    if (node.initializer) node.initializer.visit(this);
+    let initializer = this.flush(" ");
+    this.write(name + (node.initializer ? " = " + initializer : "") + ";");
+  }
+  visitVariableStatement(node: VariableStatement): void {
+    this.write("VariableStatement");
+    super.visitVariableStatement(node);
+  }
+  visitWhileStatement(node: WhileStatement): void {
+    this.write("WhileStatement");
+    super.visitWhileStatement(node);
+  }
+  visitVoidStatement(node: VoidStatement): void {
+    this.write("VoidStatement");
+    super.visitVoidStatement(node);
+  }
+  visitComment(node: CommentNode): void {
+    this.write("Comment");
+    super.visitComment(node);
+  }
+  visitDecoratorNode(node: DecoratorNode): void {
+    this.write("DecoratorNode");
+    super.visitDecoratorNode(node);
+  }
+  visitParameter(node: ParameterNode): void {
+    this.write("Parameter " + node.name.symbol + ":", false);
+    node.type.visit(this);
+  }
+}
diff --git a/lib/visitor/src/instances/elementPrinter.ts b/lib/visitor/src/instances/elementPrinter.ts
new file mode 100644
index 0000000000..bb96c72f61
--- /dev/null
+++ b/lib/visitor/src/instances/elementPrinter.ts
@@ -0,0 +1,130 @@
+import {
+  ElementVisitor,
+  File,
+  TypeDefinition,
+  Namespace,
+  Enum,
+  EnumValue,
+  Global,
+  Local,
+  FunctionPrototype,
+  FunctionTarget,
+  FieldPrototype,
+  Field,
+  PropertyPrototype,
+  Property,
+  ClassPrototype,
+  Class,
+  InterfacePrototype,
+  Interface,
+  Function,
+  Program,
+  Compiler,
+  ClassDeclaration,
+  Parser,
+  Element
+} from "assemblyscript";
+import { BaseElementVisitor } from "../element";
+import { PrinterVisitor } from "./astPrinter";
+import { Collection } from "../visitor";
+
+export default class ProgramPrinter extends BaseElementVisitor
+  implements ElementVisitor {
+  depth: number = 0;
+  astVisitor: PrinterVisitor  = new PrinterVisitor(this.parser, this.writer);
+
+
+  visit(node: Collection<Element>): void {
+    if (node && (<Element>node).name && (<Element>node).internalName.startsWith("~")) {
+      return;
+    }
+    super.visit(node);
+  }
+
+  write(str: string, newline: boolean = false): void {
+    this.writer.write("  ".repeat(this.depth) + str + (newline ? "\n" : " "));
+  }
+
+  visitFile(node: File): void {
+    if (node.name.startsWith("~")) {
+      return;
+    }
+    this.write("visiting file: " + node.name, true);
+    this.depth++;
+    super.visitFile(node);
+    this.depth--;
+  }
+  visitTypeDefinition(node: TypeDefinition): void {
+    this.write(node.type.toString());
+    this.astVisitor.visit(node.typeParameterNodes);
+  }
+  visitNamespace(node: Namespace): void {
+    this.write("Namespace: " + node.name, true);
+    super.visitNamespace(node);
+  }
+  visitEnum(node: Enum): void {
+    this.write("Enum: " + node, true);
+    super.visitNamespace(node);
+  }
+  visitEnumValue(node: EnumValue): void {
+    this.astVisitor.visit(node.valueNode);
+  }
+  visitGlobal(node: Global): void {
+    this.write("Global: ");
+    this.visitNode(node.declaration);
+    // this.astVisitor.visit(node.identifierNode);
+    // this.visitNode(node.typeNode);
+    // this.visitNode(node.initializerNode);
+    // this.astVisitor.write(this.astVisitor.flush(": "));
+  }
+  visitLocal(node: Local): void {
+    this.write("Local: " + node.name, true);
+    this.visitNode(node.identifierNode);
+    this.visitNode(node.initializerNode);
+  }
+  visitFunctionPrototype(node: FunctionPrototype): void {
+    this.write("Function ProtoType:" + node.signature);
+    super.visitFunctionPrototype(node);
+  }
+  visitFunction(node: Function): void {
+    this.write("visiting function: " + node.name);
+    this.write(node.signature.toString(), true);
+    // this.write(node.toString());
+    // if(mems)
+    // for (let mem of mems.values()){
+    //     this.write(mem.toString(), true)
+    // }
+  }
+  visitFunctionTarget(node: FunctionTarget): void {}
+  visitFieldPrototype(node: FieldPrototype): void {}
+  visitField(node: Field): void {}
+  visitPropertyPrototype(node: PropertyPrototype): void {}
+  visitProperty(node: Property): void {}
+  visitClassPrototype(node: ClassPrototype): void {
+    super.visitClassPrototype(node);
+    this.write("", true);
+  }
+  visitClass(node: Class): void {
+    this.write(node.name);
+    // this.write(node.members!.size.toString());
+    let interfaces = (<ClassDeclaration>node.declaration).implementsTypes;
+    if (interfaces) {
+      this.write("implements " + interfaces.join(", "));
+    }
+    this.write("", true);
+    this.visit(node.members);
+  }
+  visitInterfacePrototype(node: InterfacePrototype): void {
+    this.write("Interface Prototype: ");
+    this.write(node.name, true);
+    super.visitInterfacePrototype(node);
+  }
+
+  visitInterface(node: Interface): void {
+    this.write("Interface: " + node.name);
+    super.visitInterface(node);
+    // for (let [key, value] of node.members!.entries()) {
+    //   this.write(key + " " + value.toString());
+    // }
+  }
+}
diff --git a/lib/visitor/src/instances/printIds.ts b/lib/visitor/src/instances/printIds.ts
new file mode 100644
index 0000000000..e76d983fec
--- /dev/null
+++ b/lib/visitor/src/instances/printIds.ts
@@ -0,0 +1,45 @@
+import {
+  ElementVisitor,
+  Class,
+  Compiler,
+  Parser,
+  Field,
+  Property
+} from "assemblyscript";
+
+import { BaseElementVisitor } from "../element";
+
+export default class PrintIDs extends BaseElementVisitor {
+  seen: Set<Class> = new Set();
+
+  start(): void {
+    this.visitManagedClasses(this.files);
+  }
+
+  write(str: string, newline: boolean = false): void {
+    this.writer.write(str + (newline ? "\n" : " "));
+  }
+
+  visitClass(node: Class): void {
+    if (this.seen.has(node)) {
+      return;
+    }
+    this.seen.add(node);
+    this.write(node.name + ": " + node.id.toString(), true);
+    this.visit(node.members);
+  }
+
+  visitField(node: Field): void {
+    this.write(
+      "  Field:\t" + node.name + ": " + node.typeNode!.toString(),
+      true
+    );
+  }
+
+  visitProperty(node: Property): void {
+    let typeName = node.typeNode
+      ? node.typeNode.toString()
+      : node.type.toString();
+    this.write("  Property:\t" + node.name + ": " + typeName, true);
+  }
+}
diff --git a/lib/visitor/src/instances/virtual.ts b/lib/visitor/src/instances/virtual.ts
new file mode 100644
index 0000000000..32d8680783
--- /dev/null
+++ b/lib/visitor/src/instances/virtual.ts
@@ -0,0 +1,244 @@
+import {
+  ElementVisitor,
+  File,
+  TypeDefinition,
+  Namespace,
+  Enum,
+  EnumValue,
+  Global,
+  Local,
+  FunctionPrototype,
+  FunctionTarget,
+  FieldPrototype,
+  Field,
+  PropertyPrototype,
+  Property,
+  ClassPrototype,
+  Class,
+  InterfacePrototype,
+  Interface,
+  Function,
+  Program,
+  Compiler,
+  IdentifierExpression,
+  FunctionDeclaration,
+  ClassDeclaration,
+  Parser,
+  BinaryOp,
+  NativeType,
+  Signature,
+  ElementKind,
+  TypeFlags
+} from "assemblyscript";
+import { BaseElementVisitor } from "../element";
+import { PrinterVisitor } from "./astPrinter";
+import { ASTVisitor } from "../ast";
+import { Writer } from "..";
+
+type memberid = number;
+type classid = number;
+type fnPtr = number;
+
+type virtualMethod = [classid, fnPtr];
+
+export default class Virtualizer extends BaseElementVisitor
+  implements ElementVisitor {
+  interfaceMethods: Map<string, memberid> = new Map();
+  classIds: Map<memberid, virtualMethod[]> = new Map();
+  log = false;
+
+  constructor(parser: Parser, compiler: Compiler, writer: Writer) {
+    super(parser, compiler, writer);
+    debugger;
+  }
+
+  start(): void {
+    var compiler = this.compiler;
+    this.astVisitor = new PrinterVisitor(this.parser, this.writer);
+    this.visitInterfaces(this.files);
+
+    var managedClasses = [];
+    for (let _class of compiler.program.managedClasses.values()) {
+      managedClasses.push(_class.id);
+      if (!_class.file.name.startsWith("~") && _class.prototype.implementsNodes != null) {
+        _class.visit(this);
+      }
+    }
+    this.write(this.compiler.functionTable.join(" "), true);
+    this.createVitualFunction();
+    var module = compiler.module;
+
+    const updateInterfaceMethods = (i: InterfacePrototype): void => {
+      if (i.instanceMembers == null) return;
+      for (let member of i.instanceMembers.values()) {
+        if (member.kind != ElementKind.FUNCTION_PROTOTYPE) continue;
+        let func: Function = this.getFunctionByName(member.internalName);
+        let signature = func.signature;
+        let _type = this.compiler.ensureFunctionType(
+          signature.parameterTypes,
+          signature.returnType,
+          signature.thisType
+        );
+        let loadMethodID = module.i32(
+          this.interfaceMethods.get(func.prototype.signature)!
+        );
+        // let target = this.compiler.program.instancesByName("virtual");
+        let loadClass = module.load(
+          4,
+          false,
+          module.binary(
+            BinaryOp.SubI32,
+            module.local_get(0, NativeType.I32),
+            module.i32(8)
+          ),
+          NativeType.I32
+        );
+        let callVirtual = module.call(
+          "~lib/virtual/virtual",
+          [loadMethodID, loadClass],
+          NativeType.I32
+        );
+        module.removeFunction(member.internalName);
+        
+        let callIndirect = module.call_indirect(
+          callVirtual,
+          func.localsByIndex.map<number>(local => module.local_get(local.index, local.type.toNativeType())),
+
+          Signature.makeSignatureString(
+            func.signature.parameterTypes,
+            func.signature.returnType,
+            func.signature.thisType
+          ));
+
+        let body = module.block(null ,[ callIndirect ], func.signature.returnType.toNativeType());
+
+        module.addFunction(
+          member.internalName,
+          _type,
+          null,
+          body
+        );
+      }
+      debugger;
+    };
+
+    try {
+      this.visitInterfaces(this.files, updateInterfaceMethods);
+    } catch (e) {
+      this.write(e.toString());
+    }
+  }
+
+  createVitualFunction(): void {
+    var module = this.compiler.module;
+    var functionTable = this.compiler.functionTable;
+    module.setFunctionTable(functionTable.length, 0xffffffff, functionTable);
+    this.write(functionTable.join("\n"), true);
+    let methodIDCases = [];
+    let dummyMethodId: number=0, dummyClassid : number = 0;
+    for (let [id, classes] of this.classIds.entries()) {
+      let str = ["case ", id.toString(), ": {\n\tswitch (classID) {\n"];
+      dummyMethodId = id;
+      for (let [classID, fnPtr] of classes) {
+        dummyClassid = classID;
+        str.push("\t\tcase " + classID.toString() + ": return ");
+        str.push(fnPtr.toString() + ";\n");
+      }
+      str.push("\t}");
+      str.push("\n}");
+      methodIDCases.push(str.join(""));
+    }
+
+    var funcSourc = `
+      @global
+      function virtual(methodID: usize, classID: usize): usize {
+        switch (methodID){
+           ${methodIDCases.join("")}
+        }
+        unreachable();
+        return 0;
+      }
+      virtual(${dummyMethodId}, ${dummyClassid});
+      `;
+    this.parser.parseFile(funcSourc, "~lib/virtual", false);
+    this.parser.program.initialize(this.compiler.options);
+    var sources = this.parser.program.sources;
+    var file: File = new File(this.parser.program, sources[sources.length - 1]);
+    this.parser.program.initializeFunction(
+      <FunctionDeclaration>file.source.statements[0],
+      file
+    );
+    this.compiler.compileFile(file);
+    // this.compiler.module.removeFunction("~lib/virtual");
+  }
+
+  write(str: string, newline: boolean = false): void {
+    if (this.log) {
+      this.writer.write(str + (newline ? "\n" : " "));
+    }
+  }
+
+  visitFunctionPrototype(node: FunctionPrototype): void {
+    if (node.isBound) {
+      let _class = <Class> node.parent;
+      let signature = node.signature;
+      let id = this.interfaceMethods.get(signature);
+      if (id != null) {
+        let classId = _class.id;
+        this.write("Parent: " + _class.name, true);
+        this.write("visiting function " + node.internalName, false);
+        this.write(signature + " has methodID: " + id, true);
+        let fnPtr = this.compiler.functionTable.length;
+        this.compiler.functionTable.push(node.internalName);
+        let entry: virtualMethod = [classId, fnPtr];
+        this.classIds.get(id)!.push(entry);
+        // let funcPtr = this.compiler.ensureFunctionTableEntry(this.compiler.program.instancesByName)
+      }
+    }
+  }
+  visitFunction(node: Function): void {
+    this.write("visiting function: " + node.name);
+    this.write(node.signature.toString(), true);
+  }
+  visitFunctionTarget(node: FunctionTarget): void {}
+  visitFieldPrototype(node: FieldPrototype): void {}
+  visitField(node: Field): void {}
+  visitPropertyPrototype(node: PropertyPrototype): void {}
+  visitProperty(node: Property): void {}
+  visitClassPrototype(node: ClassPrototype): void {}
+  visitClass(node: Class): void {
+    this.write(node.name);
+    // this.write(node.members!.size.toString());
+    var interfaces = (<ClassDeclaration>node.declaration).implementsTypes;
+    if (interfaces) {
+      this.write("implements " + interfaces.join(", "));
+    }
+    this.write("", true);
+    for (let mem of node.members!.values()) {
+      mem.visit(this);
+    }
+  }
+  visitInterfacePrototype(node: InterfacePrototype): void {
+    this.write("Interface Prototype", true);
+    this.write(node.name);
+    for (let [key, value] of node.instanceMembers!.entries()) {
+      if (value instanceof FunctionPrototype) {
+        this.write(key + " " + value.toString());
+        let id = this.interfaceMethods.size;
+        if (!this.interfaceMethods.has(value.signature)) {
+          this.interfaceMethods.set(value.signature, id);
+          this.classIds.set(id, []);
+          this.write(value.signature, true);
+        }
+      }
+    }
+    this.write("", true);
+  }
+
+  visitInterface(node: Interface): void {
+    this.write(node.name);
+    for (let [key, value] of node.members!.entries()) {
+      this.write(key + " " + value.toString());
+    }
+  }
+}
diff --git a/lib/visitor/src/tsconfig.json b/lib/visitor/src/tsconfig.json
new file mode 100644
index 0000000000..9d9fce1a75
--- /dev/null
+++ b/lib/visitor/src/tsconfig.json
@@ -0,0 +1,11 @@
+{
+  "extends": "../node_modules/assemblyscript/std/portable.json",
+  "compilerOptions": {
+    "outDir": "../dist",
+    "noLib": true,
+    "noEmit": true,
+    "inlineSourceMap": true,
+    "inlineSources": true
+  }
+  // "exclude": ["assemblyscript/src/**/*.ts"]
+}
diff --git a/lib/visitor/src/visitor.ts b/lib/visitor/src/visitor.ts
new file mode 100644
index 0000000000..2ddb5f9fe7
--- /dev/null
+++ b/lib/visitor/src/visitor.ts
@@ -0,0 +1,85 @@
+export interface Visitor<T> {
+  visit(t: Collection<T>): void;
+}
+
+interface Visit<T> {
+    visit(visitor: any): void;
+}
+
+type Functor<T> = (node: T) => T;
+
+function id<T>(t: T): T{
+  return t;
+}
+
+export type Collection<T> = T | T[] | Map<string, T> | Iterable<T> | null;
+
+const isIterable = (object: object): boolean =>
+  //@ts-ignore
+  object != null && typeof object[Symbol.iterator] === "function";
+
+export abstract class AbstractVisitor<T extends Visit<T>> {
+
+  constructor(private func: Functor<T> = id) {}
+
+  visit(node: Collection<T>): void {
+    if (node) {
+      if (node instanceof Array) {
+        node.map(node => this.visit(node));
+      } else if (node instanceof Map) {
+        this.visit(node.values());
+      } else if (isIterable(node)) {
+          //TODO: Find better way to test if iterable
+        for (let n of node) {
+            this.visit(n);
+          }
+      }else {
+        (<T>node).visit(this);
+      }
+    }
+  }
+
+  abstract start(): void;
+
+}
+
+// interface NodeVisitor extends Visit<testNode> {
+//     visitNode(t: testNode):void
+// }
+
+// class testNode implements Visit<testNode> {
+//   constructor(private name: string) {}
+
+//   visit(visitor: NodeVisitor): void {
+//     // console.log("in" + this.name);
+//     debugger;
+//     visitor.visitNode(this)
+//   }
+// }
+
+
+// class Base extends AbstractVisitor<testNode> implements NodeVisitor {
+//     visitNode(t: testNode): void {
+//         console.log("in super")
+//     }
+// }
+
+// class Sub extends Base implements NodeVisitor {
+//     visitNode(t: testNode): void {
+//         console.log("in child");
+//         super.visitNode(t);
+//     }
+// }
+
+
+// let test = new Sub();
+// let node = new testNode("one");
+// let node2 = new testNode("two");
+// let node3 = new testNode("three");
+
+// let map = new Map([["one", node], ["two", node2], ["three", node3]]);
+// let values = map.values();
+// debugger;
+// test.visit([node, node2, node3]);
+// test.visit(map);
+// test.visit(values);
diff --git a/lib/visitor/tsconfig.json b/lib/visitor/tsconfig.json
new file mode 100644
index 0000000000..06fbad66f7
--- /dev/null
+++ b/lib/visitor/tsconfig.json
@@ -0,0 +1,10 @@
+{
+  "extends": "./node_modules/assemblyscript/std/portable.json",
+  "compilerOptions": {
+    "outDir": "./dist",
+    "inlineSourceMap": true,
+    "inlineSources": true,
+    "noLib": true
+  },
+  "include": ["src/instances/**/*.ts"],
+}
diff --git a/scripts/build-dts.js b/scripts/build-dts.js
index d301245153..637cd671c5 100644
--- a/scripts/build-dts.js
+++ b/scripts/build-dts.js
@@ -408,17 +408,116 @@
     exports.default = generate;
 });
 
-const prelude = `declare type bool = boolean;
-declare type i8 = number;
-declare type i16 = number;
-declare type i32 = number;
-declare type isize = number;
-declare type u8 = number;
-declare type u16 = number;
-declare type u32 = number;
-declare type usize = number;
-declare type f32 = number;
-declare type f64 = number;
+const prelude = `
+declare module "assemblyscript/std/assembly/shared/feature"{
+    // This file is shared with the compiler and must remain portable
+
+    /** Indicates specific features to activate. */
+    export const enum Feature {
+        /** No additional features. */
+        NONE = 0,
+        /** Sign extension operations. */
+        SIGN_EXTENSION = 1 << 0, // see: https://github.com/WebAssembly/sign-extension-ops
+        /** Mutable global imports and exports. */
+        MUTABLE_GLOBAL = 1 << 1, // see: https://github.com/WebAssembly/mutable-global
+        /** Bulk memory operations. */
+        BULK_MEMORY = 1 << 2, // see: https://github.com/WebAssembly/bulk-memory-operations
+        /** SIMD types and operations. */
+        SIMD = 1 << 3, // see: https://github.com/WebAssembly/simd
+        /** Threading and atomic operations. */
+        THREADS = 1 << 4 // see: https://github.com/WebAssembly/threads
+    }
+    // This file is shared with the compiler and must remain portable
+}
+
+declare module "assemblyscript/std/assembly/shared/target"{
+/** Compilation target. */
+export enum Target {
+    /** WebAssembly with 32-bit pointers. */
+    WASM32,
+    /** WebAssembly with 64-bit pointers. Experimental and not supported by any runtime yet. */
+    WASM64,
+    /** Portable. */
+    JS
+  }
+}
+declare module "assemblyscript/std/assembly/shared/typeinfo"{
+  // This file is shared with the compiler and must remain portable
+
+// ╒═══════════════════ Typeinfo interpretation ═══════════════════╕
+//    3                   2                   1
+//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0  bits
+// ├─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┤ ◄─ __rtti_base
+// │                             count                             │
+// ╞═══════════════════════════════════════════════════════════════╡ ┐
+// │                      Typeinfo#flags [id=0]                    │ id < count
+// ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
+// │                      Typeinfo#base  [id=0]                    │
+// ├───────────────────────────────────────────────────────────────┤
+// │                              ...                              │
+
+/** Runtime type information data structure. */
+//@ts-ignore 
+@unmanaged
+export class Typeinfo {
+  /** Flags describing the shape of this class type. */
+  flags: TypeinfoFlags;
+  /** Base class id or \`0\` if none. */
+  base: u32;
+}
+
+/** Runtime type information flags. */
+export const enum TypeinfoFlags {
+  /** No specific flags. */
+  NONE = 0,
+  /** Type is an \`ArrayBufferView\`. */
+  ARRAYBUFFERVIEW = 1 << 0,
+  /** Type is an \`Array\`. */
+  ARRAY = 1 << 1,
+  /** Type is a \`Set\`. */
+  SET = 1 << 2,
+  /** Type is a \`Map\`. */
+  MAP = 1 << 3,
+  /** Type is inherently acyclic. */
+  ACYCLIC = 1 << 4,
+  /** Value alignment of 1 byte. */
+  VALUE_ALIGN_0 = 1 << 5,
+  /** Value alignment of 2 bytes. */
+  VALUE_ALIGN_1 = 1 << 6,
+  /** Value alignment of 4 bytes. */
+  VALUE_ALIGN_2 = 1 << 7,
+  /** Value alignment of 8 bytes. */
+  VALUE_ALIGN_3 = 1 << 8,
+  /** Value alignment of 16 bytes. */
+  VALUE_ALIGN_4 = 1 << 9,
+  /** Value is a signed type. */
+  VALUE_SIGNED = 1 << 10,
+  /** Value is a float type. */
+  VALUE_FLOAT = 1 << 11,
+  /** Value type is nullable. */
+  VALUE_NULLABLE = 1 << 12,
+  /** Value type is managed. */
+  VALUE_MANAGED = 1 << 13,
+  /** Key alignment of 1 byte. */
+  KEY_ALIGN_0 = 1 << 14,
+  /** Key alignment of 2 bytes. */
+  KEY_ALIGN_1 = 1 << 15,
+  /** Key alignment of 4 bytes. */
+  KEY_ALIGN_2 = 1 << 16,
+  /** Key alignment of 8 bytes. */
+  KEY_ALIGN_3 = 1 << 17,
+  /** Key alignment of 16 bytes. */
+  KEY_ALIGN_4 = 1 << 18,
+  /** Key is a signed type. */
+  KEY_SIGNED = 1 << 19,
+  /** Key is a float type. */
+  KEY_FLOAT = 1 << 20,
+  /** Key type is nullable. */
+  KEY_NULLABLE = 1 << 21,
+  /** Key type is managed. */
+  KEY_MANAGED = 1 << 22
+}
+}
 declare module 'assemblyscript' {
   export * from 'assemblyscript/src/index';
 }
diff --git a/src/ast.ts b/src/ast.ts
index d4f091f06b..2eaa59f3a8 100644
--- a/src/ast.ts
+++ b/src/ast.ts
@@ -144,6 +144,9 @@ export abstract class Node {
   /** Source range. */
   range: Range;
 
+  // visit method each concrete node must implement
+  abstract visit(vistor: ASTVisitor): void;
+
   // types
 
   static createTypeName(
@@ -1087,6 +1090,8 @@ export abstract class TypeNode extends Node {
 
   /** Whether nullable or not. */
   isNullable: bool;
+
+  abstract toString(): string;
 }
 
 /** Represents a type name. */
@@ -1097,6 +1102,20 @@ export class TypeName extends Node {
   identifier: IdentifierExpression;
   /** Next part of the type name or `null` if this is the last part. */
   next: TypeName | null;
+
+  toString(): string {
+    var res = [this.identifier.symbol];
+    var curr = this.next;
+    while (curr != null) {
+      res.push(curr.identifier.symbol);
+      curr = curr.next;
+    }
+    return res.join("-");
+  }
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitTypeName(this);
+  }
 }
 
 /** Represents a named type. */
@@ -1107,6 +1126,20 @@ export class NamedTypeNode extends TypeNode {
   name: TypeName;
   /** Type argument references. */
   typeArguments: TypeNode[] | null;
+
+  toString(): string {
+    var res = this.name.toString();
+    var toString = (arg: TypeNode): string => arg.toString();
+    if (this.typeArguments && this.typeArguments.length > 0) {
+      res +=
+        "<" + this.typeArguments.map(toString).join(", ") + ">";
+    }
+    return res;
+  }
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitNamedTypeNode(this);
+  }
 }
 
 /** Represents a function type. */
@@ -1119,6 +1152,17 @@ export class FunctionTypeNode extends TypeNode {
   returnType: TypeNode;
   /** Explicitly provided this type, if any. */
   explicitThisType: NamedTypeNode | null; // can't be a function
+
+  toString(): string {
+    function toString(p: ParameterNode): string { return p.type.toString(); }
+    var params = this.parameters.map<string>(toString);
+    var res = "(" + params.join(",") + ")";
+    return res + "->" + this.returnType.toString();
+  }
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitFunctionTypeNode(this);
+  }
 }
 
 /** Represents a type parameter. */
@@ -1131,6 +1175,10 @@ export class TypeParameterNode extends Node {
   extendsType: NamedTypeNode | null; // can't be a function
   /** Default type if omitted, if any. */
   defaultType: NamedTypeNode | null; // can't be a function
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitTypeParameter(this);
+  }
 }
 
 /** Represents the kind of a parameter. */
@@ -1166,6 +1214,10 @@ export class ParameterNode extends Node {
   isAny(flag: CommonFlags): bool { return (this.flags & flag) != 0; }
   /** Sets a specific flag or flags. */
   set(flag: CommonFlags): void { this.flags |= flag; }
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitParameter(this);
+  }
 }
 
 // special
@@ -1266,6 +1318,10 @@ export class DecoratorNode extends Node {
   name: Expression;
   /** Argument expressions. */
   arguments: Expression[] | null;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitDecoratorNode(this);
+  }
 }
 
 /** Comment kinds. */
@@ -1286,6 +1342,10 @@ export class CommentNode extends Node {
   commentKind: CommentKind;
   /** Comment text. */
   text: string;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitComment(this);
+  }
 }
 
 // expressions
@@ -1303,6 +1363,9 @@ export class IdentifierExpression extends Expression {
   symbol: string; // TODO: symbol
   /** Whether quoted or not. */
   isQuoted: bool;
+  visit(visitor: ASTVisitor): void {
+    visitor.visitIdentifierExpression(this);
+  }
 }
 
 /** Indicates the kind of a literal. */
@@ -1321,6 +1384,10 @@ export abstract class LiteralExpression extends Expression {
 
   /** Specific literal kind. */
   literalKind: LiteralKind;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitLiteralExpression(this);
+  }
 }
 
 /** Represents an `[]` literal expression. */
@@ -1329,6 +1396,10 @@ export class ArrayLiteralExpression extends LiteralExpression {
 
   /** Nested element expressions. */
   elementExpressions: (Expression | null)[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitArrayLiteralExpression(this);
+  }
 }
 
 /** Indicates the kind of an assertion. */
@@ -1348,6 +1419,10 @@ export class AssertionExpression extends Expression {
   expression: Expression;
   /** Target type. */
   toType: TypeNode | null;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitAssertionExpression(this);
+  }
 }
 
 /** Represents a binary expression. */
@@ -1360,6 +1435,10 @@ export class BinaryExpression extends Expression {
   left: Expression;
   /** Right-hand side expression. */
   right: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitBinaryExpression(this);
+  }
 }
 
 /** Represents a call expression. */
@@ -1392,6 +1471,10 @@ export class CallExpression extends Expression {
     }
     return this.expression.range;
   }
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitCallExpression(this);
+  }
 }
 
 /** Represents a class expression using the 'class' keyword. */
@@ -1400,6 +1483,10 @@ export class ClassExpression extends Expression {
 
   /** Inline class declaration. */
   declaration: ClassDeclaration;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitClassExpression(this);
+  }
 }
 
 /** Represents a comma expression composed of multiple expressions. */
@@ -1408,6 +1495,10 @@ export class CommaExpression extends Expression {
 
   /** Sequential expressions. */
   expressions: Expression[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitCommaExpression(this);
+  }
 }
 
 /** Represents a `constructor` expression. */
@@ -1415,6 +1506,10 @@ export class ConstructorExpression extends IdentifierExpression {
   kind = NodeKind.CONSTRUCTOR;
   text = "constructor";
   symbol = CommonSymbols.constructor;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitConstructorExpression(this);
+  }
 }
 
 /** Represents an element access expression, e.g., array access. */
@@ -1425,6 +1520,10 @@ export class ElementAccessExpression extends Expression {
   expression: Expression;
   /** Element of the expression being accessed. */
   elementExpression: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitElementAccessExpression(this);
+  }
 }
 
 /** Represents a float literal expression. */
@@ -1433,6 +1532,10 @@ export class FloatLiteralExpression extends LiteralExpression {
 
   /** Float value. */
   value: f64;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitFloatLiteralExpression(this);
+  }
 }
 
 /** Represents a function expression using the 'function' keyword. */
@@ -1441,6 +1544,10 @@ export class FunctionExpression extends Expression {
 
   /** Inline function declaration. */
   declaration: FunctionDeclaration;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitFunctionExpression(this);
+  }
 }
 
 /** Represents an `instanceof` expression. */
@@ -1451,6 +1558,10 @@ export class InstanceOfExpression extends Expression {
   expression: Expression;
   /** Type to test for. */
   isType: TypeNode;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitInstanceOfExpression(this);
+  }
 }
 
 /** Represents an integer literal expression. */
@@ -1459,11 +1570,19 @@ export class IntegerLiteralExpression extends LiteralExpression {
 
   /** Integer value. */
   value: I64;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitIntegerLiteralExpression(this);
+  }
 }
 
 /** Represents a `new` expression. Like a call but with its own kind. */
 export class NewExpression extends CallExpression {
   kind = NodeKind.NEW;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitNewExpression(this);
+  }
 }
 
 /** Represents a `null` expression. */
@@ -1471,6 +1590,10 @@ export class NullExpression extends IdentifierExpression {
   kind = NodeKind.NULL;
   text = "null";
   symbol = CommonSymbols.null_;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitNullExperssion(this);
+  }
 }
 
 /** Represents an object literal expression. */
@@ -1481,6 +1604,10 @@ export class ObjectLiteralExpression extends LiteralExpression {
   names: IdentifierExpression[];
   /** Field values. */
   values: Expression[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitObjectLiteralExpression(this);
+  }
 }
 
 /** Represents a parenthesized expression. */
@@ -1489,6 +1616,10 @@ export class ParenthesizedExpression extends Expression {
 
   /** Expression in parenthesis. */
   expression: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitParenthesizedExpression(this);
+  }
 }
 
 /** Represents a property access expression. */
@@ -1499,6 +1630,10 @@ export class PropertyAccessExpression extends Expression {
   expression: Expression;
   /** Property of the expression being accessed. */
   property: IdentifierExpression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitPropertyAccessExpression(this);
+  }
 }
 
 /** Represents a regular expression literal expression. */
@@ -1509,6 +1644,10 @@ export class RegexpLiteralExpression extends LiteralExpression {
   pattern: string;
   /** Regular expression flags. */
   patternFlags: string;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitRegexpLiteralExpression(this);
+  }
 }
 
 /** Represents a ternary expression, i.e., short if notation. */
@@ -1521,6 +1660,10 @@ export class TernaryExpression extends Expression {
   ifThen: Expression;
   /** Expression executed when condition is `false`. */
   ifElse: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitTernaryExpression(this);
+  }
 }
 
 /** Represents a string literal expression. */
@@ -1529,6 +1672,10 @@ export class StringLiteralExpression extends LiteralExpression {
 
   /** String value without quotes. */
   value: string;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitStringLiteralExpression(this);
+  }
 }
 
 /** Represents a `super` expression. */
@@ -1536,6 +1683,10 @@ export class SuperExpression extends IdentifierExpression {
   kind = NodeKind.SUPER;
   text = "super";
   symbol = CommonSymbols.super_;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitSuperExpression(this);
+  }
 }
 
 /** Represents a `this` expression. */
@@ -1543,6 +1694,10 @@ export class ThisExpression extends IdentifierExpression {
   kind = NodeKind.THIS;
   text = "this";
   symbol = CommonSymbols.this_;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitThisExpression(this);
+  }
 }
 
 /** Represents a `true` expression. */
@@ -1550,6 +1705,10 @@ export class TrueExpression extends IdentifierExpression {
   kind = NodeKind.TRUE;
   text = "true";
   symbol = CommonSymbols.true_;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitTrueExpression(this);
+  }
 }
 
 /** Represents a `false` expression. */
@@ -1557,6 +1716,10 @@ export class FalseExpression extends IdentifierExpression {
   kind = NodeKind.FALSE;
   text = "false";
   symbol = CommonSymbols.false_;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitFalseExpression(this);
+  }
 }
 
 /** Base class of all unary expressions. */
@@ -1566,16 +1729,28 @@ export abstract class UnaryExpression extends Expression {
   operator: Token;
   /** Operand expression. */
   operand: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitUnaryExpression(this);
+  }
 }
 
 /** Represents a unary postfix expression, e.g. a postfix increment. */
 export class UnaryPostfixExpression extends UnaryExpression {
   kind = NodeKind.UNARYPOSTFIX;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitUnaryPostfixExpression(this);
+  }
 }
 
 /** Represents a unary prefix expression, e.g. a negation. */
 export class UnaryPrefixExpression extends UnaryExpression {
   kind = NodeKind.UNARYPREFIX;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitUnaryPrefixExpression(this);
+  }
 }
 
 // statements
@@ -1633,10 +1808,17 @@ export class Source extends Node {
     this.text = text;
   }
 
+  /** Tests if this source is an entry file. */
+  get isEntry(): bool { return this.sourceKind == SourceKind.LIBRARY_ENTRY || this.sourceKind == SourceKind.USER_ENTRY; }
+  /** Tests if this source is a stdlib file. */
   get isLibrary(): bool {
     var kind = this.sourceKind;
     return kind == SourceKind.LIBRARY || kind == SourceKind.LIBRARY_ENTRY;
   }
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitSource(this);
+  }
 }
 
 /** Base class of all declaration statements. */
@@ -1664,6 +1846,10 @@ export class IndexSignatureDeclaration extends DeclarationStatement {
   keyType: NamedTypeNode;
   /** Value type. */
   valueType: TypeNode;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitIndexSignatureDeclaration(this);
+  }
 }
 
 /** Base class of all variable-like declaration statements. */
@@ -1681,6 +1867,10 @@ export class BlockStatement extends Statement {
 
   /** Contained statements. */
   statements: Statement[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitBlockStatement(this);
+  }
 }
 
 /** Represents a `break` statement. */
@@ -1689,6 +1879,10 @@ export class BreakStatement extends Statement {
 
   /** Target label, if applicable. */
   label: IdentifierExpression | null;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitBreakStatement(this);
+  }
 }
 
 /** Represents a `class` declaration. */
@@ -1708,6 +1902,10 @@ export class ClassDeclaration extends DeclarationStatement {
     var typeParameters = this.typeParameters;
     return typeParameters != null && typeParameters.length > 0;
   }
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitClassDeclaration(this);
+  }
 }
 
 /** Represents a `continue` statement. */
@@ -1716,6 +1914,10 @@ export class ContinueStatement extends Statement {
 
   /** Target label, if applicable. */
   label: IdentifierExpression | null;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitContinueStatement(this);
+  }
 }
 
 /** Represents a `do` statement. */
@@ -1726,11 +1928,19 @@ export class DoStatement extends Statement {
   statement: Statement;
   /** Condition when to repeat. */
   condition: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitDoStatement(this);
+  }
 }
 
 /** Represents an empty statement, i.e., a semicolon terminating nothing. */
 export class EmptyStatement extends Statement {
   kind = NodeKind.EMPTY;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitEmptyStatement(this);
+  }
 }
 
 /** Represents an `enum` declaration. */
@@ -1739,6 +1949,10 @@ export class EnumDeclaration extends DeclarationStatement {
 
   /** Enum value declarations. */
   values: EnumValueDeclaration[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitEnumDeclaration(this);
+  }
 }
 
 /** Represents a value of an `enum` declaration. */
@@ -1748,6 +1962,10 @@ export class EnumValueDeclaration extends VariableLikeDeclarationStatement {
 
   /** Value expression. */
   value: Expression | null;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitEnumValueDeclaration(this);
+  }
 }
 
 /** Represents an `export import` statement of an interface. */
@@ -1758,6 +1976,10 @@ export class ExportImportStatement extends Node {
   name: IdentifierExpression;
   /** Identifier being exported. */
   externalName: IdentifierExpression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitExportImportStatement(this);
+  }
 }
 
 /** Represents a member of an `export` statement. */
@@ -1768,6 +1990,10 @@ export class ExportMember extends Node {
   localName: IdentifierExpression;
   /** Exported identifier. */
   exportedName: IdentifierExpression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitExportMember(this);
+  }
 }
 
 /** Represents an `export` statement. */
@@ -1784,6 +2010,10 @@ export class ExportStatement extends Statement {
   internalPath: string | null;
   /** Whether this is a declared export. */
   isDeclare: bool;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitExportStatement(this);
+  }
 }
 
 /** Represents an `export default` statement. */
@@ -1792,6 +2022,10 @@ export class ExportDefaultStatement extends Statement {
 
   /** Declaration being exported as default. */
   declaration: DeclarationStatement;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitExportDefaultStatement(this);
+  }
 }
 
 /** Represents an expression that is used as a statement. */
@@ -1800,6 +2034,10 @@ export class ExpressionStatement extends Statement {
 
   /** Expression being used as a statement.*/
   expression: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitExpressionStatement(this);
+  }
 }
 
 /** Represents a field declaration within a `class`. */
@@ -1808,6 +2046,10 @@ export class FieldDeclaration extends VariableLikeDeclarationStatement {
 
   /** Parameter index if declared as a constructor parameter, otherwise `-1`. */
   parameterIndex: i32 = -1;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitFieldDeclaration(this);
+  }
 }
 
 /** Represents a `for` statement. */
@@ -1825,6 +2067,10 @@ export class ForStatement extends Statement {
   incrementor: Expression | null;
   /** Statement being looped over. */
   statement: Statement;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitForStatement(this);
+  }
 }
 
 /** Indicates the kind of an array function. */
@@ -1868,6 +2114,10 @@ export class FunctionDeclaration extends DeclarationStatement {
       this.range
     );
   }
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitFunctionDeclaration(this);
+  }
 }
 
 /** Represents an `if` statement. */
@@ -1880,6 +2130,10 @@ export class IfStatement extends Statement {
   ifTrue: Statement;
   /** Statement executed when condition is `false`. */
   ifFalse: Statement | null;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitIfStatement(this);
+  }
 }
 
 /** Represents an `import` declaration part of an {@link ImportStatement}. */
@@ -1888,6 +2142,10 @@ export class ImportDeclaration extends DeclarationStatement {
 
   /** Identifier being imported. */
   foreignName: IdentifierExpression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitImportDeclaration(this);
+  }
 }
 
 /** Represents an `import` statement. */
@@ -1904,16 +2162,28 @@ export class ImportStatement extends Statement {
   normalizedPath: string;
   /** Mangled internal path being referenced. */
   internalPath: string;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitImportStatement(this);
+  }
 }
 
 /** Represents an `interfarce` declaration. */
 export class InterfaceDeclaration extends ClassDeclaration {
   kind = NodeKind.INTERFACEDECLARATION;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitInterfaceDeclaration(this);
+  }
 }
 
 /** Represents a method declaration within a `class`. */
 export class MethodDeclaration extends FunctionDeclaration {
   kind = NodeKind.METHODDECLARATION;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitMethodDeclaration(this);
+  }
 }
 
 /** Represents a `namespace` declaration. */
@@ -1922,6 +2192,10 @@ export class NamespaceDeclaration extends DeclarationStatement {
 
   /** Array of namespace members. */
   members: Statement[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitNamespaceDeclaration(this);
+  }
 }
 
 /** Represents a `return` statement. */
@@ -1930,6 +2204,10 @@ export class ReturnStatement extends Statement {
 
   /** Value expression being returned, if present. */
   value: Expression | null;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitReturnStatement(this);
+  }
 }
 
 /** Represents a single `case` within a `switch` statement. */
@@ -1940,6 +2218,10 @@ export class SwitchCase extends Node {
   label: Expression | null;
   /** Contained statements. */
   statements: Statement[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitSwitchCase(this);
+  }
 }
 
 /** Represents a `switch` statement. */
@@ -1950,6 +2232,10 @@ export class SwitchStatement extends Statement {
   condition: Expression;
   /** Contained cases. */
   cases: SwitchCase[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitSwitchStatement(this);
+  }
 }
 
 /** Represents a `throw` statement. */
@@ -1958,6 +2244,10 @@ export class ThrowStatement extends Statement {
 
   /** Value expression being thrown. */
   value: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitThrowStatement(this);
+  }
 }
 
 /** Represents a `try` statement. */
@@ -1972,6 +2262,10 @@ export class TryStatement extends Statement {
   catchStatements: Statement[] | null;
   /** Statements being executed afterwards, if a `finally` clause is present. */
   finallyStatements: Statement[] | null;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitTryStatement(this);
+  }
 }
 
 /** Represents a `type` declaration. */
@@ -1982,11 +2276,19 @@ export class TypeDeclaration extends DeclarationStatement {
   typeParameters: TypeParameterNode[] | null;
   /** Type being aliased. */
   type: TypeNode;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitTypeDeclaration(this);
+  }
 }
 
 /** Represents a variable declaration part of a {@link VariableStatement}. */
 export class VariableDeclaration extends VariableLikeDeclarationStatement {
   kind = NodeKind.VARIABLEDECLARATION;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitVariableDeclaration(this);
+  }
 }
 
 /** Represents a variable statement wrapping {@link VariableDeclaration}s. */
@@ -1997,6 +2299,10 @@ export class VariableStatement extends Statement {
   decorators: DecoratorNode[] | null;
   /** Array of member declarations. */
   declarations: VariableDeclaration[];
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitVariableStatement(this);
+  }
 }
 
 /** Represents a void statement dropping an expression's value. */
@@ -2005,6 +2311,10 @@ export class VoidStatement extends Statement {
 
   /** Expression being dropped. */
   expression: Expression;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitVoidStatement(this);
+  }
 }
 
 /** Represents a `while` statement. */
@@ -2015,6 +2325,10 @@ export class WhileStatement extends Statement {
   condition: Expression;
   /** Statement being looped over. */
   statement: Statement;
+
+  visit(visitor: ASTVisitor): void {
+    visitor.visitWhileStatement(this);
+  }
 }
 
 /** Finds the first decorator matching the specified kind. */
@@ -2042,3 +2356,92 @@ export function isTypeOmitted(type: TypeNode): bool {
   }
   return false;
 }
+
+/** An AST visitor interface. */
+export interface ASTVisitor {
+  visitSource(node: Source): void;
+
+  // visitNode(node: Node): void;
+  // visitSource(source: Source): void;
+  // types
+
+  visitTypeNode(node: TypeNode): void;
+  visitTypeName(node: TypeName): void;
+  visitNamedTypeNode(node: NamedTypeNode): void;
+  visitFunctionTypeNode(node: FunctionTypeNode): void;
+  visitTypeParameter(node: TypeParameterNode): void;
+  // expressions
+
+  visitIdentifierExpression(node: IdentifierExpression): void;
+  visitArrayLiteralExpression(node: ArrayLiteralExpression): void;
+  visitObjectLiteralExpression(node: ObjectLiteralExpression): void;
+  visitAssertionExpression(node: AssertionExpression): void;
+  visitBinaryExpression(node: BinaryExpression): void;
+  visitCallExpression(node: CallExpression): void;
+  visitClassExpression(node: ClassExpression): void;
+  visitCommaExpression(node: CommaExpression): void;
+  visitElementAccessExpression(node: ElementAccessExpression): void;
+  visitFunctionExpression(node: FunctionExpression): void;
+  visitLiteralExpression(node: LiteralExpression): void;
+  visitFloatLiteralExpression(node: FloatLiteralExpression): void;
+  visitInstanceOfExpression(node: InstanceOfExpression): void;
+  visitIntegerLiteralExpression(node: IntegerLiteralExpression): void;
+  visitStringLiteral(str: string, singleQuoted?: bool): void;
+  visitStringLiteralExpression(node: StringLiteralExpression): void;
+  visitRegexpLiteralExpression(node: RegexpLiteralExpression): void;
+  visitNewExpression(node: NewExpression): void;
+  visitParenthesizedExpression(node: ParenthesizedExpression): void;
+  visitPropertyAccessExpression(node: PropertyAccessExpression): void;
+  visitTernaryExpression(node: TernaryExpression): void;
+  visitUnaryExpression(node: UnaryExpression): void;
+  visitUnaryPostfixExpression(node: UnaryPostfixExpression): void;
+  visitUnaryPrefixExpression(node: UnaryPrefixExpression): void;
+  visitSuperExpression(node: SuperExpression): void;
+  visitFalseExpression(node: FalseExpression): void;
+  visitTrueExpression(node: TrueExpression): void;
+  visitThisExpression(node: ThisExpression): void;
+  visitNullExperssion(node: NullExpression): void;
+  visitConstructorExpression(node: ConstructorExpression): void;
+  // statements
+
+  visitNodeAndTerminate(statement: Statement): void;
+  visitBlockStatement(node: BlockStatement): void;
+  visitBreakStatement(node: BreakStatement): void;
+  visitContinueStatement(node: ContinueStatement): void;
+  visitClassDeclaration(node: ClassDeclaration, isDefault?: bool): void;
+  visitDoStatement(node: DoStatement): void;
+  visitEmptyStatement(node: EmptyStatement): void;
+  visitEnumDeclaration(node: EnumDeclaration, isDefault?: bool): void;
+  visitEnumValueDeclaration(node: EnumValueDeclaration): void;
+  visitExportImportStatement(node: ExportImportStatement): void;
+  visitExportMember(node: ExportMember): void;
+  visitExportStatement(node: ExportStatement): void;
+  visitExportDefaultStatement(node: ExportDefaultStatement): void;
+  visitExpressionStatement(node: ExpressionStatement): void;
+  visitFieldDeclaration(node: FieldDeclaration): void;
+  visitForStatement(node: ForStatement): void;
+  visitFunctionDeclaration(node: FunctionDeclaration, isDefault?: bool): void;
+  visitFunctionCommon(node: FunctionDeclaration): void;
+  visitIfStatement(node: IfStatement): void;
+  visitImportDeclaration(node: ImportDeclaration): void;
+  visitImportStatement(node: ImportStatement): void;
+  visitIndexSignatureDeclaration(node: IndexSignatureDeclaration): void;
+  visitInterfaceDeclaration(node: InterfaceDeclaration, isDefault?: bool): void;
+  visitMethodDeclaration(node: MethodDeclaration): void;
+  visitNamespaceDeclaration(node: NamespaceDeclaration, isDefault?: bool): void;
+  visitReturnStatement(node: ReturnStatement): void;
+  visitSwitchCase(node: SwitchCase): void;
+  visitSwitchStatement(node: SwitchStatement): void;
+  visitThrowStatement(node: ThrowStatement): void;
+  visitTryStatement(node: TryStatement): void;
+  visitTypeDeclaration(node: TypeDeclaration): void;
+  visitVariableDeclaration(node: VariableDeclaration): void;
+  visitVariableStatement(node: VariableStatement): void;
+  visitWhileStatement(node: WhileStatement): void;
+  visitVoidStatement(node: VoidStatement): void;
+  // other
+
+  visitComment(node: CommentNode): void;
+  visitDecoratorNode(node: DecoratorNode): void;
+  visitParameter(node: ParameterNode): void;
+}
diff --git a/src/compiler.ts b/src/compiler.ts
index 7e94bfb33b..a0f0e3001a 100644
--- a/src/compiler.ts
+++ b/src/compiler.ts
@@ -1301,23 +1301,32 @@ export class Compiler extends DiagnosticEmitter {
 
     // imported function
     } else {
-      if (!instance.is(CommonFlags.AMBIENT)) {
-        this.error(
-          DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
-          instance.identifierNode.range
-        );
+      // Virtual Methods
+      if (instance.is( CommonFlags.VIRTUAL)) {
+       funcRef = module.addFunction(instance.internalName,
+          typeRef,
+          typesToNativeTypes(instance.additionalLocals),
+          module.nop()
+       );
+
+      }else {
+        if (!instance.is(CommonFlags.AMBIENT)) {
+          this.error(
+            DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration,
+            instance.identifierNode.range
+          );
       }
+        instance.set(CommonFlags.MODULE_IMPORT);
+        mangleImportName(instance, instance.declaration); // TODO: check for duplicates
 
-      instance.set(CommonFlags.MODULE_IMPORT);
-      mangleImportName(instance, instance.declaration); // TODO: check for duplicates
-
-      // create the import
-      funcRef = module.addFunctionImport(
-        instance.internalName,
-        mangleImportName_moduleName,
-        mangleImportName_elementName,
-        typeRef
-      );
+        // create the import
+        funcRef = module.addFunctionImport(
+          instance.internalName,
+          mangleImportName_moduleName,
+          mangleImportName_elementName,
+          typeRef
+        );
+      }
     }
 
     instance.finalize(module, funcRef);
@@ -1438,10 +1447,10 @@ export class Compiler extends DiagnosticEmitter {
     alternativeReportNode: Node | null = null
   ): void {
     // TODO
-    this.error(
-      DiagnosticCode.Operation_not_supported,
-      declaration.range
-    );
+    // this.error(
+    //   DiagnosticCode.Operation_not_supported,
+    //   declaration.range
+    // );
   }
 
   // === Memory ===================================================================================
diff --git a/src/index.ts b/src/index.ts
index d35b2b2126..86fc617373 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -142,8 +142,8 @@ export function finishParsing(parser: Parser): Program {
 }
 
 /** Compiles the sources computed by the parser to a module. */
-export function compileProgram(program: Program, options: Options | null = null): Module {
-  return new Compiler(program, options).compile();
+export function initializeCompiler(program: Program, options: Options | null = null): Compiler {
+  return new Compiler(program, options);
 }
 
 /** Decompiles a module to its (low level) source. */
@@ -208,4 +208,4 @@ export * from "./program";
 export * from "./resolver";
 export * from "./tokenizer";
 export * from "./types";
-export * from "./util";
+export * from "./util/index";
diff --git a/src/program.ts b/src/program.ts
index a2822af3f6..6cacc49820 100644
--- a/src/program.ts
+++ b/src/program.ts
@@ -404,6 +404,9 @@ export class Program extends DiagnosticEmitter {
   /** Next class id. */
   nextClassId: u32 = 0;
 
+  /** Program has been initialized. */
+  initialized: boolean = false;
+
   /** Constructs a new program, optionally inheriting parser diagnostics. */
   constructor(
     /** Shared array of diagnostic messages (emitted so far). */
@@ -542,6 +545,9 @@ export class Program extends DiagnosticEmitter {
 
   /** Initializes the program and its elements prior to compilation. */
   initialize(options: Options): void {
+    if (this.initialized) {
+      return;
+    }
     this.options = options;
 
     // register native types
@@ -880,6 +886,8 @@ export class Program extends DiagnosticEmitter {
         for (let element of exports.values()) this.markModuleExport(element);
       }
     }
+
+    this.initialized = true;
   }
 
   /** Requires that a global library element of the specified kind is present and returns it. */
@@ -1038,10 +1046,10 @@ export class Program extends DiagnosticEmitter {
   ): File | null {
     var filesByName = this.filesByName;
     return filesByName.has(foreignPath)
-         ? filesByName.get(foreignPath)!
-         : filesByName.has(foreignPathAlt)
-         ? filesByName.get(foreignPathAlt)!
-         : null;
+      ? filesByName.get(foreignPath)!
+      : filesByName.has(foreignPathAlt)
+      ? filesByName.get(foreignPathAlt)!
+      : null;
   }
 
   /** Tries to locate a foreign element by traversing exports and queued exports. */
@@ -1663,7 +1671,7 @@ export class Program extends DiagnosticEmitter {
   }
 
   /** Initializes a function. Does not handle methods. */
-  private initializeFunction(
+  initializeFunction(
     /** The declaration to initialize. */
     declaration: FunctionDeclaration,
     /** Parent element, usually a file or namespace. */
@@ -2051,6 +2059,8 @@ export abstract class Element {
   toString(): string {
     return ElementKind[this.kind] + ":" + this.internalName;
   }
+
+  abstract visit(visitor: ElementVisitor): void;
 }
 
 /** Base class of elements with an associated declaration statement. */
@@ -2229,6 +2239,9 @@ export class File extends Element {
     }
     return ns;
   }
+  visit(visitor: ElementVisitor): void {
+    visitor.visitFile(this);
+  }
 }
 
 /** A type definition. */
@@ -2270,6 +2283,10 @@ export class TypeDefinition extends TypedElement {
   lookup(name: string): Element | null {
     return this.parent.lookup(name);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitTypeDefinition(this);
+  }
 }
 
 /** A namespace that differs from a file in being user-declared with a name. */
@@ -2302,6 +2319,10 @@ export class Namespace extends DeclaredElement {
     return this.lookupInSelf(name)
         || this.parent.lookup(name);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitNamespace(this);
+  }
 }
 
 /** An enum. */
@@ -2335,6 +2356,10 @@ export class Enum extends TypedElement {
     return this.lookupInSelf(name)
         || this.parent.lookup(name);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitEnum(this);
+  }
 }
 
 /** Indicates the kind of an inlined constant value. */
@@ -2449,6 +2474,10 @@ export class EnumValue extends VariableLikeElement {
   lookup(name: string): Element | null {
     return this.parent.lookup(name);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitEnumValue(this);
+  }
 }
 
 /** A global variable. */
@@ -2473,6 +2502,10 @@ export class Global extends VariableLikeElement {
     );
     this.decoratorFlags = decoratorFlags;
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitGlobal(this);
+  }
 }
 
 /** A function parameter. */
@@ -2514,6 +2547,10 @@ export class Local extends VariableLikeElement {
     assert(type != Type.void);
     this.setType(type);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitLocal(this);
+  }
 }
 
 /** A yet unresolved function prototype. */
@@ -2616,6 +2653,14 @@ export class FunctionPrototype extends DeclaredElement {
   lookup(name: string): Element | null {
     return this.parent.lookup(name);
   }
+
+  get signature(): string {
+    return this.name + this.functionTypeNode.toString();
+  }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitFunctionPrototype(this);
+  }
 }
 
 /** A resolved function. */
@@ -2770,6 +2815,9 @@ export class Function extends TypedElement {
       }
     }
   }
+  visit(visitor: ElementVisitor): void {
+    visitor.visitFunction(this);
+  }
 }
 
 /** A resolved function target, that is a function called indirectly by an index and signature. */
@@ -2804,11 +2852,14 @@ export class FunctionTarget extends Element {
   lookup(name: string): Element | null {
     return null;
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitFunctionTarget(this);
+  }
 }
 
 /** A yet unresolved instance field prototype. */
 export class FieldPrototype extends DeclaredElement {
-
   /** Constructs a new field prototype. */
   constructor(
     /** Simple name. */
@@ -2850,11 +2901,14 @@ export class FieldPrototype extends DeclaredElement {
   lookup(name: string): Element | null {
     return this.parent.lookup(name);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitFieldPrototype(this);
+  }
 }
 
 /** A resolved instance field. */
 export class Field extends VariableLikeElement {
-
   /** Field prototype reference. */
   prototype: FieldPrototype;
   /** Field memory offset, if an instance field. */
@@ -2882,6 +2936,10 @@ export class Field extends VariableLikeElement {
     this.setType(type);
     registerConcreteElement(this.program, this);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitField(this);
+  }
 }
 
 /** A property comprised of a getter and a setter function. */
@@ -2916,6 +2974,10 @@ export class PropertyPrototype extends DeclaredElement {
   lookup(name: string): Element | null {
     return this.parent.lookup(name);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitPropertyPrototype(this);
+  }
 }
 
 /** A resolved property. */
@@ -2956,6 +3018,10 @@ export class Property extends VariableLikeElement {
   lookup(name: string): Element | null {
     return this.parent.lookup(name);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitProperty(this);
+  }
 }
 
 /** A yet unresolved class prototype. */
@@ -3065,6 +3131,10 @@ export class ClassPrototype extends DeclaredElement {
   lookup(name: string): Element | null {
     return this.parent.lookup(name);
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitClassPrototype(this);
+  }
 }
 
 const enum AcyclicState {
@@ -3190,9 +3260,14 @@ export class Class extends TypedElement {
 
   /** Tests if a value of this class type is assignable to a target of the specified class type. */
   isAssignableTo(target: Class): bool {
-    var current: Class | null = this;
+    var current: Class = this;
     do if (current == target) return true;
-    while (current = current.base);
+    while (current.base && (current = current.base));
+    if (target.kind == ElementKind.INTERFACE && current.prototype.implementsNodes) {
+      let interfaceNames = current.prototype.implementsNodes.map<string>(
+              (node: NamedTypeNode, _: usize, __: NamedTypeNode[]) : string => node.toString());
+      return interfaceNames.some((name: string,_i: usize,_: string[]) : boolean => name == target.name);
+    }
     return false;
   }
 
@@ -3408,6 +3483,10 @@ export class Class extends TypedElement {
     }
     return false;
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitClass(this);
+  }
 }
 
 /** A yet unresolved interface. */
@@ -3428,6 +3507,10 @@ export class InterfacePrototype extends ClassPrototype { // FIXME
       true
     );
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitInterfacePrototype(this);
+  }
 }
 
 /** A resolved interface. */
@@ -3440,7 +3523,7 @@ export class Interface extends Class { // FIXME
     typeArguments: Type[] = [],
     base: Interface | null = null
   ) {
-    super(
+     super(
       nameInclTypeParameters,
       prototype,
       typeArguments,
@@ -3448,6 +3531,10 @@ export class Interface extends Class { // FIXME
       true
     );
   }
+
+  visit(visitor: ElementVisitor): void {
+    visitor.visitInterface(this);
+  }
 }
 
 /** Registers a concrete element with a program. */
@@ -3585,3 +3672,24 @@ export function mangleInternalName(name: string, parent: Element, isInstance: bo
     }
   }
 }
+
+export interface ElementVisitor {
+  visitFile(node: File): void;
+  visitTypeDefinition(node: TypeDefinition): void;
+  visitNamespace(node: Namespace): void;
+  visitEnum(node: Enum): void;
+  visitEnumValue(node: EnumValue): void;
+  visitGlobal(node: Global): void;
+  visitLocal(node: Local): void;
+  visitFunctionPrototype(node: FunctionPrototype): void;
+  visitFunction(node: Function): void;
+  visitFunctionTarget(node: FunctionTarget): void;
+  visitFieldPrototype(node: FieldPrototype): void;
+  visitField(node: Field): void;
+  visitPropertyPrototype(node: PropertyPrototype): void;
+  visitProperty(node: Property): void;
+  visitClassPrototype(node: ClassPrototype): void;
+  visitClass(node: Class): void;
+  visitInterfacePrototype(node: InterfacePrototype): void;
+  visitInterface(node: Interface): void;
+}
diff --git a/src/resolver.ts b/src/resolver.ts
index 4a04ed4f88..0b5a959287 100644
--- a/src/resolver.ts
+++ b/src/resolver.ts
@@ -23,7 +23,8 @@ import {
   Field,
   FieldPrototype,
   Global,
-  TypeDefinition
+  TypeDefinition,
+  InterfacePrototype
 } from "./program";
 
 import {
@@ -223,8 +224,8 @@ export class Resolver extends DiagnosticEmitter {
         return Type.i32;
       }
 
-      // Handle classes
-      if (element.kind == ElementKind.CLASS_PROTOTYPE) {
+      // handle classes
+      if (element.kind == ElementKind.CLASS_PROTOTYPE || element.kind == ElementKind.INTERFACE_PROTOTYPE) {
         let instance = this.resolveClassInclTypeArguments(
           <ClassPrototype>element,
           typeArgumentNodes,
@@ -1430,7 +1431,7 @@ export class Resolver extends DiagnosticEmitter {
 
     // Instance method prototypes are pre-bound to their concrete class as their parent
     if (prototype.is(CommonFlags.INSTANCE)) {
-      assert(actualParent.kind == ElementKind.CLASS);
+      assert(actualParent.kind == ElementKind.CLASS || actualParent.kind == ElementKind.INTERFACE);
       classInstance = <Class>actualParent;
 
       // check if this exact concrete class and function combination is known already
@@ -1690,7 +1691,7 @@ export class Resolver extends DiagnosticEmitter {
     // Construct the instance and remember that it has been resolved already
     var nameInclTypeParamters = prototype.name;
     if (instanceKey.length) nameInclTypeParamters += "<" + instanceKey + ">";
-    instance = new Class(nameInclTypeParamters, prototype, typeArguments, baseClass);
+    instance = new Class(nameInclTypeParamters, prototype, typeArguments, baseClass, prototype instanceof InterfacePrototype);
     instance.contextualTypeArguments = ctxTypes;
     prototype.setResolvedInstance(instanceKey, instance);
 
diff --git a/std/assembly/shared/index.d.ts b/std/assembly/shared/index.d.ts
new file mode 100644
index 0000000000..c15efc0da7
--- /dev/null
+++ b/std/assembly/shared/index.d.ts
@@ -0,0 +1,109 @@
+// declare module "assemblyscript/std/assembly/shared/feature"{
+//     // This file is shared with the compiler and must remain portable
+
+//     /** Indicates specific features to activate. */
+//     export const enum Feature {
+//         /** No additional features. */
+//         NONE = 0,
+//         /** Sign extension operations. */
+//         SIGN_EXTENSION = 1 << 0, // see: https://github.com/WebAssembly/sign-extension-ops
+//         /** Mutable global imports and exports. */
+//         MUTABLE_GLOBAL = 1 << 1, // see: https://github.com/WebAssembly/mutable-global
+//         /** Bulk memory operations. */
+//         BULK_MEMORY = 1 << 2, // see: https://github.com/WebAssembly/bulk-memory-operations
+//         /** SIMD types and operations. */
+//         SIMD = 1 << 3, // see: https://github.com/WebAssembly/simd
+//         /** Threading and atomic operations. */
+//         THREADS = 1 << 4 // see: https://github.com/WebAssembly/threads
+//     }
+//     // This file is shared with the compiler and must remain portable
+// }
+
+// declare module "assemblyscript/std/assembly/shared/target"{
+// /** Compilation target. */
+// export enum Target {
+//     /** WebAssembly with 32-bit pointers. */
+//     WASM32,
+//     /** WebAssembly with 64-bit pointers. Experimental and not supported by any runtime yet. */
+//     WASM64,
+//     /** Portable. */
+//     JS
+//   }
+// }
+// declare module "assemblyscript/std/assembly/shared/typeinfo"{
+//   // This file is shared with the compiler and must remain portable
+
+// // ╒═══════════════════ Typeinfo interpretation ═══════════════════╕
+// //    3                   2                   1
+// //  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0  bits
+// // ├─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┤ ◄─ __rtti_base
+// // │                             count                             │
+// // ╞═══════════════════════════════════════════════════════════════╡ ┐
+// // │                      Typeinfo#flags [id=0]                    │ id < count
+// // ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
+// // │                      Typeinfo#base  [id=0]                    │
+// // ├───────────────────────────────────────────────────────────────┤
+// // │                              ...                              │
+
+// /** Runtime type information data structure. */
+// //@ts-ignore 
+// @unmanaged
+// export class Typeinfo {
+//   /** Flags describing the shape of this class type. */
+//   flags: TypeinfoFlags;
+//   /** Base class id or `0` if none. */
+//   base: u32;
+// }
+
+// /** Runtime type information flags. */
+// export const enum TypeinfoFlags {
+//   /** No specific flags. */
+//   NONE = 0,
+//   /** Type is an `ArrayBufferView`. */
+//   ARRAYBUFFERVIEW = 1 << 0,
+//   /** Type is an `Array`. */
+//   ARRAY = 1 << 1,
+//   /** Type is a `Set`. */
+//   SET = 1 << 2,
+//   /** Type is a `Map`. */
+//   MAP = 1 << 3,
+//   /** Type is inherently acyclic. */
+//   ACYCLIC = 1 << 4,
+//   /** Value alignment of 1 byte. */
+//   VALUE_ALIGN_0 = 1 << 5,
+//   /** Value alignment of 2 bytes. */
+//   VALUE_ALIGN_1 = 1 << 6,
+//   /** Value alignment of 4 bytes. */
+//   VALUE_ALIGN_2 = 1 << 7,
+//   /** Value alignment of 8 bytes. */
+//   VALUE_ALIGN_3 = 1 << 8,
+//   /** Value alignment of 16 bytes. */
+//   VALUE_ALIGN_4 = 1 << 9,
+//   /** Value is a signed type. */
+//   VALUE_SIGNED = 1 << 10,
+//   /** Value is a float type. */
+//   VALUE_FLOAT = 1 << 11,
+//   /** Value type is nullable. */
+//   VALUE_NULLABLE = 1 << 12,
+//   /** Value type is managed. */
+//   VALUE_MANAGED = 1 << 13,
+//   /** Key alignment of 1 byte. */
+//   KEY_ALIGN_0 = 1 << 14,
+//   /** Key alignment of 2 bytes. */
+//   KEY_ALIGN_1 = 1 << 15,
+//   /** Key alignment of 4 bytes. */
+//   KEY_ALIGN_2 = 1 << 16,
+//   /** Key alignment of 8 bytes. */
+//   KEY_ALIGN_3 = 1 << 17,
+//   /** Key alignment of 16 bytes. */
+//   KEY_ALIGN_4 = 1 << 18,
+//   /** Key is a signed type. */
+//   KEY_SIGNED = 1 << 19,
+//   /** Key is a float type. */
+//   KEY_FLOAT = 1 << 20,
+//   /** Key type is nullable. */
+//   KEY_NULLABLE = 1 << 21,
+//   /** Key type is managed. */
+//   KEY_MANAGED = 1 << 22
+// }
+// }
\ No newline at end of file