
Hi% habra_user%!
In the course of a series of articles on the Flex compiler, I decided to translate a good article by the author of this work on what processes occur inside the compiler when building an application. It dates back to the year 2008, but it was not noticed in the Russian-speaking community (and in others as well). And since in the near future this particular compiler remains relevant for building the vast majority of Flash projects, I decided to continue the cycle of articles on its expansion.
As usual, all those who are not tired of reading this line - I ask for the cut!
First, I consider it appropriate to provide links to other articles in the series:
- Adding Designer Parameters to the MXML Flex Compiler
- MXML compiler. Part 2. Non-string parameter initializers
- MXML compiler. Part 3. We understand the work of the Flex-compiler
Secondly, I had to google pretty well to find the actual (due to the transfer of Flex to the Apache) link to the code for branch 4.6, and to save your time,
I just leave it here:opensource.adobe.com/svn//opensource/flex/sdk/branches/4.yWhy am I using this particular version?The answer lies in the build process, because if the version from Adobe could be assembled out of the box by simply downloading the sources and running ant, then with the version of Apache you have to pretty much try to compile it because of dependencies. And the difference between them is still minimal (both do not support Maven for building :))
I (like the author of the original article) strongly recommend downloading the source code for a better understanding of the article material. The article material is relevant for both (Apache & Adobe) versions of the compiler.
')
Language compilers
In general, Flex compiler supports different programming languages. They are compiled by a set of language-specific compilers. If you look at the list of project classes named Compiler, you can see some of them:

However, it cannot be argued that all languages can be compiled in one step. For example, the MXML compiler may use dependencies written in AS3. Therefore, before compiling the MXML component into bytecode, the compiler must determine which AS3 classes it needs and verify that the code called from MXML code on AS3 is correct.
It is also reasonable to assume that different compilers require a different number of stages. For example, the MXML compiler requires twice as many steps as AS3.
flex2.compiler.SubCompiler
In Flex, all language compilers implement the same interface -
flex2.compiler.SubCompiler :
public interface SubCompiler { String getName(); boolean isSupported(String mimeType); String[] getSupportedMimeTypes(); Source preprocess(Source source); CompilationUnit parse1(Source source, SymbolTable symbolTable); void parse2(CompilationUnit unit, SymbolTable symbolTable); void analyze1(CompilationUnit unit, SymbolTable symbolTable); void analyze2(CompilationUnit unit, SymbolTable symbolTable); void analyze3(CompilationUnit unit, SymbolTable symbolTable); void analyze4(CompilationUnit unit, SymbolTable symbolTable); void generate(CompilationUnit unit, SymbolTable symbolTable); void postprocess(CompilationUnit unit, SymbolTable symbolTable); void initBenchmarks(); PerformanceData[] getBenchmarks(); PerformanceData[] getEmbeddedBenchmarks(); void logBenchmarks(Logger logger); }
Among the methods not related to the compilation process can be distinguished:
String getName () - as the name implies, the method returns the name of the compiler;
isSupported and
getSupportedMimeTypes - used to determine the type of files that this compiler can read;
benchmarks methods related to compile performance measurement.
Compilation stages
As you can see, the compilation process consists of 9 steps. The main Flex compiler acts as a coordinator and is responsible for invoking compiler instances that expect something like this:
- preprocess (once)
- parse1 (once)
- parse2 (once)
- analyze1 (once)
- analyze2 (once)
- analyze3 (once)
- analyze4 (once)
- generate (once)
- postprocess (many times until the instance requires a stop)
In addition to calling these methods, the main Flex compiler does a number of things:
- Selects the appropriate compiler instance based on the type of the source file;
- Receives a list of not allowed types from instances and searches for them among project sources and libraries;
- Pass information by type into instances;
- Decides which compiler should run based on the state of the instances and the overall state of the resources.
In order to control everything and everyone, the main compiler forces instances to cooperate. Basically, he requires you to follow a specific set of rules:
- The syntax tree should be available at the end of parse2 ;
- analyze1 should have information about the name of the superclass;
- analyze2 should be aware of all dependencies;
- analyze4 should provide complete type information.
The compilation process continues until:
- There will be no dependencies that need to be resolved;
- Instances of compilers will give an error.
Call algorithms
As mentioned earlier, the compilation process consists of calling these 9 methods. But despite the fact that the order of calling these methods is defined quite precisely, the main compiler can still call them differently. In fact, there are 2 algorithms: One (
flex2.compiler.API.batch1 () ) is structured, the other (
flex2.compiler.API.batch2 () ) is conditionally pathogenic. Consider them separately:
API.batch1 () is a conservative and more structured algorithm. Its essence lies in the fact that it guarantees the occurrence of one phase for each file before moving to another phase. For example,
analyze1 () will be called for all files before proceeding to
analyze2 () .
API.batch2 () is a conditionally pathogenic algorithm, its main goal is to minimize memory consumption. Unlike
API.batch1 () , source files with a smaller number of dependencies can reach the
generate stage much earlier than files with a greater number of dependencies reach the phase of analyze3 (). The idea is that the resources allocated to the file can be freed immediately as the file will be compiled into bytecode.
Conclusion
Well, now you know much more about the internal workings of the Flex compiler! Let's summarize:
- The main Flex compiler uses only one of two compilation algorithms: batch1 or batch2;
- Compilation algorithms use 2 different strategies to invoke 9 stages of building an application;
- During the compilation process, compiler instances must cooperate and provide type information to the main compiler at the end of each step;
- The main compiler does all the gigantic work (searching for source files / libraries, managing error logging, etc.), which means that language compilers do not have to worry about it.
Described The above is relevant for all versions of utilities (mxmlc, compc, asdoc) that are part of the Flex Framework.
From the translator:
Please find the grammatical errors and inaccuracies to send a personal message, so as not to increase the number of translucent comments;)
PS In general, initially the idea was to write an article about the Flex Compiler Extension, which allows you to expand the compiler without changing its code (connect via flex-config.xml as a jar-ok), but having thought better of it, I decided to first make this article that describes the whole under the hood.
PSS Given the pace of development of ASC2.0, I believe that the Flex Compiler will be relevant for at least another year, or even more, so do not be afraid to study and pick it, especially since it is an invaluable experience!
PSSS Yes, yes, dead. Yes, Adobe abandoned the player. Yes, they gave Apache. Blah blah blah…