Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

A: Basically we are utilizing the fantastic AST IASNode structure, traversing the nodes and visiting them individually with an emitter. The difference here is the AST walker is a hand written implementation that can easily be maintained and optimized per individual specs.

Framework Design

The FalconJx javascript cross compiler relies on AST generated by the Falcon compiler when it parses ActionScript code. This AST is then traversed in a top down fashion from the IFileNode down into the leaf expression nodes of an ActionScript source file.

There are 3 abstract concepts employed here;

  1. A traversing class that is responsible for knowing the toplevel structure of an ActionScript file, in the default implementation of the compiler, this class is the ASBlockWalker.
  2. A node visitor that will handle each node based on it's type. This is the ASNodeSwitch class. The walker calls this class's handle() method when traversing the AST.
  3. An emitter class that is a strategy as well inside the walker class that gets called when a node is found that needs to be emitted.

One question you may be asking is, when I look at the source code of the ASEmitter, you seem to have coupled that with the walker in callbacks to the walker's walk() method.

A: Yes, this is true but to maintain a central walker class that could be overridden to provide hooks to generate extra code, delegating on a 1 to 1 relationship between these classes only rely on a public API, the emit and walk API.

It could be argued that there is redundant calls back and forth, but I guess it comes down to the designer and what was implemented. :) I really see this as a very good abstraction that will lead to easy code maintenance down the road as ALL emitting should be done in the base ASEmitter class. Plus, there are circumstances present and in the unforeseeable future that having the core traversing done in the walker with more fine grained traversal in the emitter really pays off.

The first implementation of the IASNodeStrategy handler of the walker uses a before and after handler which sandwiches the main AST node handler in the middle. The benefit of this is leaving the open and closing of blocks in an external class for good decoupling of the block generation. It may work out that this before and after strategy is not needed and affects performance but that is to be decided.

Compilation Steps

  • Main method is called with compile arguments like MXMLC
  • A backend instance is created that acts as a factory to create the source file handler, configurator, javascript target, AST walker, JavaScript emitter and node switch strategy and the JavaScript writer.
  • The configuration instance is created and the project is configured with the run-time arguments and defaults.
  • The main compile() method is called.
  • The file handler is setup for .as and .mxml files.
  • The target file is setup. The target file is the main application file used just like MXMLC expects. The target file is the entry point to the application.
  • Once everything is setup and there are no configuration and target errors present, the JavaScript target is built.
  • A JSTarget instance is created and the build() method is called.
  • Once the build() method is called, the compiler runs in multi-threaded mode finding all reachable compilation units and proceeds to call the ASParser on them created their AST trees.
  • If the JSApplication artifact is created successfully a JSWriter is created for each compilation unit and an AST walker is created to traverse each compilation unit's AST tree to emit JavaScript source code dependent on the visitor/emitter implementation.
  • After each compilation unit is traversed, the output bytes of the emitter are then saved to it's corresponding .js file in the source output directory.
  • If all is successful, the compiler will exit with a 0 exit code meaning success and all ActionScript files were cross compiled to JavaScript.

...

Note: Most of these base test output JavaScript that is virtually identical to JavaScriptActionScript. This means ActionScript could as easily be output from the emitter since it proves that the walker is semantically traversing the ActionScript AST correctly. Using this same framework, different language output could be implemented, would you want to do that? Only time will tell.

Composition

The main goal of this prototype is for composition of emitter strategies. There are specific levels of node handlers that have been implemented.

...