Giter Club home page Giter Club logo

fortran-src's Introduction

CamFort

CamFort is a refactoring and verification tool for scientific Fortran programs. It currently supports Fortran 66, 77, 90, 95 and 2003 (somewhat) with various legacy extensions.

It is a research project developed in the University of Cambridge and University of Kent.

Obtaining

Recommended install method by OS:

  • Windows: prebuilt bundles (includes dependencies) at Releases: download ones beginning camfort-bundle-windows
  • Mac: via Homebrew: brew install camfort/camfort/camfort
  • Linux: prebuilt binaries at Releases. See Wiki: Building for how to install library dependencies for your OS.

We provide prebuilt binaries for Windows, Mac and Linux. For Windows, we also provide archives that bundle the CamFort executable together with all of its dependencies.

CamFort is also available through Homebrew (formula):

brew install camfort/camfort/camfort

An older (~2019) version of CamFort is available on Docker at camfort/camfort.

A new Docker image for developers (still work-in-progress) is available at ghcr.io/camfort/camfort:dev. Suggested invocation is:

  • podman: podman run --volume $(pwd):/host --workdir /host ghcr.io/camfort/camfort:dev <CamFort arguments>

Usage

CamFort is a command-line tool, so invoke it from your favourite shell or command prompt. Detailed usage information is available on the wiki.

Building

