indexing authors: "Emmanuel STAPF & Jerome BOUAZIZ" date: "$Date$" version: "$Revision$" A Standard Eiffel Compilation: ------------------------------ Degree 6: --------- Two choices are offered to the users: - Melt - Quick-melt Melt: If the system is using some precompiled libraries, the LACE_I.recompile or LACE_I.do_recompilation will merge the precompiled libraries into the system. Then we take all the remaining classes which are specified in the Ace file and we make them available to the compiler Quick-Melt: We check all the compiled class of the compiler and we check if they have changed, if so we put them in `pass1_controler' Between Degree 6 and 5: ----------------------- Before to start everything we check the validity of the precompilations. Then we check the validity of the added/removed classes. Set the value of `poofter_intialization' to True only when a class has been changed. This is used for the finalization process (still mysterious!!) Degree 5: --------- We do a pass on `pass1_controler' and we apply execute from PASS1_C on each item, and then we remove the current item and we redo for the next one. For each item, if it is marked as `new_compilation' we reparsed it again, if not we retrieve the AST from either the TMP_AST_SERVER or AST_SERVER. 1 - We first check that all the class used (both real suppliers and parents) in the Current class are part of the Universe, otherwise we generate a VTCT error message. When they are part of the Universe and not yet compiled, we add them in the `pass1_controller' and we create an associated CLASS_C. 2 - We create an instance of CLASS_INFO with the list of parents for the current class and also the list of the creators of the Current class. 3 - Init current instance of CLASS_C: a) Insert obsolete_message into CLASS_C b) If the class was already compiled, we remove the class from all the descendants list of each parent (I.e. as if we removed the class from the system). c) If the class has changed the `deferred' status and if the class had some parents we insert the class into `pass2_controler', and set `changed_status' to True. d) If the class is expanded we set the system to have an expanded type. e) If the class has changed its `expanded' status and if the class had some parents we insert it into `pass2_controler' and set `changed_status' and `changed_expanded' f) If the class is separate we set the system to have a separate type. g) If the class has changed its `separate' status and if the class had some parents we insert it into `pass2_controler' and set `changed_status' and `changed_separate' h) If the class has the `changed_status' flag, then we loop through all the syntactical clients. If the class has changed its status for `expanded' or `separate' we insert the client into `pass1_controler' if it does not have is `changed' flag set. For all the clients we insert them into`pass2_controler', `pass3_controler' and `pass4_controler' For each class_type of the current class, we mark it as `changed' and update the `expanded' flag. i) If class has `parents' we go through each parent: - first loop, we make sure that we do not have a `like' declaration, if there is one we generate a VE04 error. - second loop, we update the corresponding CLASS_INFO.parents structures and the `parents' attributes of CLASS_C with the parents taken from the PARENT_AS node. we also add `Current' into the descendant of the parents CLASS_C. Else if the class is not GENERAL, we add ANY as a parent of Current and add Current as a descendant of ANY If it is GENERAL we do nothing special. j) We now check if the class has some generic parameters. If there is some, we check their validity, i.e. valid only if it is not a name of the surrounding universe, and if the name does not appear twice in the declaration. k) If the class has its generic declaration part changed in one or two way, we marked it as `changed_generics'. l) If `changed_generics', we add all the syntactical clients into `pass2_controler', `pass3_controler' and `pass4_controler'. We also update the syntactical relations, i.e we removed the current class from all the suppliers and update the new syntactical relations. We removed the class from the system and add it again in all the `controlers'. m) Check if between two compilations we changed the inheritance. If so, we marked the current class as `changed', `changed3a', and we need to mark SYSTEM_I to `update_sort' If not, we still need to do some work on it later, so we marked as `changed2'. If it is the first compilation, we just marked SYSTEM_I to `update_sort' There is a `if' statement which is never satisfied for `Conformance tables incrementality' 4) We have a checksum for errors. 5) If class is still part of the system, we do: a) Update the syntactical clients b) We set an id to the AST and we put it in TMP_AST_SERVER c) If the class a `unique' declaration we initialize the `unique_counter' and compute the unique values with the AST and put the result in the corresponding CLASS_INFO. d) Get the index from the TMP_AST_SERVER for the just parsed class, and the invariant_info and put them in the CLASS_INFO. We put the invariant_info into TMP_INV_AST_SERVER We put CLASS_INFO into TMP_CLASS_INFO_SERVER We clear the index of TMP_AST_SERVER e) We clean the `filters'. Note and improvements: ---------------------- 1 - There is maybe a possibility to merge all the `passx_controler' into one pass 2 - In `init' from CLASS_C, we have to remove all the call which add `Current' into the controler and do it only once when `changed_status' is true. 3 - In point 3-i) we can merge the two traversals of the `parents' 4 - We can maybe get rid of `update_syntactical_relations' in `init' from CLASS_C (3-l) point) since the call which just follows will delete all the added information. 5 - There seems to be a problem with the inheritance removal bug that Michael fixed in September 97. 6 - We absolutely need to save the result of `same_parents' 3-m) otherwise we compute it twice (and this is not a nice algorithm: two loops with a loop inside -((() 6bis - What is written in 6 is stupid, because we can remove the full statement. There is a `if' statement which is never satisfied for `Conformance tables incrementality' which needs to be removed Between Degree 5 and 4: ----------------------- Check generic paramaters of classes which have not been recompiled because one of their generic parameter can become a name of a new added class. If we are using a root class, it means that we are not in precompiled or compile all classes mode and as a consequence we need to make sure that the root class us not generic. We also need to remove all the useless classes (i.e. classes which are not part of the living universe anymore). If `update_sort' or if a class has been moved (added or removed) we need to redo a topological sort on `sorter', `pass2_controler', `pass3_controler' and `pass4_controler'. And then we have to rebuild the conformance table for all the classes. This implies that we need to reset the content of the melted_conformance_table. We clear `sorter'. Note and Improvements: ---------------------- We can merge CLASS_SORTER and TOPO_SORTER in one class Degree 4: --------- We check the validity of each changed generic classes. I.e. we check that the generic parameter is not constraint to an anchored type or if the declaration itself does not contain an anchored type, and that the name of the constraint is part of the surrounding universe. When the constraint is also generic, we need to check the validity of the declaration. For each class of the controler we will do: Execution of `execute' from PASS2_C: 1) We marked the class as non-reverse engineered. 2) If class marked as changed we mark `do_pass2' and insert it in `pass3_controler' and `pass4_controler' Otherwise `do_pass2' has the value of `changed2' of current class 3) If `do_pass2', we called `pass2' from INHERIT_TABLE. a) Getting the current class, its ID, its cluster, its `is_supplier_status_modifier', its CLASS_INFO, and the parents list. We wipe out the content of Selected, set `new_body_id' to Void. b) We compute the feature table: - We search for the feature table with the ID `a_class.id' in FEAT_TBL_SERVER, if we found it we call `update_table' on it. - `Update_table' check that all the elements of the table are valid, and remove the invalid one and put them in `removed_feature_ids'. We also descative the body_id corresponding to the non-valid FEATURE_I. (Explanation: for example, some features are still using types which are no longer defined in the system). The content of `removed_feature_ids' is used in `fill_pass2_control' from FEATURE_TABLE. - We prepare `inherited_features' by setting its ID - If it is a resumed compilation we do `update_table' on the feature table found in the TMP_FEAT_TBL_SERVER. c) We take each parents which have been put in the correct order and we merge them into the current INHERIT_TABLE. - We `check_parents' of CLASS_C on `a_class' each time we call `merge' - We take the feature table of each parent, and for each entry we duplicate it and instantiate it (??). With the new feature_i we create a new INHERIT_INFO object that we insert in the INHERIT_TABLE d) We check validity1, this is for the renaming purpose. - Make sure that old_name is different from new_name - Make sure that old_name is a feature of the parent - If new_name is infixed make sure it has one argument and it is a function - If new_name is prefixed make sure it has no argument and it is a function. e) We check twice for the renamings f) Analyze - For each feature which are inherited we call `process' on them. This will check that we are not undefining a deferred, a once, an attribute or a frozen feature. Then we check that the redefinition are correct in `check_features' from INHERIT_FEAT. We insert the feature in `adapatations' if it defines an inherited deferred feature, otherwuse we put the `inherited_info' into ̉rigin_table. g) We check validity2, this is for the undefine/redefine/select/export clause. - Make sure that the redefined features exist in the parent. - Make sure that the selected features exist in the parent. - Make sure that the undefined features exist in the parent. - Make sure that the exported features exist in the parent. h) If the class has been marked `changed' we clean `changed_features' of `a_class' and we analyze the class declarations. I.e. we create for each features a corresponding FEATURE_I by calling `feature_unit'. 4) Then if the `local_extra_check_list' does not have the current compiled class, we insert it, because we need to do some stuff at the end of degree 4. 5) We check the validity of the creation constraints, i.e. that the feature specified in the creation clause are part of the constrained class. 6) If the system has some expanded types, we do a check on all the system to be sure about the validity of the use of expanded type. 7) If the system support `code_replication' we do a single pass on all the compiled class of degree 4. Note and improvements: ---------------------- 1) Can we do a marking of all living features now and get rid of the Dead Code Removal part? 2) We can improve the remove of `update_table' called in 3-b) 3) We can maybe do only one call to `check_parents' from 3-c) 4) Are we sure to do twice `check_generics' in 3-e) 5) in PARENT_LIST, we can remove all the standard traversals by using the area instead of the start/item/forth/after mechanism. 6) Remove the `a_class: CLASS_C' attributes and give it through an extra parameter. 7) Change the size of the INHERIT_TABLE in SHARED_INHERITED, we should put 100 instead of 500 since even in the compiler we reached rarely the 100 features per class. Between Degree 4 and 3: ----------------------- Make sure that all the creation procedures of the ROOT_CLASS have 0 argument or 1 argument of type ARRAY[STIRNG]. Notes: ------ We should not go through all the creation procedures of the root class, we just need to take the `creation_name' from the Ace file and make sure it has the correct number of arguments and it is a creation procedure. Degree 3: --------- We call `execute' of PASS3_C, which calls `pass3' of each CLASS_C which needs to be recompiled. Copy/paste of a comment to understand what we do : -- Byte code production and type checking: list `changed_classes' -- contains classes marked `changed' and/or changed3. For -- the classes marked `changed', produce byte code and type -- check the features marked `melted'; if the class is also -- marked `changed3' type check also the other features. For -- classes marked `changed3' only, type check all the -- features. For each class, 1) We update the suppliers of the class. A) We take the dependances of the class in the depend_server (or we create them) and the replication dependances of the class (rep_depend_server).We clone the suppliers list of the class if marked changed.We take the feature table of the class and then prepare an ast_context and a new melted_set. B) For each feature in the class: if the feature is to be melted in the current class, a/ we re-compute the default rescue clause. b/ we check if the current feature has changed : _ if it is a routine in the changed_feature list (1) _ if one of the suppliers of the feature in melted_propagator (equivalent to changed ???) _ if one of the suppliers has been removed from the system c/ if the feature has changed (except in case 1 : WHY ??? ) we re-compute the body-id d/ if the feature is an attribute, we re-compute the body-id ( in case it was a routine redefined in attribute : but WHY ALWAYS ???) e/ type checking : _ we try to find the body of the feature and we call the type checking on it. _ we put the type of the actual class in the context stack and we call the type checking on the body_as _ if the content is not an attribute (WE HAVE ALREADY CHECKED IT ???) we call the type checking on it. _there are 2 type of content : constant_as or routine_as. we do something only in the case of routine_as (otherwise the function is empty). _we first check the locals variables: double loop, but it seems usefull... _we analyse the precondition _we analyse the body: we take each instruction and call its own type_check (2) _we analyse the postcondition f/ if everything was ok until now, then we update the suppliers list. _ we remove the dependances of the current feature _ we recreate the dependancies of the current feature g/ we generate the bytecode for the feature: the browsing is almost the same as for the type checking for the body. h/ we do the type checking for the feature marked changed3: they were not to be melted but for question of dependence with the ones to be melted they have to be checked them anyway. C/ We re-compute the invariant of the class: the invariant is treated just like an other feature_i(although it is not). It undergoes the same treatment as in the main loop described obove. D/ We update the dependencies/suppliers of the class itself: we remove the removed feature_i from the tables and their dependencies. Note and improvements: ---------------------- 1/ See the notes in uppercase along the text. 2/ As we go through the all system during the type checking, we should be able to make at least a part of the dead code removal during this degree. In particular during (2):cf type_check from ROUTINE_AS. 3/ Between Degree 3 and 2: ----------------------- We check if we need to do a freeze: either the user choosed it or we have no other choices because the externals features have changed (basically we added one) We do `process_type_system' which basically recomputes the class_types for each non generic classes which has changed. With the INSTANTIATOR class, we find all the derivations of a generic class. When it is the first compilation, we compute the dynamic types for the first time. We create for this purpose an array of CLASS_C indexed by their topological_id, and then we go through this array and we assign for each class_type of a CLASS_C a unique type_id. We do `process_skeleton'. If we are in standard compilation mode, we `process_skeleton' on each CLASS_C that has been recompiled and we check their validity. In precompiled mode, we do it only if CLASS_C has `has_types'. The `check_validity' call make sure that all the known classes from the compiler have not been changed by the user. After we check the validity of the expanded declaration in all the classes. Degree 2: --------- If we do a freeze, we call `update_dispatch_table' from PASS4_C, otherwise we call `melt' from PASS4_C. Check the validity of the MELTED_INFO, if not valid we remove it from the `melted_set' 1) melt: if the class is not a precompiled one, we `melt' its CLASS_TYPE 2) update_dispatch_table: if the class is not a precompiled one, we `update_dispatch_table' its CLASS_TYPE. Degree 1: --------- If we do not freeze, we start degree 1, otherwise we merge the `melted_set' into the `freeze_set'. Notes: ------ When we melt, we can definitively merge degree 2 and 1. Null State: ----------- We reset all the flags of CLASS_C We take over the content of all the TMP_SERVERS. When we `melt' we generate the melted.eif file. Degree -1: ---------- We create the Makefiles. We process the PATTERN_TABLE. We clear the melted byte code servers. We rebuild the dispatch_table and execution tables. For each class we generate the workbench files: 1) We take the feature table of the corresponding class 2) We generate the descriptor tables for each associated class types. 3) We generate the feature table 4) We generate the effective C code. 2) We create the descriptors list DESC_LIST from the CLASS_C: A DESC_LIST is a list of DESCRIPTOR. Each item of the DESC_LIST corresponds to a generic derivation of the CLASS_C. Each descriptor has a number of element equal to the number of features written in CLASS_C. a) If the class has an invariant, we put it in each DESCRIPTOR of the DESC_LIST since each generic derivation shares the same invariant. b) For each feature, we put them in each DESCRIPTOR of DESC_LIST. 3) We create an array of FEATURE_I from the FEATURE_TABLE indexed by the feature_id of feature_i. Thenwe go through this array to generate in the correct order the feature table. 4) We generate the effective C code for each feature, by going through all the BYTE_NODES of the feature_I. Notes and improvements: ----------------------- 1) In `put_invariant' from DESC_LIST, we can remove the test `f.has_entry' since it is always true for an INVARIANT_FEAT_I. We can also remove the test `u /= Void' since `new_entry' alsways creates a non-void object. 2) We can remove the test `u /= Void' in `put' from DESC_LIST, Cf 1) 3) Check for a possibility of merging the creation of DESC_LIST and the effective generation. 4) Check for a possibility of merging the creation of ARRAY[FEATURE_I] and the effective generation.