Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
f90mod_rules.py270 linesDownload Raw Back to f2py
1"""
2Build F90 module support for f2py2e.
3
4Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
5Copyright 2011 -- present NumPy Developers.
6Permission to use, modify, and distribute this software is given under the
7terms of the NumPy License.
8
9NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
10"""
11__version__ = "$Revision: 1.27 $"[10:-1]
12
13f2py_version = 'See `f2py -v`'
14
15import numpy as np
16
17from . import capi_maps, func2subr
18
19# The environment provided by auxfuncs.py is needed for some calls to eval.
20# As the needed functions cannot be determined by static inspection of the
21# code, it is safest to use import * pending a major refactoring of f2py.
22from .auxfuncs import *
23from .crackfortran import undo_rmbadname, undo_rmbadname1
24
25options = {}
26
27
28def findf90modules(m):
29    if ismodule(m):
30        return [m]
31    if not hasbody(m):
32        return []
33    ret = []
34    for b in m['body']:
35        if ismodule(b):
36            ret.append(b)
37        else:
38            ret = ret + findf90modules(b)
39    return ret
40
41
42fgetdims1 = """\
43      external f2pysetdata
44      logical ns
45      integer r,i
46      integer(%d) s(*)
47      ns = .FALSE.
48      if (allocated(d)) then
49         do i=1,r
50            if ((size(d,i).ne.s(i)).and.(s(i).ge.0)) then
51               ns = .TRUE.
52            end if
53         end do
54         if (ns) then
55            deallocate(d)
56         end if
57      end if
58      if ((.not.allocated(d)).and.(s(1).ge.1)) then""" % np.intp().itemsize
59
60fgetdims2 = """\
61      end if
62      if (allocated(d)) then
63         do i=1,r
64            s(i) = size(d,i)
65         end do
66      end if
67      flag = 1
68      call f2pysetdata(d,allocated(d))"""
69
70fgetdims2_sa = """\
71      end if
72      if (allocated(d)) then
73         do i=1,r
74            s(i) = size(d,i)
75         end do
76         !s(r) must be equal to len(d(1))
77      end if
78      flag = 2
79      call f2pysetdata(d,allocated(d))"""
80
81
82def buildhooks(pymod):
83    from . import rules
84    ret = {'f90modhooks': [], 'initf90modhooks': [], 'body': [],
85           'need': ['F_FUNC', 'arrayobject.h'],
86           'separatorsfor': {'includes0': '\n', 'includes': '\n'},
87           'docs': ['"Fortran 90/95 modules:\\n"'],
88           'latexdoc': []}
89    fhooks = ['']
90
91    def fadd(line, s=fhooks):
92        s[0] = f'{s[0]}\n      {line}'
93    doc = ['']
94
95    def dadd(line, s=doc):
96        s[0] = f'{s[0]}\n{line}'
97
98    usenames = getuseblocks(pymod)
99    for m in findf90modules(pymod):
100        sargs, fargs, efargs, modobjs, notvars, onlyvars = [], [], [], [], [
101            m['name']], []
102        sargsp = []
103        ifargs = []
104        mfargs = []
105        if hasbody(m):
106            for b in m['body']:
107                notvars.append(b['name'])
108        for n in m['vars'].keys():
109            var = m['vars'][n]
110
111            if (n not in notvars and isvariable(var)) and (not l_or(isintent_hide, isprivate)(var)):
112                onlyvars.append(n)
113                mfargs.append(n)
114        outmess(f"\t\tConstructing F90 module support for \"{m['name']}\"...\n")
115        if len(onlyvars) == 0 and len(notvars) == 1 and m['name'] in notvars:
116            outmess(f"\t\t\tSkipping {m['name']} since there are no public vars/func in this module...\n")
117            continue
118
119        # gh-25186
120        if m['name'] in usenames and containscommon(m):
121            outmess(f"\t\t\tSkipping {m['name']} since it is in 'use' and contains a common block...\n")
122            continue
123        # skip modules with derived types
124        if m['name'] in usenames and containsderivedtypes(m):
125            outmess(f"\t\t\tSkipping {m['name']} since it is in 'use' and contains a derived type...\n")
126            continue
127        if onlyvars:
128            outmess(f"\t\t  Variables: {' '.join(onlyvars)}\n")
129        chooks = ['']
130
131        def cadd(line, s=chooks):
132            s[0] = f'{s[0]}\n{line}'
133        ihooks = ['']
134
135        def iadd(line, s=ihooks):
136            s[0] = f'{s[0]}\n{line}'
137
138        vrd = capi_maps.modsign2map(m)
139        cadd('static FortranDataDef f2py_%s_def[] = {' % (m['name']))
140        dadd('\\subsection{Fortran 90/95 module \\texttt{%s}}\n' % (m['name']))
141        if hasnote(m):
142            note = m['note']
143            if isinstance(note, list):
144                note = '\n'.join(note)
145            dadd(note)
146        if onlyvars:
147            dadd('\\begin{description}')
148        for n in onlyvars:
149            var = m['vars'][n]
150            modobjs.append(n)
151            ct = capi_maps.getctype(var)
152            at = capi_maps.c2capi_map[ct]
153            dm = capi_maps.getarrdims(n, var)
154            dms = dm['dims'].replace('*', '-1').strip()
155            dms = dms.replace(':', '-1').strip()
156            if not dms:
157                dms = '-1'
158            use_fgetdims2 = fgetdims2
159            cadd('\t{"%s",%s,{{%s}},%s, %s},' %
160                 (undo_rmbadname1(n), dm['rank'], dms, at,
161                  capi_maps.get_elsize(var)))
162            dadd('\\item[]{{}\\verb@%s@{}}' %
163                 (capi_maps.getarrdocsign(n, var)))
164            if hasnote(var):
165                note = var['note']
166                if isinstance(note, list):
167                    note = '\n'.join(note)
168                dadd(f'--- {note}')
169            if isallocatable(var):
170                fargs.append(f"f2py_{m['name']}_getdims_{n}")
171                efargs.append(fargs[-1])
172                sargs.append(
173                    f'void (*{n})(int*,npy_intp*,void(*)(char*,npy_intp*),int*)')
174                sargsp.append('void (*)(int*,npy_intp*,void(*)(char*,npy_intp*),int*)')
175                iadd(f"\tf2py_{m['name']}_def[i_f2py++].func = {n};")
176                fadd(f'subroutine {fargs[-1]}(r,s,f2pysetdata,flag)')
177                fadd(f"use {m['name']}, only: d => {undo_rmbadname1(n)}\n")
178                fadd('integer flag\n')
179                fhooks[0] = fhooks[0] + fgetdims1
180                dms = range(1, int(dm['rank']) + 1)
181                fadd(' allocate(d(%s))\n' %
182                     (','.join(['s(%s)' % i for i in dms])))
183                fhooks[0] = fhooks[0] + use_fgetdims2
184                fadd(f'end subroutine {fargs[-1]}')
185            else:
186                fargs.append(n)
187                sargs.append(f'char *{n}')
188                sargsp.append('char*')
189                iadd(f"\tf2py_{m['name']}_def[i_f2py++].data = {n};")
190        if onlyvars:
191            dadd('\\end{description}')
192        if hasbody(m):
193            for b in m['body']:
194                if not isroutine(b):
195                    outmess("f90mod_rules.buildhooks:"
196                            f" skipping {b['block']} {b['name']}\n")
197                    continue
198                modobjs.append(f"{b['name']}()")
199                b['modulename'] = m['name']
200                api, wrap = rules.buildapi(b)
201                if isfunction(b):
202                    fhooks[0] = fhooks[0] + wrap
203                    fargs.append(f"f2pywrap_{m['name']}_{b['name']}")
204                    ifargs.append(func2subr.createfuncwrapper(b, signature=1))
205                elif wrap:
206                    fhooks[0] = fhooks[0] + wrap
207                    fargs.append(f"f2pywrap_{m['name']}_{b['name']}")
208                    ifargs.append(
209                        func2subr.createsubrwrapper(b, signature=1))
210                else:
211                    fargs.append(b['name'])
212                    mfargs.append(fargs[-1])
213                api['externroutines'] = []
214                ar = applyrules(api, vrd)
215                ar['docs'] = []
216                ar['docshort'] = []
217                ret = dictappend(ret, ar)
218                cadd(('\t{"%s",-1,{{-1}},0,0,NULL,(void *)'
219                      'f2py_rout_#modulename#_%s_%s,'
220                      'doc_f2py_rout_#modulename#_%s_%s},')
221                     % (b['name'], m['name'], b['name'], m['name'], b['name']))
222                sargs.append(f"char *{b['name']}")
223                sargsp.append('char *')
224                iadd(f"\tf2py_{m['name']}_def[i_f2py++].data = {b['name']};")
225        cadd('\t{NULL}\n};\n')
226        iadd('}')
227        ihooks[0] = 'static void f2py_setup_%s(%s) {\n\tint i_f2py=0;%s' % (
228            m['name'], ','.join(sargs), ihooks[0])
229        if '_' in m['name']:
230            F_FUNC = 'F_FUNC_US'
231        else:
232            F_FUNC = 'F_FUNC'
233        iadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void (*)(%s));'
234             % (F_FUNC, m['name'], m['name'].upper(), ','.join(sargsp)))
235        iadd('static void f2py_init_%s(void) {' % (m['name']))
236        iadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
237             % (F_FUNC, m['name'], m['name'].upper(), m['name']))
238        iadd('}\n')
239        ret['f90modhooks'] = ret['f90modhooks'] + chooks + ihooks
240        ret['initf90modhooks'] = ['\tPyDict_SetItemString(d, "%s", PyFortranObject_New(f2py_%s_def,f2py_init_%s));' % (
241            m['name'], m['name'], m['name'])] + ret['initf90modhooks']
242        fadd('')
243        fadd(f"subroutine f2pyinit{m['name']}(f2pysetupfunc)")
244        if mfargs:
245            for a in undo_rmbadname(mfargs):
246                fadd(f"use {m['name']}, only : {a}")
247        if ifargs:
248            fadd(' '.join(['interface'] + ifargs))
249            fadd('end interface')
250        fadd('external f2pysetupfunc')
251        if efargs:
252            for a in undo_rmbadname(efargs):
253                fadd(f'external {a}')
254        fadd(f"call f2pysetupfunc({','.join(undo_rmbadname(fargs))})")
255        fadd(f"end subroutine f2pyinit{m['name']}\n")
256
257        dadd('\n'.join(ret['latexdoc']).replace(
258            r'\subsection{', r'\subsubsection{'))
259
260        ret['latexdoc'] = []
261        ret['docs'].append(f"\"\t{m['name']} --- {','.join(undo_rmbadname(modobjs))}\"")
262
263    ret['routine_defs'] = ''
264    ret['doc'] = []
265    ret['docshort'] = []
266    ret['latexdoc'] = doc[0]
267    if len(ret['docs']) <= 1:
268        ret['docs'] = ''
269    return ret, fhooks[0]
270 
codekingpro/portable-devtools · Team Ai