From e77a6561a10c09e70ab74807c1913868a0944e0d Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 19:53:12 +0100 Subject: [PATCH 1/4] Support for Fortran 2008 submodules. --- waflib/Tools/fc.py | 22 ++++++++++++++++++---- waflib/Tools/fc_scan.py | 8 +++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/waflib/Tools/fc.py b/waflib/Tools/fc.py index d9e8d8c4..fd4d39c9 100644 --- a/waflib/Tools/fc.py +++ b/waflib/Tools/fc.py @@ -28,10 +28,24 @@ def modfile(conf, name): Turns a module name into the right module file name. Defaults to all lower case. """ - return {'lower' :name.lower() + '.mod', - 'lower.MOD' :name.lower() + '.MOD', - 'UPPER.mod' :name.upper() + '.mod', - 'UPPER' :name.upper() + '.MOD'}[conf.env.FC_MOD_CAPITALIZATION or 'lower'] + if name.find(':') >= 0: + # Depending on a submodule! + separator = conf.env.FC_SUBMOD_SEPARATOR or '@' + # Ancestors of the submodule will be prefixed to the + # submodule name, separated by a colon. + modpath = name.split(':') + # Only the ancestor (actual) module and the submodule name + # will be used for the filename. + modname = modpath[0] + separator + modpath[-1] + suffix = conf.env.FC_SUBMOD_SUFFIX or '.smod' + else: + modname = name + suffix = '.mod' + + return {'lower' :modname.lower() + suffix.lower(), + 'lower.MOD' :modname.lower() + suffix.upper(), + 'UPPER.mod' :modname.upper() + suffix.lower(), + 'UPPER' :modname.upper() + suffix.upper()}[conf.env.FC_MOD_CAPITALIZATION or 'lower'] def get_fortran_tasks(tsk): """ diff --git a/waflib/Tools/fc_scan.py b/waflib/Tools/fc_scan.py index 12cb0fc0..dda5df70 100644 --- a/waflib/Tools/fc_scan.py +++ b/waflib/Tools/fc_scan.py @@ -7,11 +7,13 @@ import re INC_REGEX = """(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" USE_REGEX = """(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" -MOD_REGEX = """(?:^|;)\s*MODULE(?!\s*PROCEDURE)(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" +MOD_REGEX = """(?:^|;)\s*MODULE(?!\s+(?:PROCEDURE|SUBROUTINE|FUNCTION))\s+(\w+)""" +SMD_REGEX = """(?:^|;)\s*SUBMODULE\s*\(([\w:]+)\)\s*(\w+)""" re_inc = re.compile(INC_REGEX, re.I) re_use = re.compile(USE_REGEX, re.I) re_mod = re.compile(MOD_REGEX, re.I) +re_smd = re.compile(SMD_REGEX, re.I) class fortran_parser(object): """ @@ -58,6 +60,10 @@ class fortran_parser(object): m = re_mod.search(line) if m: mods.append(m.group(1)) + m = re_smd.search(line) + if m: + uses.append(m.group(1)) + mods.append('{0}:{1}'.format(m.group(1),m.group(2)) return (incs, uses, mods) def start(self, node): From e0254f7a75e3a47011f64781fcc59d74b78af2cf Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 23:13:35 +0100 Subject: [PATCH 2/4] Missing bracket in submodule appending of fc_scan. --- waflib/Tools/fc_scan.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/fc_scan.py b/waflib/Tools/fc_scan.py index dda5df70..36893780 100644 --- a/waflib/Tools/fc_scan.py +++ b/waflib/Tools/fc_scan.py @@ -63,7 +63,7 @@ class fortran_parser(object): m = re_smd.search(line) if m: uses.append(m.group(1)) - mods.append('{0}:{1}'.format(m.group(1),m.group(2)) + mods.append('{0}:{1}'.format(m.group(1),m.group(2))) return (incs, uses, mods) def start(self, node): From 9ff9eb73ad0033bbaa598da4779cee0c092d3527 Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 23:14:19 +0100 Subject: [PATCH 3/4] Added submodules demonstrator to demos/fortran. Its only built if gfortran is used at least with version 6. --- demos/fortran/submodules/container.f90 | 13 +++++++++++++ demos/fortran/submodules/helper.f90 | 13 +++++++++++++ demos/fortran/submodules/parent.f90 | 21 +++++++++++++++++++++ demos/fortran/submodules/wscript | 20 ++++++++++++++++++++ demos/fortran/wscript | 2 ++ 5 files changed, 69 insertions(+) create mode 100644 demos/fortran/submodules/container.f90 create mode 100644 demos/fortran/submodules/helper.f90 create mode 100644 demos/fortran/submodules/parent.f90 create mode 100644 demos/fortran/submodules/wscript diff --git a/demos/fortran/submodules/container.f90 b/demos/fortran/submodules/container.f90 new file mode 100644 index 00000000..1d9387c0 --- /dev/null +++ b/demos/fortran/submodules/container.f90 @@ -0,0 +1,13 @@ +submodule (parent) container + implicit none + +contains + + module function parent_weight(p) result(w) + type(parent_type), intent(in) :: p + real :: w + + w = p%mother**2 + p%father**2 + end function parent_weight + +end submodule container diff --git a/demos/fortran/submodules/helper.f90 b/demos/fortran/submodules/helper.f90 new file mode 100644 index 00000000..b72de8c0 --- /dev/null +++ b/demos/fortran/submodules/helper.f90 @@ -0,0 +1,13 @@ +submodule (parent:container) helper + implicit none + +contains + + module function parent_distance(pa, pb) result(dist) + type(parent_type), intent(in) :: pa, pb + real :: dist + + dist = sqrt(parent_weight(pa) + parent_weight(pb)) + end function parent_distance + +end submodule helper diff --git a/demos/fortran/submodules/parent.f90 b/demos/fortran/submodules/parent.f90 new file mode 100644 index 00000000..e40fbca9 --- /dev/null +++ b/demos/fortran/submodules/parent.f90 @@ -0,0 +1,21 @@ +module parent + implicit none + + type parent_type + real :: mother + real :: father + end type parent_type + + interface + module function parent_weight(p) result(w) + type(parent_type), intent(in) :: p + real :: w + end function parent_weight + + module function parent_distance(pa, pb) result(dist) + type(parent_type), intent(in) :: pa, pb + real :: dist + end function parent_distance + end interface + +end module parent diff --git a/demos/fortran/submodules/wscript b/demos/fortran/submodules/wscript new file mode 100644 index 00000000..73f8be13 --- /dev/null +++ b/demos/fortran/submodules/wscript @@ -0,0 +1,20 @@ +#! /usr/bin/env python + +top = '.' +out = 'build' + +def options(opt): + opt.load('compiler_c') + opt.load('compiler_fc') + +def configure(conf): + conf.load('compiler_c') + conf.load('compiler_fc') + +def build(bld): + + bld( + features = 'fc fcshlib', + source = 'parent.f90 container.f90 helper.f90', + target = 'fudge', + ) diff --git a/demos/fortran/wscript b/demos/fortran/wscript index f1fb5d7c..f1223d80 100644 --- a/demos/fortran/wscript +++ b/demos/fortran/wscript @@ -78,3 +78,5 @@ def build(bld): target = 'mod/two_mods') bld.recurse('typemap') + if bld.env.FC_NAME == 'GFORTRAN' and int(bld.env.FC_VERSION[0]) >= 6: + bld.recurse('submodules') From 24ea24ff24288ade3af6b2350189233895365ef0 Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 23:36:55 +0100 Subject: [PATCH 4/4] Added more syntactic cases to the demos/fortran/submodules example. Also build a main program that uses the parent module. --- demos/fortran/submodules/container.f90 | 14 ++++++++++++++ demos/fortran/submodules/parent.f90 | 9 +++++++++ demos/fortran/submodules/submain.f90 | 18 ++++++++++++++++++ demos/fortran/submodules/wscript | 6 ++++++ 4 files changed, 47 insertions(+) create mode 100644 demos/fortran/submodules/submain.f90 diff --git a/demos/fortran/submodules/container.f90 b/demos/fortran/submodules/container.f90 index 1d9387c0..d8a6c471 100644 --- a/demos/fortran/submodules/container.f90 +++ b/demos/fortran/submodules/container.f90 @@ -3,6 +3,20 @@ submodule (parent) container contains + module procedure init + p%mother = mother + p%father = father + end procedure init + + module subroutine harmonize(p) + type(parent_type), intent(inout) :: p + real :: avg + + avg = 0.5 * (p%father + p%mother) + p%father = avg + p%mother = avg + end subroutine harmonize + module function parent_weight(p) result(w) type(parent_type), intent(in) :: p real :: w diff --git a/demos/fortran/submodules/parent.f90 b/demos/fortran/submodules/parent.f90 index e40fbca9..17b8370b 100644 --- a/demos/fortran/submodules/parent.f90 +++ b/demos/fortran/submodules/parent.f90 @@ -7,6 +7,15 @@ module parent end type parent_type interface + module subroutine init(p, mother, father) + type(parent_type), intent(out) :: p + real, intent(in) :: mother, father + end subroutine init + + module subroutine harmonize(p) + type(parent_type), intent(inout) :: p + end subroutine harmonize + module function parent_weight(p) result(w) type(parent_type), intent(in) :: p real :: w diff --git a/demos/fortran/submodules/submain.f90 b/demos/fortran/submodules/submain.f90 new file mode 100644 index 00000000..e47013a5 --- /dev/null +++ b/demos/fortran/submodules/submain.f90 @@ -0,0 +1,18 @@ +program submain + use parent + + implicit none + + type(parent_type) :: a,b + real :: dist, weight + + call init(a, 1.0, 2.0) + call init(b, 10.0, 12.0) + + call harmonize(a) + weight = parent_weight(b) + write(*,*) weight + dist = parent_distance(a, b) + write(*,*) dist + +end program submain diff --git a/demos/fortran/submodules/wscript b/demos/fortran/submodules/wscript index 73f8be13..771614e1 100644 --- a/demos/fortran/submodules/wscript +++ b/demos/fortran/submodules/wscript @@ -18,3 +18,9 @@ def build(bld): source = 'parent.f90 container.f90 helper.f90', target = 'fudge', ) + bld( + features = 'fc fcprogram', + source = 'submain.f90', + use = 'fudge', + target = 'submain', + )