fortran-src

Parsers and analyses for Fortran standards 66, 77, 90, 95 and 2003 (partial).

https://github.com/camfort/fortran-src#readme

LTS Haskell 20.26:0.12.0
Stackage Nightly 2024-11-12:0.16.3
Latest on Hackage:0.16.3

See all snapshots fortran-src appears in

Apache-2.0 licensed by Mistral Contrastin, Matthew Danish, Dominic Orchard, Andrew Rice
Maintained by [email protected], Ben Orchard
This version can be pinned in stack with:fortran-src-0.16.3@sha256:873b2c95fd313beac794f5efe75fc4b9171a96c6db27d99e2d4231c7f40072e5,12633

Module documentation for 0.16.3

fortran-src

CI status badge

Provides lexing/parsing and early static analyses of Fortran code. The following Fortran standards are covered:

  • FORTRAN 66 (ANSI X3.9-1966)
  • FORTRAN 77 (ANSI X3.9-1978 / ISO 1539:1980)
  • Fortran 90 (ISO/IEC 1539:1991)
  • Fortran 95 (ISO/IEC 1539-1:1997
  • Fortran 2003 (partial)

Parsing is configurable, and you can select the Fortran standard to target, including special extended modes for nonstandard FORTRAN 77.

Includes data flow and basic block analysis, a renamer, and type analysis.

This package primarily exports a Haskell library, but also builds an executable that can be used for testing and debugging. For example usage, see the CamFort project, which uses fortran-src as its front end.

Obtaining

We provide prebuilt binaries for Windows, Mac and Linux.

Usage

Add fortran-src as a dependency in your Haskell project. We’re on Hackage and also on Stackage.

Command-line tool

You can also invoke fortran-src on the command line.

For features that output graphs, the intended usage is to pipe it into the command dot -Tpdf and redirect that into a PDF file. The dot command is part of the GraphViz project, please see their manual for the many other options that can be explored for visualisation purposes.

Usage: fortran-src [OPTION...] <file>
                          --version                        show fortran-src version
  -v VERSION, -F VERSION  --fortranVersion=VERSION         Fortran version to use, format: Fortran[66/77/77Legacy/77Extended/90]
  -a ACTION               --action=ACTION                  choose the action, possible values: lex|parse
  -t                      --typecheck                      parse and run typechecker
  -R                      --rename                         parse and rename variables
  -B                      --bblocks                        analyse basic blocks
  -S                      --supergraph                     analyse super graph of basic blocks
  -r                      --reprint                        Parse and output using pretty printer
                          --split-long                     when using pretty printer, split long lines via continuations
                          --dot                            output graphs in GraphViz DOT format
                          --dump-mod-file                  dump the information contained within mod files
  -C[CPP-OPTS]            --cpp[=CPP-OPTS]                 run the C Pre Processor on the Fortran files first
  -I DIR                  --include-dir=DIR                directory to search for precompiled 'mod files'
  -c                      --summarise, --compile-mod       build an .fsmod file from the input
  -o FILE                 --output-file=FILE               name of output file (e.g. name of generated fsmod file)
                          --make-mods, --make              determine dependency order of modules and automatically build .fsmod files
                          --show-make-graph                dump a graph showing the build structure of modules
                          --show-make-list                 dump a list of files in build dependency order (topological sort from the dependency graph)
                          --show-block-numbers[=LINE-NUM]  Show the corresponding AST-block identifier number next to every line of code.
                          --show-flows-to=AST-BLOCK-ID     dump a graph showing flows-to information from the given AST-block ID; prefix with 's' for supergraph
                          --show-flows-from=AST-BLOCK-ID   dump a graph showing flows-from information from the given AST-block ID; prefix with 's' for supergraph

If you do not pass a --fortranVersion flag, the version will be guessed from the file name:

  • Files ending in *.f are parsed with extended FORTRAN 77 syntax.
  • Files ending in *.f90 are parsed with Fortran 90 syntax (and respectively for *.f2003/*.f03, *.f2008/*.f08).
  • Unknown extensions are parsed like *.f files.

Building

You will need the GMP library plus header files: on many platforms, this will be via the package libgmp-dev.

Haskell library dependencies are listed in package.yaml. fortran-src supports building with Stack or Cabal.

fortran-src supports GHC 9.0 through GHC 9.4. 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 to build fortran-src.

For installing GHC and build tools, we strongly recommend ghcup.

When latest recommended is used, it means the latest version of the tool that ghcup tags with recommended. This sometimes lags behind the latest-tagged version. With ghcup installed, run ghcup list for a better understanding.

Following are general guides for any OS that provides the relevant tools. If you have trouble, consider checking the CI workflow files in .github/workflows.

Stack

We support the latest recommended version of Stack (as of 2021-09-17, Stack 2.7). Generally, any Stack 2.x should work. (Stack 1.x may work with minor alternations – you may have to download the resolver manually.)

stack build

For an interactive shell:

stack build
stack ghci

Note that running stack ghci before running stack build won’t work properly, due to stack ghci not running build tools like Alex and Happy. So parser modules will not be built, and you’ll receive an error after building the other modules. You can cheat a bit and run stack build until you see Building library for [...] (= preprocessing has finished), then hit <Ctrl-C> to stop the build and run stack ghci as usual.

Cabal

We support the latest recommended version of Cabal (as of 2021-09-17, Cabal 3.4)

cabal build

Testing

Unit tests are stored in test. Run with stack test or cabal test.

Usage

As a dependency

fortran-src is available on Hackage and Stackage, so for Cabal or Stack projects you should only need to add fortran-src to your project dependencies.

If you need a specific version of fortran-src in a Stack setup, you can stuff a Hackage reference into stack.yaml using extra-deps, like:

resolver: ...
...

extra-deps:
- ...
- fortran-src-$VERSION

As a CLI tool

If you have Cabal properly configured, you should be able install fortran-src from Hackage:

cabal install fortran-src

We provide prebuilt binaries for some platforms: see the Releases tab.

Otherwise, you can build from source and use convenience commands like cabal run, stack run. See #Building for details.

Contributing

We welcome bug reports, fixes and feature proposals. Add an issue or create a pull request on the GitHub repository.

Support

You may be able to find maintainers on the Libera.Chat IRC network. Check in #fortran-src and #camfort . Otherwise, you could get into contact with one of the team on the CamFort team page – or create an issue describing your problem and we’ll have a look.

For maintainers

See doc/maintainers.md in camfort/camfort.

Changes

0.16.3 (Sep 30, 2024)

  • Store source names for local declarations in .fsmod files.
  • Constant evaluator now handles real-integer exponent and real-real exponent expression

0.16.2 (Sep 13, 2024)

  • Small change to allow a path to be added when building mod-file naming map
  • Improvements to the power of constant propagation and constant expression evaluation.

0.16.1 (Sep 04, 2024)

  • Minor fix to fromConstReal which was partial.
  • Added Ord instance for AST and all its sub data types, allowing, for example, ASTs to be in containers like Data.Set

0.16.0 (Sep 04, 2024)

  • Added --show-make-list option to give a topological sort on the dependency graph for a source tree
  • Added --version option
  • Some robustness improvements around mod files #286
  • Helpers to work with the partial evaluation representation #285

0.15.1 (Jun 22, 2023)

  • remove unused vector-sized dependency

0.15.0 (May 04, 2023)

  • handle more INT intrinsic forms #263
  • add more Language.Fortran.Common.Array utils #263
  • Analysis.SemanticTypes: use type Dimensions = Dims NonEmpty (Maybe Int) instead of type Dimensions = Dims NonEmpty Int #263

0.14.0 (Mar 21, 2023)

  • provide extended evaluated array dimensions type at Language.Fortran.Common.Array (#261, @raehik)
    • replace the previous Dimensions type in Language.Fortran.Analysis.SemanticTypes

0.13.0 (Mar 14, 2023)

  • better handling for line directives in free form lexer (#248, @mrd)
  • don’t inline solo includes in relevant F77 parsers (#245, @RaoulHC)
  • add -C=opts CLI option for passing CPP arguments (#250, @mrd)
  • fix reformatting of 73 character long lines in naive mixed form reformatter (#251, @ksromanov)
  • assume extended Fortran77Legacy rather than Fortran77 for *.f, *.for etc. files (#260)
  • allow comment lines between continuation lines in F77 parser (in standard) (#257, @RaoulHC)
  • refactor Fortran type & value representation & expression evaluator without Fortran kind-indexed GADTs; replace constant folder (#253, @raehik)

0.12.0 (Oct 19, 2022)

  • clean up F77 include inlining (#245, @RaoulHC)
    • directly export F77 include parser at f77lIncludesNoTransform
    • f77lIncIncludes :: String -> ByteString -> IO [Block A0] should now be defined by the user e.g. \fn bs -> throwIOLeft $ f77lIncludesNoTransform fn bs
  • Language.Fortran.Analysis.SemanticTypes: alter SemType constructor TArray to support assumed-size (e.g. integer arr(*)) arrays (#244)
  • Language.Fortran.Rewriter: fix inline comment padding (#242, @RaoulHC)

0.11.0 (Oct 10, 2022)

  • add strong Fortran value & type representation at Language.Fortran.Repr (currently unused) (#235, @raehik)
    • operations are accurate to actual Fortran compiler behaviour e.g. integers are stored fixed-width based on kind, so overflow behaviour is free
    • can recover a value’s precise type (e.g. INTEGER(8), including kind) via pattern matching
  • bump minimum compiler version to GHC 9.0
  • improved comment handling in fixed form lexer: parse more comment syntax, case sensitive, parse beyond column 72 (#237, @RaoulHC)
  • allow ExpDataRef constructor in varName (fixes a crash in type analysis #238)
  • add Annotated, Spanned instances for intermediate AST data type ArgumentExpression
  • export statement-level “pre-prepared” parsers (previously, you would have to define the parser yourself using parser utils and the Happy parser export)
  • export Language.Fortran.Parser.byVerFromFilename :: Parser (ProgramFile A0), a replacement for the removed Language.Fortran.Parser.Any.fortranParser

0.10.2 (Aug 18, 2022)

  • fix missing parentheses when pretty printing certain syntax #233
  • fix missing export of ParseErrorSimple in Parser
  • fix inlined includes block order #234

0.10.1 (Aug 1, 2022)

  • export ParseErrorSimple from Parser, not internal module Parser.Monad
  • rewriter fixes #232

0.10.0 (Jul 13, 2022)

  • Fix parsing kind parameters like a_1 on literals. Previously, that would be parsed as a kind parameter on a kind parameter. Now we don’t do that, following gfortran’s behaviour.
    • Kind parameter representation is changed to explicitly say if it’s an integer kind or named constant kind, rather than reusing Expression.
  • BOZ literals
    • add some syntactic info (to enable checking standards conformance)
    • export bozAsTwosComp function for reading as two’s complement integer
  • allow named constants in complex literals
  • document FirstParameter, SecondParameter behaviour/safety, fix erroneous instances
  • fiddle with record selectors for some AST nodes (for better Aeson instances)
  • pair IF/CASE conditions with their blocks, rather than splitting between two lists
  • ExpFunctionCall and StCall store procedure arguments in AList ([a]) instead of Maybe AList (Maybe [a])
    • Matching is safer because empty lists are always [] instead of Nothing or Just []. Construction for empty lists is more awkward.
    • A better solution would be to use an AList-like that also stores extra syntactic information.
  • refactored a number of small AST nodes
    • ImpElement
    • ForallHeader
  • add Hackage documentation to many individual AST constructors and fields
  • improve include parser interface #227
  • improve newline handling for block parsers #228
  • fix some source span misses #225

0.9.0 (Feb 14, 2022)

  • Restructure parsing-related modules for code deduplication and better user experience.
    • Now all user-facing parsers and the combinators to create them are in a single module at Language.Fortran.Parser.
    • The Happy parsers have fewer dependencies, so should no longer require a recompile due to apparently unrelated changes.
  • Remove some deprecated shims (from the restructured modules).
  • Merge fortran-src-extras Language.Fortran.Extras.ModFiles.Extras module into Language.Fortran.Util.ModFile.

0.8.0 (Jan 04, 2022)

  • Merge declarator constructors. Now you differentiate between array and scalar declarators by looking at the relevant field. See Language.Fortran.AST.Declarator for details.
  • Add bozAsNatural :: Num a => Boz -> a function to resolve BOZ constants as integers

0.7.0 (Dec 09, 2021)

  • No longer treat ! in strings as comments in continuation reformatter (thanks @envp) #179
  • CI builds on Mac; more release automation #181 #189
  • Handle nonstandard kind parameter in parsing & type analysis #188
  • Fix renamer ambiguity resulting in unusual name-related breakages (e.g. ValVariable not getting transformed to ValIntrinsic) #190
  • Fully parse logical literals early (don’t leave as String) #185
    • Code that touches ValLogical will have to be updated – it should mean removal of user-side parsing.
  • Explicitly parse integer literal kind parameter #191
    • The String representation stored should now always be safe to read to a Haskell Integral.
  • Provide real literals in a semi-parsed “decomposed” format #193
    • Kind parameters are also made explicit.
    • Libraries with custom real literal parsing should be able to replace it with readRealLit :: (Fractional a, Read a) => RealLit -> a.
  • BOZ literal constants receive their own Value constructor (instead of sharing one with integers) #194
    • Also parse them to an intermediate data type and provide handling functions.

Note that kind parameters are disabled in fixed form parsers (F77, F66), so for codebases targeting older standards, many changes will be along the lines of ValInteger x -> ValInteger x _.

0.6.1 (Sep 17, 2021)

  • Properly include test data in package dist (in preparation for placing on Stackage)

0.6.0 (Sep 03, 2021)

  • IF and CASE block constructs are now parsed as blocks at parsing instead of as a post-parse transformation (no intermediate statement representation) #154
  • add ASSOCIATE block construct (Fortran 2003 parser only) #165
  • CommonGroup AST nodes now store Declarators instead of Expressions #173
    • various bug fixes related to their typing as a result
  • CI now building on Windows, and save Linux & Windows executables for each build
  • various bugfixes (#34, #155)

0.5.0 (Jun 30, 2021)

  • Introduce a second-stage type representation including kind info alongside types, and resolving some types to semantic type with preset kinds (e.g. DOUBLE PRECISION -> REAL(8)).
    • Module is at Language.Fortran.Analysis.SemanticTypes . Includes utils and instances.
    • The type analysis in Language.Fortran.Analysis.Types uses this representation now (IDType stores a SemType instead of a BaseType).
  • Move CharacterLen from parsing to type analysis.
    • This makes BaseType now a plain tag/enum with no extra info.
  • Add extended Fortran 90 real literal parser (parses kind info).
  • Export some infer monad utils (potentially useful for running just parts of type analysis)
  • Parser & lexer tweaks
    • Fortran 77 parser should no longer attempt to parse kind selectors for DOUBLE types
    • Fix an edge case with the fixed form lexer (#150)

0.4.3 (May 25, 2021)

  • Add Haddock documentation to AST module. Many parts of the AST now have commentary on meaning and usage, and the Haddock page is sectioned.
  • Add STATIC statement (should be similar/identical to SAVE attribute) to fixed-form lexer, support in Fortran 77 Extended parser.
  • Rewrite post-parse transformation handling. Parser modules now export more parsers which allow you to select post-parse transformations to apply, intended to enable quicker parsing if you know you don’t need to certain transformations.
  • Support percent data references in fixed-form lexer, enable in Fortran 77 parser
  • Now also testing on GHC 9.0
  • Cache INCLUDE-ed files to avoid unnecessary re-parsing

0.4.2 (March 03, 2021)

  • FortranVersion from ParserMonad moved to its own module Language.Fortran.Version. ParserMonad will re-export it for now.
  • Version.deduceVersion renamed to deduceFortranVersion due to often being imported non-qualified. deduceVersion remains as an alias.
  • Provide a continuation reformatter in PrettyPrint. Runs on Strings and doesn’t guarantee the output is a valid program, so not enabled by default.
  • Add a diff-like rewriter, similar to reprinter but uses replacements rather than an annotated AST.
  • Various internal de-duplication and changes.

0.4.1

  • Ignore comments in structure declaration PR#107 (thanks Jason Xu)

0.4.0 (August 29, 2019)

  • ModGraph: parse Fortran files and assemble them into a dependency graph in order to construct automated ‘build’ plans for analysis and summarisation (e.g. with –make-mods option).
  • Change name of compilation to summarisation. Remains as ‘-c’ option.
  • Allow multiple files and directories to be specified on command line.
  • Search includedir recursively for fsmod files.
  • Change format of fsmod-files so that they can contain [ModFile] since multiple Fortran files can be summarised into a single mod file.
  • Introduce strictness and NFData dependencies across the board.
  • Use Pipes to process large amounts of files in order to control memory usage and more efficiently process things.
  • Parsing rules for StructStructures (thanks Raoul Charman)

0.3.0 (June 13, 2019)

  • Add partial Fortran2003 support.
  • Introduce datatype for BBGr instead of prior type alias for Gr.
    • Now split into three fields: bbgrGr, bbgrEntries and bbgrExits
    • May require refactoring of code to use bbgrGr field where a Gr was expected before.
  • Introduce pragmaOffset field for Position, allowing pragmas to specify an apparent file and line-number.
    • May require refactoring of code that uses the Position constructor.
    • Fifth field is Maybe (Int, String), containing a line-offset and a target filename when present.
    • It’s designed such that most Position-based transformations are not affected by the pragmaOffset.
    • They may need to preserve the field, though, as it passes through functions.
    • Default value is ‘Nothing’.
  • Add –show-flows-to/–show-flows-from features
    • Visualise the dataflow use/def chains using GraphViz.
  • Add –show-block-numbers feature.
    • Allows user to get AST-block numbers easily in order to use them with the above visualisation features.
  • Fix several bugs with dataflow analysis that had accumulated.
  • Eliminate StContinue and StEnddo are eliminated during GroupLabeledDo transformations.
    • To be consistent with unlabeled Do.
  • Parse and discard C-comments as a convenience feature for when fortran-src must interact with the output of C preprocessors that insert spurious comments.
  • Add type propagation into type analysis, annotating every expression with a type.
    • Additional interface: analyseTypesWithEnv to access a list of type errors found.
  • Add dimensional information to CTArray and length/kind to TypeCharacter.
  • Stricter checking of the grouping transform - if any statements that should be grouped are not grouped, raise an error.
  • Support pragmas that alter the current ‘filename and position’ tracker, often used by preprocessors to help pinpoint original code locations.
    • Uses a relative offset field called ‘posPragmaOffset’ so that relative measures continue to function correctly.
  • Add constant propagation / parameter variable analysis.
  • Add -c feature to compile ‘fsmod files’ with renaming and type info.

0.2.1.1 (May 18, 2018)

  • Extend Fortran 95 support
  • Extend support for legacy extensions

0.2.1.1 (December 13, 2017)

  • Fortran95Experimental module renamed to Fortran95
  • No infinite loops due to symlinks.
  • Fortran 95 support.
    • AST extended to support more non-standard statements internally.