bsc-pm / mcxx

Mercurium is a C/C++/Fortran source-to-source compilation infrastructure aimed at fast prototyping developed by the Programming Models group at the Barcelona Supercomputing Center
GNU Lesser General Public License v3.0
69 stars 23 forks source link

Enforce the order of Fortran statements within a program unit #23

Closed rofirrim closed 6 years ago

rofirrim commented 6 years ago

Since the beginning, Mercurium hasn't enforced the order of Fortran statements within program units. This leads to some complication and wrongly handled cases.

Also the FE lacked a generic mechanism to delay actions. Unfortunately some of the actions must be delayed until we know some form of statement cannot occur again (e.g. USE, IMPLICIT), so we could not reliably do this.

Each statement is now assigned to a statement ordering class. For the specific case of IMPLICIT NONE we need a new AST node for it so we can do this (it was currently represented with the same AST kind as a regular IMPLICIT statement). A few classes only represent a single statement (SOC_DATA, SOC_FORMAT, SOC_IMPLICIT, SOC_IMPLICIT_NONE, SOC_IMPORT, SOC_USE). Classes SOC_DECLARATION and SOC_EXECUTABLE represent non-executable and executable Fortran statements respectively. Note that because of the way we parse the Fortran code, statements that demarcate the range of program or subprogram units (like CONTAINS, FUNCTIONS, SUBROUTINE and their related END-statements) are not assigned a statement order class.

The array statement_order has one entry per set of classes allowed at a given point. A program unit starts at the beginning. When handling the statements within a program unit the current statement (once disambiguated) is checked against the current statement order. If it still allowed, nothing changes, if the statement is not allowed, then the order is advanced until it is allowed. If no order allows the current statement then this statement is misplaced within the program unit and this is an error.

Each program unit kind is assigned a statement constraint checker which basically is an index in the above statement_order array and a function that filters statements that are not allowed in the program unit (e.g. we used to ICE when an executable statement was used in the specification part of a MODULE, this is not the case any more).

This change also adds a generic mecanism for delayed actions. We had some ad-hoc delayed actions in the past but now that we can rely on the order we can now be more generic and more fine-grained. There is a set of delayed categories which mean at which point the delayed action will be run. We can now delay tasks after all the use statements have been seen, all the implicit statements, all the declarations and at the end of the current program unit. Delayed actions are associated to a category and a pair function-data (i.e. a closure).

Because now we can delay the initializations of the declarations, we no longer need to do odd things while checking an initializer expression. The same applies when checking the bounds of array declarations. Thanks to this, we can also make the handling of intrinsics more consistent and we can remove the previous exceptional cases.