Week1 - Implementing COMMON block!
Implement COMMON block
Date: May 21, 2023.
Hii, welcome to the very first blog of my GSoC'23 journey. I will be working to get LFortran compile the fortran codebase of SciPy. To begin with this, I figured out the major bugs in the codebase that is preventing LFortran to compile it and one of them was the use of COMMON block.
You might be wondering why to use COMMON block when we have modules and classes in fortran. Well, the answer is simple, COMMON block is a way to share data between different subroutines and functions. It is a global variable that can be accessed by any subroutine or function. It is a very old way of sharing data and is not recommended to use it in modern fortran code. But, SciPy is a very old codebase and it is not possible to change the whole codebase to use modules and classes. So, we have to use COMMON block to share data between different subroutines and functions.
Let's start with an example to understand how COMMON block works. Suppose we have two subroutines, one to read the data and other to print the data. We want to share the data between these two subroutines. So, we will use COMMON block to share the data. We will declare a COMMON block in both the subroutines and use it to share the data. You can refer to the code snippet below to understand how to it is done, where r() represents read subroutine and w() represents write subroutine. We use COMMON block `block` to share the data between these two subroutines.
Now, let us proceed to the implementation part. During this week, I mainly focused on successfull parsing to AST and then implementation of conversion of AST to ASR. On starting with the implementation, I realised that there are a few cases that current parser is unable to parse, example of such case is shown below: Issue: 1653
On observing we realised that if we added a `,` after declaration of a COMMON block, then it was parsed successfully. So, we decided to tweak exisiting fixed-form parser to handle this case. We added a `,` after declaration of COMMON block and then parsed it successfully. More details about it can be found at: PR: 1655
After this, we started working on conversion of AST to ASR. It was an iterative approach we started off by creating a local hash table that contains `std::string common_block_name` as key and `std::vector<\ASR::expr_t*> common_block_variables` as value. Upon encounter of a COMMON block, we populated the hash table and then at the end of every program unit, we create an `ASR::Module_t` with `common_block_variables` as public variables. Simply, we tried to perform the conversion shown below:
But this failed as we realised that COMMON block variables can't be declared like this inside module. We need to have these variables inside struct and then use that struct as public variable which is present inside module as shown below:
On further investigation we realised that to impose restrictions over decalration of COMMON blocks and to verify the correctness of declaration, we need to have `Union` of structs inside module as public variable and then access it. Assuming that the codebase of SciPy is correct, we decided to avoid this step and move forward with simple struct inside module based implemenation. Now in body of the program, we need to replace all the positions where common block variables is used with StructAccessMember present in ASR node of LFortran.
Summarizing 20.5 hours of this week work, we were able to parse COMMON block, populate hash table and create an `ASR::Module_t` with `ASR::StructType_t` inside it as public variable, which contains all the variables of COMMON block. Further more, we were able to replace common block variables with StructAccessMember for assignments. But, we are still working to make it more robust and generic. All the Issues and PRs can be found below:
I would to thank Ondřej Čertík for helping me out during this week and guiding me through the whole process.