Skip to content

NLESC-JCER/roquefort

Repository files navigation

Roquefort

A tool for Refactoring Of QUEstionable FORTran

Features

Roquefort allows to :

Installation

To install roquefort, do:

git clone https://github.com//roquefort.git
cd roquefort
pip install .

Run tests (including coverage) with:

python setup.py test

Usage

Remove Common block

Common blocks are not unusual to find in Fortran77 code. It recommended to move this common block to modules. The original Fortran code is :

subroutine func()

common /mod1/ var1, var2
common /mod2/ var3, var4

implicit real*8(a-h,o-z)

x = var1
y = var2

i = 2

end

To remove common blocks:

python refac_fortran.py --action clean_common -n mod1 -p ./example/

Leads to the code :

subroutine func()


use mod1, only: var1, var2
implicit real*8(a-h,o-z)


common /mod2/ var3, var4


x = var1
y = var2

i = 2

end

with the additional module file

module mod1
  !> Arguments: var1, var2
  use precision_kinds, only: dp
  include 'vmc.h'

   real(dp) :: var1
   real(dp) :: var2
   private

   public :: var1, var2
   save
end module mod1

Clean unused imported variable

Unused varialbe can pollute use statements. For example in the code

subroutine func()

use mod1, only: var1, var2
use mod2, only: var3

implicit none

integer :: i, j

i = var1
j = var3

end

The variable var2 of mod1 is not used. We can remove that variable with

python refac_fortran.py --action clean_use --filename ../example/test_use.f

Leading to

subroutine func()

use mod1, only: var1
use mod2, only: var3

implicit none

integer :: i, j

i = var1
j = var3

end

Remove implicit variable

Implicit declaration of variable were common but lead to unclarity in the code. We can remove all implicit declaration and automatically declare variables. For example the code

subroutine func()

use mod1, only: var1
use mod2, only: var2

implicit real*8(a-h,o-z)

x = var1
y = var2

i = 2

end

implicitly declare variables x, y and i. We can make the declaration implicit with :

python refac_fortran.py --action clean_implicit --filename ../example/test_implicit.f

Leading to :

subroutine func()

use mod1, only: var1
use mod2, only: var2

use precision_kinds, only: dp
implicit none

integer :: i
real(dp) :: x, y

x = var1
y = var2

i = 2

end

Note that the precision_kinds module needs to be created separately to look like:

module precision_kinds
   implicit none
  ! named constants for 4, 2, and 1 byte integers:
  integer, parameter :: &
       i4b = selected_int_kind(9), &
       i2b = selected_int_kind(4), &
       i1b = selected_int_kind(2)
  ! single, double and quadruple precision reals:
  integer, parameter :: &
       sp = kind(1.0), &
       dp = selected_real_kind(2 * precision(1.0_sp)), &
       qp = selected_real_kind(2 * precision(1.0_dp))
end module precision_kinds

Move variable in new module

During refactoring of large code base it is sometimes useful to move variable from one module to another. For example in the following code :

subroutine func()

use mod1, only: var1, var3, var5
use mod2, only: var2, var7

implicit real*8(a-h,o-z)

x = var1
y = var2

i = 2

end

We might wish to move var3 to a new module called modx. This can be done with

python refac_fortran.py --action move_var --var_name var3 --new_module modx --filename ../example/test_move_var.f

Leading to :

subroutine func()

use mod1, only: var1, var5
use mod2, only: var2, var7
use modx, only: var3

implicit real*8(a-h,o-z)

x = var1
y = var2

i = 2

end

Note that you need to move the variable from mod1 to modx in the module file separately.

Sort and condense your use statements

During refactoring of large code base it is sometimes useful to reorder the use statements and condense them. For example in the following code :

subroutine func()

use mod1, only: var1, var3, var5
use module2, only: var2, var7
use mod1, only: var1, var3, var5
use module2, only: var4
use very_long_module_name, only: longvar1
use xmod1, only: var8, var9
use xmod2

implicit none

x = var1
y = var2

i = 2

end

We might wish to remove duplicate imports, and condense the existing imports. This can be done with

roquefort condense_use --sort --min_only_offset=20 --max_line_length=72 --overwrite ../example/test_condense_use.f

Leading to :

subroutine func()

use mod1,    only: var1,var3,var5
use module2, only: var4,var2,var7
use very_long_module_name, only: longvar1
use xmod1,   only: var8,var9
use xmod2

implicit none

x = var1
y = var2

i = 2

end

The min_only_offset argument determines the minimum column where the only statement can start, thus aligning them vertically

Contributing

If you want to contribute to the development of roquefort, have a look at the contribution guidelines.

License

Copyright (c) 2020, Netherlands eScience Center

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Credits

This package was created with Cookiecutter and the NLeSC/python-template.

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •