Eiffel Compilation Explained
The goal of this page is to describe the various steps which happen during the compilation of an Eiffel system, and to give a general overview of our code generation.
This is the place where using the configuration file, we traverse the file system for looking at files with the .e extension, and then lookup the class name associated with the .e file.
This is where the compilation actually starts. Starting from a set of classes that needs to be compiled (e.g. ANY, STRING, INTEGER, ...) and the root class, we parse each class, and each unparsed class we encounter in the parsed class will be added to the set of classes that needs to be compiled. Degree 5 will complete when the transitive closure of referenced classes is done, in other word when the set is empty.
Degree 5 parses each class and creates a CLASS_AS node (that is to say an abstract syntax tree representing the class). We also initialize the inheritance clauses, so that a topological sort can be done at the very end of degree 5.
The topological sort will sort so that when you have a class, all the parents of that class are located before that class in the topological sort. Thus making ANY the first entry (since ancestor of all classes), and NONE the last one (except that since NONE is not a real class, it does not actually appear).
Using the topological order, we analyze the inheritance clause of every classes to ensure they are valid, and build their feature table. The feature table is a table where all available features for a class are registered. It is indexed by name or by routine ID.
This is where we actually validate the code of each routine, and when it is valid, we generate a BYTE_NODE object representing a compiled version of the AST which is made for code generation purposes. This new object has more information about how to generate certain eiffel constructs.
Usually place where melted code is generated.
Place where C code is generated for the workbench version.
Analyzing of features to build polymorphic tables. A polymorphic table is a table which stores all the versions of a routine, and let you know which version to call depending on the target type. They are used for code generation at degree -3.
Dead code removal
Starting from the creation procedure, we mark alive all routines that we encounter. All unmarked routines are considered dead and therefore won't be generated at degree -3.
This is where we generate the optimized code. It does inlining, dynamic to static binding optimization, removal of dead branches,...