(If you want a recent build and don't want to sit through the compilation process, you may wish to instead check the Actions tab and download the relevant build for your system from a recent workflow run.)

This section only covers building briefly. See Wiki: Building for full details.

CamFort supports GHC 8.4 through GHC 8.10, and builds with both Stack and Cabal. We regularly test at least the minimum and maximum supported GHCs. Releases prior to/newer than those may have issues. (We welcome fixes that would let us support a wider range of compilers!)

You will likely need at least 3 GiBs of memory and some patience to build CamFort.

CamFort depends on the following foreign libraries:

  • FLINT >= 2.5
  • LAPACK
  • BLAS
  • Z3 >= 4.5 (executable)

These should be built for your system, but installation method varies. System-specific guides are provided on the wiki. (Alternatively, you could check the GitHub Actions workflows.) On Ubuntu:

apt install libflint-dev liblapack-dev libopenblas-dev z3

Then stack build for Stack, or cabal build for Cabal.

Tab Completion (Bash)

To enable Bash autocompletion for camfort, add the following to your .bashrc or .bash_profile file:

eval "$(camfort --bash-completion-script=$(which camfort))"

Contributing

We appreciate any bugs you encounter and kindly request you to submit it as an issue.

Pull requests are much appreciated, but please contact us first if it is a substantial change. Make sure to run the test suite before you submit.

If you have scientific code that you would like us to analyse, we would be happy to add it to CamFort corpus. This helps us finding useful ways to extend CamFort as well as ensuring it is robust.

Support

For maintainers

See doc/maintainers.md.

fortran-src's People

Contributors

azeemba avatar burz avatar dorchard avatar envp avatar gridaphobe avatar guiltydolphin avatar harry-clarke avatar jasonqxu avatar ksromanov avatar lukaszkolodziejczyk avatar mrd avatar raehik avatar traveltissues avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fortran-src's Issues

Prelude.read: no parse on reals with no leading 0

I think this error is coming from fortran-src to do with the real-parsing functionality though it appears when I am using camfort (e.g., units-infer or something). Example

program f
   implicit none
   real :: x = .1
end program

camfort fails with
camfort: Prelude.read: no parse

INCLUDE statements not parsed

      program foo
      implicit none
      include 'bar.cmn'
      end  

This is part of Fortran 90 (see p.43 of the standard, ftp://ftp.nag.co.uk/sc22wg5/N001-N1100/N692.pdf)
However, it seems fairly common to use this in Fortran 77 too.... although it is not standard. Perhaps we can allow it in Fortran 77 extended mode?

ValInteger should not have an annotation

Value nodes are meat to be embedded in ExpValue at all times, hence none of them need annotation. Enclosing expressions should have the annotations.

At some point @mrd changed this for ValVariable (I believe for renaming), it would be nice if we go back to original design as right now all captures/generations of ValIntegers end up copying the same annotation for ValVariable and its enclosing ExpValue.

BBlocks analysis produces refuted pattern for some kinds of nested

module test
  implicit none
  contains

   subroutine foo 
     integer:: i, j

     do i = 1, 2
        do j = 1, 2
        end do
     end do

   end subroutine

end module

Via camfort's stencil analysis, this throw up the error:

$ camfort stencils-infer test.f90 out
...
camfort: src/Language/Fortran/Analysis/BBlocks.hs:39:47-82: Irrefutable pattern failed for pattern Just gr
``

Empty module "blocks" unsupported

This is accepted by NAG but not fortran-src:

module bug
contains
! foo
subroutine a()
integer :: x
end subroutine a
end module bug

Off-by-one error in `Util.Position.getSpan`?

Util.Position.getSpan seems to have an off-by-one error, which gets revealed in the source spans that are spat out by units-check as part of the constraints.

They are all short by one, e.g. (12:9)-(12:19) should really be (12:9)-(12:20).

This is assuming that we start both lines and columns at 1 (from my observation Vim and Atom do this, but Emacs starts lines at 1 and columns at 0).

More permissive INCLUDE?

I note in the Fortran 90 standard (ftp://ftp.nag.co.uk/sc22wg5/N001-N1100/N692.pdf, section 3.4) that "An INCLUDE line is not a Fortran statement. An INCLUDE line must appear on a single source line where a statement may appear;” We only allow it to appear in the place of a NONEXECUTABLE_STATEMENT and I just saw some code where it appears between end program and subroutine…. From the standard it kinda sounds like you can do an include where any kind of statement can appear (include a PROGRM statement), so maybe we need to be more flexible than we are at the moment - without creating a shift/reduce :s

Flow analysis seems incorrect when inside modules.

There appears to be some problems with building flows graphs (and other related information) when working inside subroutines/functions inside a Fortran 90 module. I have extended DataFlowSpec.hs
with a module-subroutine-Fortran90 version of the loop4 test. I don't expect the block numbers to be the same, but the flows graph is clearly now a different shape. Also there are some fromJust exceptions getting thrown up in some cases.

IVMAP only getting partially built

Example program:

program foo
  implicit none
  integer :: i, j
  real, dimension(100) :: a, b
  do i=1,100
     do j=1,100
        a(i) = b(i) + b(1)
     end do
  end do
end program

At some point in the last month (I think), a bug has been introduced which means that the induction-variable analysis is wrong. See fortran-src -S foo.90:

...
ivMap: fromList [(5,fromList ["foo_j2"])]

i is missing.

Subroutines without arguments not parsing

In 77 and 90, subroutines with no arguments fail to parse:

subroutine foo 
implicit none
integer :: i
end

gives
ProgramFileforpar: 2:1: Parsing failed.Last parsed token: TNewline (1:15,1:15).
With arguments (e.g., subroutine foo (v)) is fine.

Empty 'if' block causes exception

For example

program emptyIf
  implicit none
  if (.true.) then
  end if

end program emptyIf

throws up:

$ fortran-src EmptyIf.f90 
ProgramFilefortran-src: Trying to find how long an empty list spans for.
CallStack (from HasCallStack):
  error, called at src/Language/Fortran/AST.hs:500:17 in main:Language.Fortran.AST

Identifiers greater than 29 letters are rejected [F90]

The specification states 31 as the maximum length [ftp://ftp.nag.co.uk/sc22wg5/N001-N1100/N692.pdf, p.18], but identifiers of length 30 and 31 are currently rejected.

program simple
  implicit none
  ! 29 characters is fine
  integer :: abcdefghijklmnopqrstuvwxyzAAA
  ! 30 breaks
  integer :: abcdefghijklmnopqrstuvwxyzAAAA
end program 

dataFlowSolver exception

The code in computational-physics-1/fortran77/code214.f raises a dataFlowSolver exception that I can't debug, see: fortran-src code214.f -S

Grouped array subscript

I've noticed some code using an array subscript a bit like the following:

program arra
  integer, dimension(5) :: x
  integer :: i
  x([1,2,5]) = 42
end program

This assigns to 1, 2 and 5 indices at the same time. I haven't found which standard (if any) introduces this. But I suspect it's Fortran 95.

Support .CMN files

This is not in the standard as far as I can see, but most compilers support naked common block definitions inside of '.CMN' files, which can then be be included via an include statement. I think we need this support to make common-block elimination more useful. Probably not a very big change.

Cannot parse program units that do not have a named "end".

Bug in Fortran90.y. Small example:

module simple
  implicit none
end module

This raises pattern matching error in unitNameCheck. I think the fix should allow more than just TId to be matched, with some cases for other kinds of "end" which are not named.

Cannot parse one-armed-if with assignment to array.

program simple
  implicit none
  integer, dimension(1) :: x
  if (.true.) x(1) = 1
end program simple

fails with:
ProgramFileforpar: 4:15: Lexing failed. Last parsed token: TRightPar (4:13,4:13).

Can't track down why this is. The parsing for an if with just the "true" branch seems fine. A possible shift/reduce problem? Doesn't appear for assignments to non-arrays or assignments to arrays with multi-armed if.

Error messages for badly grouped DO blocks are not informative.

For the following program:

      program goto
      implicit none
      integer i, j

      do 10 i = 0, 10
      do 20 j = 0, 20
 10   continue
 20   continue
      end

Compare the output of fortran-src with gfortran:

174:tmp dorchard$ fortran-src goto-bad.f
ProgramFilefortran-src: src/Language/Fortran/Transformation/Grouping.hs:(186,3)-(189,89): Non-exhaustive patterns in case

vs.

174:tmp dorchard$ gfortran goto-bad.f
goto-bad.f:8:72: Error: End of nonblock DO statement at (1) is interwoven with another DO loop
goto-bad.f:10:9:

       end
         1
Error: END DO statement expected at (1)
f951: Error: Unexpected end of file in ‘goto-bad.f’

Inconsistent AST node for label

Fortran 90 parser uses ValInteger while Fortran 66/77 parsers use ValLabel. I'd like to eliminate ValLabel altogether and at some point it should become an annotation.

I can't do this at this point because there are five instances in BBlocks that I don't know if they are safe to remove or what. If they can be changed to ValInteger please let me know.

Add Parse<->Print isomorphism tests

@dorchard As discussed, this is a suggestion to add tests to help ensure consistency of the parser/printer.

Gen->Print->Parse

We could use QuickCheck to generate syntax trees, then 'pretty' show them in a canonical way and parse them. We would expect the parsed syntax trees to be the same (modulo some information such as position) as the original syntax tree.

File->Parse->Print

Assuming we had example programs in a 'pretty' canonical form, we would expect parsing the files, then printing them, to give the same text as the original file.

Integer labels in Fortran 90 cause parser error

Small example:

program example
  implicit none

  integer :: i = 12
  10  if (i .gt. 10) continue
end program

ProgramFilefortran-src: 6:1: Parsing failed.Last parsed token: TNewline (5:30,5:30).

I can't figure out why this is happening as it looks all fine in the grammar. Lexing issue? Strangely the parse error points to the newline at the end of the line, but the issue seems to do with the integer label.

STOP should permit a character string

program simple
  implicit none
  STOP 'Computer says no.'
end program simple

Breaks at the string. Section 8.4 of Fortran 90 spec allows for a scalar-char-constant here.

Problem parsing `case` (Fortran 90)

program simplecase
  implicit none
  integer :: d = 0
  select case (d)
   case (0)
     d = 1
  end select
end program simplecase

Gives error:
ProgramFileforpar: 5:12: Parsing failed.Last parsed token: TRightPar (5:11,5:11).

I believe the problem here is that RANGE in Fortran90.y does not allow singleton ranges.
I suggest extending the non-terminal with a production for EXPRESSION.

genBackEdgeMap fails on recursive subroutines

Example:

program gbe
  implicit none
  contains
   recursive subroutine foo(x)
     integer :: x
     if (x == 0) then 
       x = x
     else
       call foo(x-1)
     end if
   end subroutine foo
end program gbe

fortran-src gbe.f90 -S fails with an exception genBackEdgeMap coming from the function of the same name- I guess we need to compute a fixpoint in this case when we currently are not?

Eliminate UNIT node altogether

UNIT node is only used in backspace, rewind, and endfile statements. It seems this can be eliminated and merged with generic control information lists.

Problem with analyseBBlocks and intrinsics / function call disambiguation and flows graph

Consider the following example from camfort:

program bug
  implicit none
  integer :: i
  real, dimension(2) :: a, b
  real :: x
  do i = 1, 2
    x = abs(a(i))
    b(i) = x
  end do
end program

We should infer a specification of != stencil readOnce, pointed(dim=1) :: a here but we don't because there are no subscripts flowing to b(i). I've narrowed this down to a problem with the basic blocks / flows graph I think. Basically, the transformations carried out by processFunctions of BBlocks don't seem to be interacting well with the flows graph here. Perhaps the newly created statements aren't getting picked up in the flows graph?

DO LABEL WHILE not supported

Fortran 90 standard allows the following kind of thing:

      program dowhile
      implicit none
      integer :: i = 0
      DO  200  WHILE (i .lt. 10)
         i = i + 1
  200  write (*,*), i
      end

We can't parse a DO WHILE with a label in it yet. Should we allow this in F77 extended too as well as F90?

Comments following `contains` fail.

program simple
  implicit none
  contains
  ! Comments
end program simple

raises error:
ProgramFileforpar: 4:13: Parsing failed.Last parsed token: TComment (4:3,4:12) "! comments".

Note also that the comment is presented here in lowercase. Is there "too much" lowercase conversion happening?

haddock failure

src/Language/Fortran/Analysis/Types.hs:87:3: error:
    parse error on input ‘-- | any (not . isIxSingle) (aStrip ixAList) = recordCType CTArray (varName v)  -- it's an array (or a string?) FIXME’

ping @phadej

CASE statements on multiple values fail to parse (Fortran 90)

Example program:

program foo
  implicit none
  integer :: i = 0
  select case(i)
  case(0,1)
     WRITE (*,*) "0 or 1"
  case default
     WRITE (*,*) "anything else"
  end select
end program

Looking at the parser this does seem to be accounted for, so I'm not sure why it is failing.
Error is:
ProgramFileforpar: 5:10: Parsing failed.Last parsed token: TComma (5:9,5:9).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.