Chris@87
|
1 #!/usr/bin/env python
|
Chris@87
|
2 """
|
Chris@87
|
3 crackfortran --- read fortran (77,90) code and extract declaration information.
|
Chris@87
|
4
|
Chris@87
|
5 Copyright 1999-2004 Pearu Peterson all rights reserved,
|
Chris@87
|
6 Pearu Peterson <pearu@ioc.ee>
|
Chris@87
|
7 Permission to use, modify, and distribute this software is given under the
|
Chris@87
|
8 terms of the NumPy License.
|
Chris@87
|
9
|
Chris@87
|
10 NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
Chris@87
|
11 $Date: 2005/09/27 07:13:49 $
|
Chris@87
|
12 Pearu Peterson
|
Chris@87
|
13
|
Chris@87
|
14
|
Chris@87
|
15 Usage of crackfortran:
|
Chris@87
|
16 ======================
|
Chris@87
|
17 Command line keys: -quiet,-verbose,-fix,-f77,-f90,-show,-h <pyffilename>
|
Chris@87
|
18 -m <module name for f77 routines>,--ignore-contains
|
Chris@87
|
19 Functions: crackfortran, crack2fortran
|
Chris@87
|
20 The following Fortran statements/constructions are supported
|
Chris@87
|
21 (or will be if needed):
|
Chris@87
|
22 block data,byte,call,character,common,complex,contains,data,
|
Chris@87
|
23 dimension,double complex,double precision,end,external,function,
|
Chris@87
|
24 implicit,integer,intent,interface,intrinsic,
|
Chris@87
|
25 logical,module,optional,parameter,private,public,
|
Chris@87
|
26 program,real,(sequence?),subroutine,type,use,virtual,
|
Chris@87
|
27 include,pythonmodule
|
Chris@87
|
28 Note: 'virtual' is mapped to 'dimension'.
|
Chris@87
|
29 Note: 'implicit integer (z) static (z)' is 'implicit static (z)' (this is minor bug).
|
Chris@87
|
30 Note: code after 'contains' will be ignored until its scope ends.
|
Chris@87
|
31 Note: 'common' statement is extended: dimensions are moved to variable definitions
|
Chris@87
|
32 Note: f2py directive: <commentchar>f2py<line> is read as <line>
|
Chris@87
|
33 Note: pythonmodule is introduced to represent Python module
|
Chris@87
|
34
|
Chris@87
|
35 Usage:
|
Chris@87
|
36 `postlist=crackfortran(files,funcs)`
|
Chris@87
|
37 `postlist` contains declaration information read from the list of files `files`.
|
Chris@87
|
38 `crack2fortran(postlist)` returns a fortran code to be saved to pyf-file
|
Chris@87
|
39
|
Chris@87
|
40 `postlist` has the following structure:
|
Chris@87
|
41 *** it is a list of dictionaries containing `blocks':
|
Chris@87
|
42 B = {'block','body','vars','parent_block'[,'name','prefix','args','result',
|
Chris@87
|
43 'implicit','externals','interfaced','common','sortvars',
|
Chris@87
|
44 'commonvars','note']}
|
Chris@87
|
45 B['block'] = 'interface' | 'function' | 'subroutine' | 'module' |
|
Chris@87
|
46 'program' | 'block data' | 'type' | 'pythonmodule'
|
Chris@87
|
47 B['body'] --- list containing `subblocks' with the same structure as `blocks'
|
Chris@87
|
48 B['parent_block'] --- dictionary of a parent block:
|
Chris@87
|
49 C['body'][<index>]['parent_block'] is C
|
Chris@87
|
50 B['vars'] --- dictionary of variable definitions
|
Chris@87
|
51 B['sortvars'] --- dictionary of variable definitions sorted by dependence (independent first)
|
Chris@87
|
52 B['name'] --- name of the block (not if B['block']=='interface')
|
Chris@87
|
53 B['prefix'] --- prefix string (only if B['block']=='function')
|
Chris@87
|
54 B['args'] --- list of argument names if B['block']== 'function' | 'subroutine'
|
Chris@87
|
55 B['result'] --- name of the return value (only if B['block']=='function')
|
Chris@87
|
56 B['implicit'] --- dictionary {'a':<variable definition>,'b':...} | None
|
Chris@87
|
57 B['externals'] --- list of variables being external
|
Chris@87
|
58 B['interfaced'] --- list of variables being external and defined
|
Chris@87
|
59 B['common'] --- dictionary of common blocks (list of objects)
|
Chris@87
|
60 B['commonvars'] --- list of variables used in common blocks (dimensions are moved to variable definitions)
|
Chris@87
|
61 B['from'] --- string showing the 'parents' of the current block
|
Chris@87
|
62 B['use'] --- dictionary of modules used in current block:
|
Chris@87
|
63 {<modulename>:{['only':<0|1>],['map':{<local_name1>:<use_name1>,...}]}}
|
Chris@87
|
64 B['note'] --- list of LaTeX comments on the block
|
Chris@87
|
65 B['f2pyenhancements'] --- optional dictionary
|
Chris@87
|
66 {'threadsafe':'','fortranname':<name>,
|
Chris@87
|
67 'callstatement':<C-expr>|<multi-line block>,
|
Chris@87
|
68 'callprotoargument':<C-expr-list>,
|
Chris@87
|
69 'usercode':<multi-line block>|<list of multi-line blocks>,
|
Chris@87
|
70 'pymethoddef:<multi-line block>'
|
Chris@87
|
71 }
|
Chris@87
|
72 B['entry'] --- dictionary {entryname:argslist,..}
|
Chris@87
|
73 B['varnames'] --- list of variable names given in the order of reading the
|
Chris@87
|
74 Fortran code, useful for derived types.
|
Chris@87
|
75 B['saved_interface'] --- a string of scanned routine signature, defines explicit interface
|
Chris@87
|
76 *** Variable definition is a dictionary
|
Chris@87
|
77 D = B['vars'][<variable name>] =
|
Chris@87
|
78 {'typespec'[,'attrspec','kindselector','charselector','=','typename']}
|
Chris@87
|
79 D['typespec'] = 'byte' | 'character' | 'complex' | 'double complex' |
|
Chris@87
|
80 'double precision' | 'integer' | 'logical' | 'real' | 'type'
|
Chris@87
|
81 D['attrspec'] --- list of attributes (e.g. 'dimension(<arrayspec>)',
|
Chris@87
|
82 'external','intent(in|out|inout|hide|c|callback|cache|aligned4|aligned8|aligned16)',
|
Chris@87
|
83 'optional','required', etc)
|
Chris@87
|
84 K = D['kindselector'] = {['*','kind']} (only if D['typespec'] =
|
Chris@87
|
85 'complex' | 'integer' | 'logical' | 'real' )
|
Chris@87
|
86 C = D['charselector'] = {['*','len','kind']}
|
Chris@87
|
87 (only if D['typespec']=='character')
|
Chris@87
|
88 D['='] --- initialization expression string
|
Chris@87
|
89 D['typename'] --- name of the type if D['typespec']=='type'
|
Chris@87
|
90 D['dimension'] --- list of dimension bounds
|
Chris@87
|
91 D['intent'] --- list of intent specifications
|
Chris@87
|
92 D['depend'] --- list of variable names on which current variable depends on
|
Chris@87
|
93 D['check'] --- list of C-expressions; if C-expr returns zero, exception is raised
|
Chris@87
|
94 D['note'] --- list of LaTeX comments on the variable
|
Chris@87
|
95 *** Meaning of kind/char selectors (few examples):
|
Chris@87
|
96 D['typespec>']*K['*']
|
Chris@87
|
97 D['typespec'](kind=K['kind'])
|
Chris@87
|
98 character*C['*']
|
Chris@87
|
99 character(len=C['len'],kind=C['kind'])
|
Chris@87
|
100 (see also fortran type declaration statement formats below)
|
Chris@87
|
101
|
Chris@87
|
102 Fortran 90 type declaration statement format (F77 is subset of F90)
|
Chris@87
|
103 ====================================================================
|
Chris@87
|
104 (Main source: IBM XL Fortran 5.1 Language Reference Manual)
|
Chris@87
|
105 type declaration = <typespec> [[<attrspec>]::] <entitydecl>
|
Chris@87
|
106 <typespec> = byte |
|
Chris@87
|
107 character[<charselector>] |
|
Chris@87
|
108 complex[<kindselector>] |
|
Chris@87
|
109 double complex |
|
Chris@87
|
110 double precision |
|
Chris@87
|
111 integer[<kindselector>] |
|
Chris@87
|
112 logical[<kindselector>] |
|
Chris@87
|
113 real[<kindselector>] |
|
Chris@87
|
114 type(<typename>)
|
Chris@87
|
115 <charselector> = * <charlen> |
|
Chris@87
|
116 ([len=]<len>[,[kind=]<kind>]) |
|
Chris@87
|
117 (kind=<kind>[,len=<len>])
|
Chris@87
|
118 <kindselector> = * <intlen> |
|
Chris@87
|
119 ([kind=]<kind>)
|
Chris@87
|
120 <attrspec> = comma separated list of attributes.
|
Chris@87
|
121 Only the following attributes are used in
|
Chris@87
|
122 building up the interface:
|
Chris@87
|
123 external
|
Chris@87
|
124 (parameter --- affects '=' key)
|
Chris@87
|
125 optional
|
Chris@87
|
126 intent
|
Chris@87
|
127 Other attributes are ignored.
|
Chris@87
|
128 <intentspec> = in | out | inout
|
Chris@87
|
129 <arrayspec> = comma separated list of dimension bounds.
|
Chris@87
|
130 <entitydecl> = <name> [[*<charlen>][(<arrayspec>)] | [(<arrayspec>)]*<charlen>]
|
Chris@87
|
131 [/<init_expr>/ | =<init_expr>] [,<entitydecl>]
|
Chris@87
|
132
|
Chris@87
|
133 In addition, the following attributes are used: check,depend,note
|
Chris@87
|
134
|
Chris@87
|
135 TODO:
|
Chris@87
|
136 * Apply 'parameter' attribute (e.g. 'integer parameter :: i=2' 'real x(i)'
|
Chris@87
|
137 -> 'real x(2)')
|
Chris@87
|
138 The above may be solved by creating appropriate preprocessor program, for example.
|
Chris@87
|
139
|
Chris@87
|
140 """
|
Chris@87
|
141 from __future__ import division, absolute_import, print_function
|
Chris@87
|
142
|
Chris@87
|
143 import sys
|
Chris@87
|
144 import string
|
Chris@87
|
145 import fileinput
|
Chris@87
|
146 import re
|
Chris@87
|
147 import pprint
|
Chris@87
|
148 import os
|
Chris@87
|
149 import copy
|
Chris@87
|
150 import platform
|
Chris@87
|
151
|
Chris@87
|
152 from . import __version__
|
Chris@87
|
153 from .auxfuncs import *
|
Chris@87
|
154
|
Chris@87
|
155 f2py_version = __version__.version
|
Chris@87
|
156
|
Chris@87
|
157 # Global flags:
|
Chris@87
|
158 strictf77=1 # Ignore `!' comments unless line[0]=='!'
|
Chris@87
|
159 sourcecodeform='fix' # 'fix','free'
|
Chris@87
|
160 quiet=0 # Be verbose if 0 (Obsolete: not used any more)
|
Chris@87
|
161 verbose=1 # Be quiet if 0, extra verbose if > 1.
|
Chris@87
|
162 tabchar=4*' '
|
Chris@87
|
163 pyffilename=''
|
Chris@87
|
164 f77modulename=''
|
Chris@87
|
165 skipemptyends=0 # for old F77 programs without 'program' statement
|
Chris@87
|
166 ignorecontains=1
|
Chris@87
|
167 dolowercase=1
|
Chris@87
|
168 debug=[]
|
Chris@87
|
169
|
Chris@87
|
170 # Global variables
|
Chris@87
|
171 groupcounter=0
|
Chris@87
|
172 grouplist={groupcounter:[]}
|
Chris@87
|
173 neededmodule=-1
|
Chris@87
|
174 expectbegin=1
|
Chris@87
|
175 skipblocksuntil=-1
|
Chris@87
|
176 usermodules=[]
|
Chris@87
|
177 f90modulevars={}
|
Chris@87
|
178 gotnextfile=1
|
Chris@87
|
179 filepositiontext=''
|
Chris@87
|
180 currentfilename=''
|
Chris@87
|
181 skipfunctions=[]
|
Chris@87
|
182 skipfuncs=[]
|
Chris@87
|
183 onlyfuncs=[]
|
Chris@87
|
184 include_paths=[]
|
Chris@87
|
185 previous_context = None
|
Chris@87
|
186
|
Chris@87
|
187
|
Chris@87
|
188 def reset_global_f2py_vars():
|
Chris@87
|
189 global groupcounter, grouplist, neededmodule, expectbegin, \
|
Chris@87
|
190 skipblocksuntil, usermodules, f90modulevars, gotnextfile, \
|
Chris@87
|
191 filepositiontext, currentfilename, skipfunctions, skipfuncs, \
|
Chris@87
|
192 onlyfuncs, include_paths, previous_context, \
|
Chris@87
|
193 strictf77, sourcecodeform, quiet, verbose, tabchar, pyffilename, \
|
Chris@87
|
194 f77modulename, skipemptyends, ignorecontains, dolowercase, debug
|
Chris@87
|
195
|
Chris@87
|
196 # flags
|
Chris@87
|
197 strictf77 = 1
|
Chris@87
|
198 sourcecodeform = 'fix'
|
Chris@87
|
199 quiet = 0
|
Chris@87
|
200 verbose = 1
|
Chris@87
|
201 tabchar = 4*' '
|
Chris@87
|
202 pyffilename = ''
|
Chris@87
|
203 f77modulename = ''
|
Chris@87
|
204 skipemptyends = 0
|
Chris@87
|
205 ignorecontains = 1
|
Chris@87
|
206 dolowercase = 1
|
Chris@87
|
207 debug = []
|
Chris@87
|
208 # variables
|
Chris@87
|
209 groupcounter = 0
|
Chris@87
|
210 grouplist = {groupcounter:[]}
|
Chris@87
|
211 neededmodule =-1
|
Chris@87
|
212 expectbegin = 1
|
Chris@87
|
213 skipblocksuntil = -1
|
Chris@87
|
214 usermodules = []
|
Chris@87
|
215 f90modulevars = {}
|
Chris@87
|
216 gotnextfile = 1
|
Chris@87
|
217 filepositiontext = ''
|
Chris@87
|
218 currentfilename = ''
|
Chris@87
|
219 skipfunctions = []
|
Chris@87
|
220 skipfuncs = []
|
Chris@87
|
221 onlyfuncs = []
|
Chris@87
|
222 include_paths = []
|
Chris@87
|
223 previous_context = None
|
Chris@87
|
224
|
Chris@87
|
225
|
Chris@87
|
226 ###### Some helper functions
|
Chris@87
|
227 def show(o,f=0):pprint.pprint(o)
|
Chris@87
|
228 errmess=sys.stderr.write
|
Chris@87
|
229 def outmess(line,flag=1):
|
Chris@87
|
230 global filepositiontext
|
Chris@87
|
231 if not verbose: return
|
Chris@87
|
232 if not quiet:
|
Chris@87
|
233 if flag:sys.stdout.write(filepositiontext)
|
Chris@87
|
234 sys.stdout.write(line)
|
Chris@87
|
235 re._MAXCACHE=50
|
Chris@87
|
236 defaultimplicitrules={}
|
Chris@87
|
237 for c in "abcdefghopqrstuvwxyz$_": defaultimplicitrules[c]={'typespec':'real'}
|
Chris@87
|
238 for c in "ijklmn": defaultimplicitrules[c]={'typespec':'integer'}
|
Chris@87
|
239 del c
|
Chris@87
|
240 badnames={}
|
Chris@87
|
241 invbadnames={}
|
Chris@87
|
242 for n in ['int', 'double', 'float', 'char', 'short', 'long', 'void', 'case', 'while',
|
Chris@87
|
243 'return', 'signed', 'unsigned', 'if', 'for', 'typedef', 'sizeof', 'union',
|
Chris@87
|
244 'struct', 'static', 'register', 'new', 'break', 'do', 'goto', 'switch',
|
Chris@87
|
245 'continue', 'else', 'inline', 'extern', 'delete', 'const', 'auto',
|
Chris@87
|
246 'len', 'rank', 'shape', 'index', 'slen', 'size', '_i',
|
Chris@87
|
247 'max', 'min',
|
Chris@87
|
248 'flen', 'fshape',
|
Chris@87
|
249 'string', 'complex_double', 'float_double', 'stdin', 'stderr', 'stdout',
|
Chris@87
|
250 'type', 'default']:
|
Chris@87
|
251 badnames[n]=n+'_bn'
|
Chris@87
|
252 invbadnames[n+'_bn']=n
|
Chris@87
|
253
|
Chris@87
|
254 def rmbadname1(name):
|
Chris@87
|
255 if name in badnames:
|
Chris@87
|
256 errmess('rmbadname1: Replacing "%s" with "%s".\n'%(name, badnames[name]))
|
Chris@87
|
257 return badnames[name]
|
Chris@87
|
258 return name
|
Chris@87
|
259
|
Chris@87
|
260 def rmbadname(names): return [rmbadname1(_m) for _m in names]
|
Chris@87
|
261
|
Chris@87
|
262 def undo_rmbadname1(name):
|
Chris@87
|
263 if name in invbadnames:
|
Chris@87
|
264 errmess('undo_rmbadname1: Replacing "%s" with "%s".\n'\
|
Chris@87
|
265 %(name, invbadnames[name]))
|
Chris@87
|
266 return invbadnames[name]
|
Chris@87
|
267 return name
|
Chris@87
|
268
|
Chris@87
|
269 def undo_rmbadname(names): return [undo_rmbadname1(_m) for _m in names]
|
Chris@87
|
270
|
Chris@87
|
271 def getextension(name):
|
Chris@87
|
272 i=name.rfind('.')
|
Chris@87
|
273 if i==-1: return ''
|
Chris@87
|
274 if '\\' in name[i:]: return ''
|
Chris@87
|
275 if '/' in name[i:]: return ''
|
Chris@87
|
276 return name[i+1:]
|
Chris@87
|
277
|
Chris@87
|
278 is_f_file = re.compile(r'.*[.](for|ftn|f77|f)\Z', re.I).match
|
Chris@87
|
279 _has_f_header = re.compile(r'-[*]-\s*fortran\s*-[*]-', re.I).search
|
Chris@87
|
280 _has_f90_header = re.compile(r'-[*]-\s*f90\s*-[*]-', re.I).search
|
Chris@87
|
281 _has_fix_header = re.compile(r'-[*]-\s*fix\s*-[*]-', re.I).search
|
Chris@87
|
282 _free_f90_start = re.compile(r'[^c*]\s*[^\s\d\t]', re.I).match
|
Chris@87
|
283 def is_free_format(file):
|
Chris@87
|
284 """Check if file is in free format Fortran."""
|
Chris@87
|
285 # f90 allows both fixed and free format, assuming fixed unless
|
Chris@87
|
286 # signs of free format are detected.
|
Chris@87
|
287 result = 0
|
Chris@87
|
288 f = open(file, 'r')
|
Chris@87
|
289 line = f.readline()
|
Chris@87
|
290 n = 15 # the number of non-comment lines to scan for hints
|
Chris@87
|
291 if _has_f_header(line):
|
Chris@87
|
292 n = 0
|
Chris@87
|
293 elif _has_f90_header(line):
|
Chris@87
|
294 n = 0
|
Chris@87
|
295 result = 1
|
Chris@87
|
296 while n>0 and line:
|
Chris@87
|
297 if line[0]!='!' and line.strip():
|
Chris@87
|
298 n -= 1
|
Chris@87
|
299 if (line[0]!='\t' and _free_f90_start(line[:5])) or line[-2:-1]=='&':
|
Chris@87
|
300 result = 1
|
Chris@87
|
301 break
|
Chris@87
|
302 line = f.readline()
|
Chris@87
|
303 f.close()
|
Chris@87
|
304 return result
|
Chris@87
|
305
|
Chris@87
|
306
|
Chris@87
|
307 ####### Read fortran (77,90) code
|
Chris@87
|
308 def readfortrancode(ffile,dowithline=show,istop=1):
|
Chris@87
|
309 """
|
Chris@87
|
310 Read fortran codes from files and
|
Chris@87
|
311 1) Get rid of comments, line continuations, and empty lines; lower cases.
|
Chris@87
|
312 2) Call dowithline(line) on every line.
|
Chris@87
|
313 3) Recursively call itself when statement \"include '<filename>'\" is met.
|
Chris@87
|
314 """
|
Chris@87
|
315 global gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
|
Chris@87
|
316 beginpattern, quiet, verbose, dolowercase, include_paths
|
Chris@87
|
317 if not istop:
|
Chris@87
|
318 saveglobals=gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
|
Chris@87
|
319 beginpattern, quiet, verbose, dolowercase
|
Chris@87
|
320 if ffile==[]: return
|
Chris@87
|
321 localdolowercase = dolowercase
|
Chris@87
|
322 cont=0
|
Chris@87
|
323 finalline=''
|
Chris@87
|
324 ll=''
|
Chris@87
|
325 commentline=re.compile(r'(?P<line>([^"]*["][^"]*["][^"!]*|[^\']*\'[^\']*\'[^\'!]*|[^!\'"]*))!{1}(?P<rest>.*)')
|
Chris@87
|
326 includeline=re.compile(r'\s*include\s*(\'|")(?P<name>[^\'"]*)(\'|")', re.I)
|
Chris@87
|
327 cont1=re.compile(r'(?P<line>.*)&\s*\Z')
|
Chris@87
|
328 cont2=re.compile(r'(\s*&|)(?P<line>.*)')
|
Chris@87
|
329 mline_mark = re.compile(r".*?'''")
|
Chris@87
|
330 if istop: dowithline('', -1)
|
Chris@87
|
331 ll, l1='', ''
|
Chris@87
|
332 spacedigits=[' '] + [str(_m) for _m in range(10)]
|
Chris@87
|
333 filepositiontext=''
|
Chris@87
|
334 fin=fileinput.FileInput(ffile)
|
Chris@87
|
335 while True:
|
Chris@87
|
336 l=fin.readline()
|
Chris@87
|
337 if not l: break
|
Chris@87
|
338 if fin.isfirstline():
|
Chris@87
|
339 filepositiontext=''
|
Chris@87
|
340 currentfilename=fin.filename()
|
Chris@87
|
341 gotnextfile=1
|
Chris@87
|
342 l1=l
|
Chris@87
|
343 strictf77=0
|
Chris@87
|
344 sourcecodeform='fix'
|
Chris@87
|
345 ext = os.path.splitext(currentfilename)[1]
|
Chris@87
|
346 if is_f_file(currentfilename) and \
|
Chris@87
|
347 not (_has_f90_header(l) or _has_fix_header(l)):
|
Chris@87
|
348 strictf77=1
|
Chris@87
|
349 elif is_free_format(currentfilename) and not _has_fix_header(l):
|
Chris@87
|
350 sourcecodeform='free'
|
Chris@87
|
351 if strictf77: beginpattern=beginpattern77
|
Chris@87
|
352 else: beginpattern=beginpattern90
|
Chris@87
|
353 outmess('\tReading file %s (format:%s%s)\n'\
|
Chris@87
|
354 %(repr(currentfilename), sourcecodeform,
|
Chris@87
|
355 strictf77 and ',strict' or ''))
|
Chris@87
|
356
|
Chris@87
|
357 l=l.expandtabs().replace('\xa0', ' ')
|
Chris@87
|
358 while not l=='': # Get rid of newline characters
|
Chris@87
|
359 if l[-1] not in "\n\r\f": break
|
Chris@87
|
360 l=l[:-1]
|
Chris@87
|
361 if not strictf77:
|
Chris@87
|
362 r=commentline.match(l)
|
Chris@87
|
363 if r:
|
Chris@87
|
364 l=r.group('line')+' ' # Strip comments starting with `!'
|
Chris@87
|
365 rl=r.group('rest')
|
Chris@87
|
366 if rl[:4].lower()=='f2py': # f2py directive
|
Chris@87
|
367 l = l + 4*' '
|
Chris@87
|
368 r=commentline.match(rl[4:])
|
Chris@87
|
369 if r: l=l+r.group('line')
|
Chris@87
|
370 else: l = l + rl[4:]
|
Chris@87
|
371 if l.strip()=='': # Skip empty line
|
Chris@87
|
372 cont=0
|
Chris@87
|
373 continue
|
Chris@87
|
374 if sourcecodeform=='fix':
|
Chris@87
|
375 if l[0] in ['*', 'c', '!', 'C', '#']:
|
Chris@87
|
376 if l[1:5].lower()=='f2py': # f2py directive
|
Chris@87
|
377 l=' '+l[5:]
|
Chris@87
|
378 else: # Skip comment line
|
Chris@87
|
379 cont=0
|
Chris@87
|
380 continue
|
Chris@87
|
381 elif strictf77:
|
Chris@87
|
382 if len(l)>72: l=l[:72]
|
Chris@87
|
383 if not (l[0] in spacedigits):
|
Chris@87
|
384 raise Exception('readfortrancode: Found non-(space,digit) char '
|
Chris@87
|
385 'in the first column.\n\tAre you sure that '
|
Chris@87
|
386 'this code is in fix form?\n\tline=%s' % repr(l))
|
Chris@87
|
387
|
Chris@87
|
388 if (not cont or strictf77) and (len(l)>5 and not l[5]==' '):
|
Chris@87
|
389 # Continuation of a previous line
|
Chris@87
|
390 ll=ll+l[6:]
|
Chris@87
|
391 finalline=''
|
Chris@87
|
392 origfinalline=''
|
Chris@87
|
393 else:
|
Chris@87
|
394 if not strictf77:
|
Chris@87
|
395 # F90 continuation
|
Chris@87
|
396 r=cont1.match(l)
|
Chris@87
|
397 if r: l=r.group('line') # Continuation follows ..
|
Chris@87
|
398 if cont:
|
Chris@87
|
399 ll=ll+cont2.match(l).group('line')
|
Chris@87
|
400 finalline=''
|
Chris@87
|
401 origfinalline=''
|
Chris@87
|
402 else:
|
Chris@87
|
403 l=' '+l[5:] # clean up line beginning from possible digits.
|
Chris@87
|
404 if localdolowercase: finalline=ll.lower()
|
Chris@87
|
405 else: finalline=ll
|
Chris@87
|
406 origfinalline=ll
|
Chris@87
|
407 ll=l
|
Chris@87
|
408 cont=(r is not None)
|
Chris@87
|
409 else:
|
Chris@87
|
410 l=' '+l[5:] # clean up line beginning from possible digits.
|
Chris@87
|
411 if localdolowercase: finalline=ll.lower()
|
Chris@87
|
412 else: finalline=ll
|
Chris@87
|
413 origfinalline =ll
|
Chris@87
|
414 ll=l
|
Chris@87
|
415
|
Chris@87
|
416 elif sourcecodeform=='free':
|
Chris@87
|
417 if not cont and ext=='.pyf' and mline_mark.match(l):
|
Chris@87
|
418 l = l + '\n'
|
Chris@87
|
419 while True:
|
Chris@87
|
420 lc = fin.readline()
|
Chris@87
|
421 if not lc:
|
Chris@87
|
422 errmess('Unexpected end of file when reading multiline\n')
|
Chris@87
|
423 break
|
Chris@87
|
424 l = l + lc
|
Chris@87
|
425 if mline_mark.match(lc):
|
Chris@87
|
426 break
|
Chris@87
|
427 l = l.rstrip()
|
Chris@87
|
428 r=cont1.match(l)
|
Chris@87
|
429 if r: l=r.group('line') # Continuation follows ..
|
Chris@87
|
430 if cont:
|
Chris@87
|
431 ll=ll+cont2.match(l).group('line')
|
Chris@87
|
432 finalline=''
|
Chris@87
|
433 origfinalline=''
|
Chris@87
|
434 else:
|
Chris@87
|
435 if localdolowercase: finalline=ll.lower()
|
Chris@87
|
436 else: finalline=ll
|
Chris@87
|
437 origfinalline =ll
|
Chris@87
|
438 ll=l
|
Chris@87
|
439 cont=(r is not None)
|
Chris@87
|
440 else:
|
Chris@87
|
441 raise ValueError("Flag sourcecodeform must be either 'fix' or 'free': %s"%repr(sourcecodeform))
|
Chris@87
|
442 filepositiontext='Line #%d in %s:"%s"\n\t' % (fin.filelineno()-1, currentfilename, l1)
|
Chris@87
|
443 m=includeline.match(origfinalline)
|
Chris@87
|
444 if m:
|
Chris@87
|
445 fn=m.group('name')
|
Chris@87
|
446 if os.path.isfile(fn):
|
Chris@87
|
447 readfortrancode(fn, dowithline=dowithline, istop=0)
|
Chris@87
|
448 else:
|
Chris@87
|
449 include_dirs = [os.path.dirname(currentfilename)] + include_paths
|
Chris@87
|
450 foundfile = 0
|
Chris@87
|
451 for inc_dir in include_dirs:
|
Chris@87
|
452 fn1 = os.path.join(inc_dir, fn)
|
Chris@87
|
453 if os.path.isfile(fn1):
|
Chris@87
|
454 foundfile = 1
|
Chris@87
|
455 readfortrancode(fn1, dowithline=dowithline, istop=0)
|
Chris@87
|
456 break
|
Chris@87
|
457 if not foundfile:
|
Chris@87
|
458 outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n'%(repr(fn), os.pathsep.join(include_dirs)))
|
Chris@87
|
459 else:
|
Chris@87
|
460 dowithline(finalline)
|
Chris@87
|
461 l1=ll
|
Chris@87
|
462 if localdolowercase:
|
Chris@87
|
463 finalline=ll.lower()
|
Chris@87
|
464 else: finalline=ll
|
Chris@87
|
465 origfinalline = ll
|
Chris@87
|
466 filepositiontext='Line #%d in %s:"%s"\n\t' % (fin.filelineno()-1, currentfilename, l1)
|
Chris@87
|
467 m=includeline.match(origfinalline)
|
Chris@87
|
468 if m:
|
Chris@87
|
469 fn=m.group('name')
|
Chris@87
|
470 if os.path.isfile(fn):
|
Chris@87
|
471 readfortrancode(fn, dowithline=dowithline, istop=0)
|
Chris@87
|
472 else:
|
Chris@87
|
473 include_dirs = [os.path.dirname(currentfilename)] + include_paths
|
Chris@87
|
474 foundfile = 0
|
Chris@87
|
475 for inc_dir in include_dirs:
|
Chris@87
|
476 fn1 = os.path.join(inc_dir, fn)
|
Chris@87
|
477 if os.path.isfile(fn1):
|
Chris@87
|
478 foundfile = 1
|
Chris@87
|
479 readfortrancode(fn1, dowithline=dowithline, istop=0)
|
Chris@87
|
480 break
|
Chris@87
|
481 if not foundfile:
|
Chris@87
|
482 outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n'%(repr(fn), os.pathsep.join(include_dirs)))
|
Chris@87
|
483 else:
|
Chris@87
|
484 dowithline(finalline)
|
Chris@87
|
485 filepositiontext=''
|
Chris@87
|
486 fin.close()
|
Chris@87
|
487 if istop: dowithline('', 1)
|
Chris@87
|
488 else:
|
Chris@87
|
489 gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
|
Chris@87
|
490 beginpattern, quiet, verbose, dolowercase=saveglobals
|
Chris@87
|
491
|
Chris@87
|
492 ########### Crack line
|
Chris@87
|
493 beforethisafter=r'\s*(?P<before>%s(?=\s*(\b(%s)\b)))'+ \
|
Chris@87
|
494 r'\s*(?P<this>(\b(%s)\b))'+ \
|
Chris@87
|
495 r'\s*(?P<after>%s)\s*\Z'
|
Chris@87
|
496 ##
|
Chris@87
|
497 fortrantypes='character|logical|integer|real|complex|double\s*(precision\s*(complex|)|complex)|type(?=\s*\([\w\s,=(*)]*\))|byte'
|
Chris@87
|
498 typespattern=re.compile(beforethisafter%('', fortrantypes, fortrantypes, '.*'), re.I), 'type'
|
Chris@87
|
499 typespattern4implicit=re.compile(beforethisafter%('', fortrantypes+'|static|automatic|undefined', fortrantypes+'|static|automatic|undefined', '.*'), re.I)
|
Chris@87
|
500 #
|
Chris@87
|
501 functionpattern=re.compile(beforethisafter%('([a-z]+[\w\s(=*+-/)]*?|)', 'function', 'function', '.*'), re.I), 'begin'
|
Chris@87
|
502 subroutinepattern=re.compile(beforethisafter%('[a-z\s]*?', 'subroutine', 'subroutine', '.*'), re.I), 'begin'
|
Chris@87
|
503 #modulepattern=re.compile(beforethisafter%('[a-z\s]*?','module','module','.*'),re.I),'begin'
|
Chris@87
|
504 #
|
Chris@87
|
505 groupbegins77=r'program|block\s*data'
|
Chris@87
|
506 beginpattern77=re.compile(beforethisafter%('', groupbegins77, groupbegins77, '.*'), re.I), 'begin'
|
Chris@87
|
507 groupbegins90=groupbegins77+r'|module(?!\s*procedure)|python\s*module|interface|type(?!\s*\()'
|
Chris@87
|
508 beginpattern90=re.compile(beforethisafter%('', groupbegins90, groupbegins90, '.*'), re.I), 'begin'
|
Chris@87
|
509 groupends=r'end|endprogram|endblockdata|endmodule|endpythonmodule|endinterface'
|
Chris@87
|
510 endpattern=re.compile(beforethisafter%('', groupends, groupends, '[\w\s]*'), re.I), 'end'
|
Chris@87
|
511 #endifs='end\s*(if|do|where|select|while|forall)'
|
Chris@87
|
512 endifs='(end\s*(if|do|where|select|while|forall))|(module\s*procedure)'
|
Chris@87
|
513 endifpattern=re.compile(beforethisafter%('[\w]*?', endifs, endifs, '[\w\s]*'), re.I), 'endif'
|
Chris@87
|
514 #
|
Chris@87
|
515 implicitpattern=re.compile(beforethisafter%('', 'implicit', 'implicit', '.*'), re.I), 'implicit'
|
Chris@87
|
516 dimensionpattern=re.compile(beforethisafter%('', 'dimension|virtual', 'dimension|virtual', '.*'), re.I), 'dimension'
|
Chris@87
|
517 externalpattern=re.compile(beforethisafter%('', 'external', 'external', '.*'), re.I), 'external'
|
Chris@87
|
518 optionalpattern=re.compile(beforethisafter%('', 'optional', 'optional', '.*'), re.I), 'optional'
|
Chris@87
|
519 requiredpattern=re.compile(beforethisafter%('', 'required', 'required', '.*'), re.I), 'required'
|
Chris@87
|
520 publicpattern=re.compile(beforethisafter%('', 'public', 'public', '.*'), re.I), 'public'
|
Chris@87
|
521 privatepattern=re.compile(beforethisafter%('', 'private', 'private', '.*'), re.I), 'private'
|
Chris@87
|
522 intrisicpattern=re.compile(beforethisafter%('', 'intrisic', 'intrisic', '.*'), re.I), 'intrisic'
|
Chris@87
|
523 intentpattern=re.compile(beforethisafter%('', 'intent|depend|note|check', 'intent|depend|note|check', '\s*\(.*?\).*'), re.I), 'intent'
|
Chris@87
|
524 parameterpattern=re.compile(beforethisafter%('', 'parameter', 'parameter', '\s*\(.*'), re.I), 'parameter'
|
Chris@87
|
525 datapattern=re.compile(beforethisafter%('', 'data', 'data', '.*'), re.I), 'data'
|
Chris@87
|
526 callpattern=re.compile(beforethisafter%('', 'call', 'call', '.*'), re.I), 'call'
|
Chris@87
|
527 entrypattern=re.compile(beforethisafter%('', 'entry', 'entry', '.*'), re.I), 'entry'
|
Chris@87
|
528 callfunpattern=re.compile(beforethisafter%('', 'callfun', 'callfun', '.*'), re.I), 'callfun'
|
Chris@87
|
529 commonpattern=re.compile(beforethisafter%('', 'common', 'common', '.*'), re.I), 'common'
|
Chris@87
|
530 usepattern=re.compile(beforethisafter%('', 'use', 'use', '.*'), re.I), 'use'
|
Chris@87
|
531 containspattern=re.compile(beforethisafter%('', 'contains', 'contains', ''), re.I), 'contains'
|
Chris@87
|
532 formatpattern=re.compile(beforethisafter%('', 'format', 'format', '.*'), re.I), 'format'
|
Chris@87
|
533 ## Non-fortran and f2py-specific statements
|
Chris@87
|
534 f2pyenhancementspattern=re.compile(beforethisafter%('', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', '.*'), re.I|re.S), 'f2pyenhancements'
|
Chris@87
|
535 multilinepattern = re.compile(r"\s*(?P<before>''')(?P<this>.*?)(?P<after>''')\s*\Z", re.S), 'multiline'
|
Chris@87
|
536 ##
|
Chris@87
|
537
|
Chris@87
|
538 def _simplifyargs(argsline):
|
Chris@87
|
539 a = []
|
Chris@87
|
540 for n in markoutercomma(argsline).split('@,@'):
|
Chris@87
|
541 for r in '(),':
|
Chris@87
|
542 n = n.replace(r, '_')
|
Chris@87
|
543 a.append(n)
|
Chris@87
|
544 return ','.join(a)
|
Chris@87
|
545
|
Chris@87
|
546 crackline_re_1 = re.compile(r'\s*(?P<result>\b[a-z]+[\w]*\b)\s*[=].*', re.I)
|
Chris@87
|
547 def crackline(line,reset=0):
|
Chris@87
|
548 """
|
Chris@87
|
549 reset=-1 --- initialize
|
Chris@87
|
550 reset=0 --- crack the line
|
Chris@87
|
551 reset=1 --- final check if mismatch of blocks occured
|
Chris@87
|
552
|
Chris@87
|
553 Cracked data is saved in grouplist[0].
|
Chris@87
|
554 """
|
Chris@87
|
555 global beginpattern, groupcounter, groupname, groupcache, grouplist, gotnextfile,\
|
Chris@87
|
556 filepositiontext, currentfilename, neededmodule, expectbegin, skipblocksuntil,\
|
Chris@87
|
557 skipemptyends, previous_context
|
Chris@87
|
558 if ';' in line and not (f2pyenhancementspattern[0].match(line) or
|
Chris@87
|
559 multilinepattern[0].match(line)):
|
Chris@87
|
560 for l in line.split(';'):
|
Chris@87
|
561 assert reset==0, repr(reset) # XXX: non-zero reset values need testing
|
Chris@87
|
562 crackline(l, reset)
|
Chris@87
|
563 return
|
Chris@87
|
564 if reset<0:
|
Chris@87
|
565 groupcounter=0
|
Chris@87
|
566 groupname={groupcounter:''}
|
Chris@87
|
567 groupcache={groupcounter:{}}
|
Chris@87
|
568 grouplist={groupcounter:[]}
|
Chris@87
|
569 groupcache[groupcounter]['body']=[]
|
Chris@87
|
570 groupcache[groupcounter]['vars']={}
|
Chris@87
|
571 groupcache[groupcounter]['block']=''
|
Chris@87
|
572 groupcache[groupcounter]['name']=''
|
Chris@87
|
573 neededmodule=-1
|
Chris@87
|
574 skipblocksuntil=-1
|
Chris@87
|
575 return
|
Chris@87
|
576 if reset>0:
|
Chris@87
|
577 fl=0
|
Chris@87
|
578 if f77modulename and neededmodule==groupcounter: fl=2
|
Chris@87
|
579 while groupcounter>fl:
|
Chris@87
|
580 outmess('crackline: groupcounter=%s groupname=%s\n'%(repr(groupcounter), repr(groupname)))
|
Chris@87
|
581 outmess('crackline: Mismatch of blocks encountered. Trying to fix it by assuming "end" statement.\n')
|
Chris@87
|
582 grouplist[groupcounter-1].append(groupcache[groupcounter])
|
Chris@87
|
583 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
|
Chris@87
|
584 del grouplist[groupcounter]
|
Chris@87
|
585 groupcounter=groupcounter-1
|
Chris@87
|
586 if f77modulename and neededmodule==groupcounter:
|
Chris@87
|
587 grouplist[groupcounter-1].append(groupcache[groupcounter])
|
Chris@87
|
588 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
|
Chris@87
|
589 del grouplist[groupcounter]
|
Chris@87
|
590 groupcounter=groupcounter-1 # end interface
|
Chris@87
|
591 grouplist[groupcounter-1].append(groupcache[groupcounter])
|
Chris@87
|
592 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
|
Chris@87
|
593 del grouplist[groupcounter]
|
Chris@87
|
594 groupcounter=groupcounter-1 # end module
|
Chris@87
|
595 neededmodule=-1
|
Chris@87
|
596 return
|
Chris@87
|
597 if line=='': return
|
Chris@87
|
598 flag=0
|
Chris@87
|
599 for pat in [dimensionpattern, externalpattern, intentpattern, optionalpattern,
|
Chris@87
|
600 requiredpattern,
|
Chris@87
|
601 parameterpattern, datapattern, publicpattern, privatepattern,
|
Chris@87
|
602 intrisicpattern,
|
Chris@87
|
603 endifpattern, endpattern,
|
Chris@87
|
604 formatpattern,
|
Chris@87
|
605 beginpattern, functionpattern, subroutinepattern,
|
Chris@87
|
606 implicitpattern, typespattern, commonpattern,
|
Chris@87
|
607 callpattern, usepattern, containspattern,
|
Chris@87
|
608 entrypattern,
|
Chris@87
|
609 f2pyenhancementspattern,
|
Chris@87
|
610 multilinepattern
|
Chris@87
|
611 ]:
|
Chris@87
|
612 m = pat[0].match(line)
|
Chris@87
|
613 if m:
|
Chris@87
|
614 break
|
Chris@87
|
615 flag=flag+1
|
Chris@87
|
616 if not m:
|
Chris@87
|
617 re_1 = crackline_re_1
|
Chris@87
|
618 if 0<=skipblocksuntil<=groupcounter:return
|
Chris@87
|
619 if 'externals' in groupcache[groupcounter]:
|
Chris@87
|
620 for name in groupcache[groupcounter]['externals']:
|
Chris@87
|
621 if name in invbadnames:
|
Chris@87
|
622 name=invbadnames[name]
|
Chris@87
|
623 if 'interfaced' in groupcache[groupcounter] and name in groupcache[groupcounter]['interfaced']:
|
Chris@87
|
624 continue
|
Chris@87
|
625 m1=re.match(r'(?P<before>[^"]*)\b%s\b\s*@\(@(?P<args>[^@]*)@\)@.*\Z'%name, markouterparen(line), re.I)
|
Chris@87
|
626 if m1:
|
Chris@87
|
627 m2 = re_1.match(m1.group('before'))
|
Chris@87
|
628 a = _simplifyargs(m1.group('args'))
|
Chris@87
|
629 if m2:
|
Chris@87
|
630 line='callfun %s(%s) result (%s)'%(name, a, m2.group('result'))
|
Chris@87
|
631 else: line='callfun %s(%s)'%(name, a)
|
Chris@87
|
632 m = callfunpattern[0].match(line)
|
Chris@87
|
633 if not m:
|
Chris@87
|
634 outmess('crackline: could not resolve function call for line=%s.\n'%repr(line))
|
Chris@87
|
635 return
|
Chris@87
|
636 analyzeline(m, 'callfun', line)
|
Chris@87
|
637 return
|
Chris@87
|
638 if verbose>1 or (verbose==1 and currentfilename.lower().endswith('.pyf')):
|
Chris@87
|
639 previous_context = None
|
Chris@87
|
640 outmess('crackline:%d: No pattern for line\n'%(groupcounter))
|
Chris@87
|
641 return
|
Chris@87
|
642 elif pat[1]=='end':
|
Chris@87
|
643 if 0<=skipblocksuntil<groupcounter:
|
Chris@87
|
644 groupcounter=groupcounter-1
|
Chris@87
|
645 if skipblocksuntil<=groupcounter: return
|
Chris@87
|
646 if groupcounter<=0:
|
Chris@87
|
647 raise Exception('crackline: groupcounter(=%s) is nonpositive. '
|
Chris@87
|
648 'Check the blocks.' \
|
Chris@87
|
649 % (groupcounter))
|
Chris@87
|
650 m1 = beginpattern[0].match((line))
|
Chris@87
|
651 if (m1) and (not m1.group('this')==groupname[groupcounter]):
|
Chris@87
|
652 raise Exception('crackline: End group %s does not match with '
|
Chris@87
|
653 'previous Begin group %s\n\t%s' % \
|
Chris@87
|
654 (repr(m1.group('this')), repr(groupname[groupcounter]),
|
Chris@87
|
655 filepositiontext)
|
Chris@87
|
656 )
|
Chris@87
|
657 if skipblocksuntil==groupcounter:
|
Chris@87
|
658 skipblocksuntil=-1
|
Chris@87
|
659 grouplist[groupcounter-1].append(groupcache[groupcounter])
|
Chris@87
|
660 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
|
Chris@87
|
661 del grouplist[groupcounter]
|
Chris@87
|
662 groupcounter=groupcounter-1
|
Chris@87
|
663 if not skipemptyends:
|
Chris@87
|
664 expectbegin=1
|
Chris@87
|
665 elif pat[1] == 'begin':
|
Chris@87
|
666 if 0<=skipblocksuntil<=groupcounter:
|
Chris@87
|
667 groupcounter=groupcounter+1
|
Chris@87
|
668 return
|
Chris@87
|
669 gotnextfile=0
|
Chris@87
|
670 analyzeline(m, pat[1], line)
|
Chris@87
|
671 expectbegin=0
|
Chris@87
|
672 elif pat[1]=='endif':
|
Chris@87
|
673 pass
|
Chris@87
|
674 elif pat[1]=='contains':
|
Chris@87
|
675 if ignorecontains: return
|
Chris@87
|
676 if 0<=skipblocksuntil<=groupcounter: return
|
Chris@87
|
677 skipblocksuntil=groupcounter
|
Chris@87
|
678 else:
|
Chris@87
|
679 if 0<=skipblocksuntil<=groupcounter:return
|
Chris@87
|
680 analyzeline(m, pat[1], line)
|
Chris@87
|
681
|
Chris@87
|
682 def markouterparen(line):
|
Chris@87
|
683 l='';f=0
|
Chris@87
|
684 for c in line:
|
Chris@87
|
685 if c=='(':
|
Chris@87
|
686 f=f+1
|
Chris@87
|
687 if f==1: l=l+'@(@'; continue
|
Chris@87
|
688 elif c==')':
|
Chris@87
|
689 f=f-1
|
Chris@87
|
690 if f==0: l=l+'@)@'; continue
|
Chris@87
|
691 l=l+c
|
Chris@87
|
692 return l
|
Chris@87
|
693 def markoutercomma(line,comma=','):
|
Chris@87
|
694 l='';f=0
|
Chris@87
|
695 cc=''
|
Chris@87
|
696 for c in line:
|
Chris@87
|
697 if (not cc or cc==')') and c=='(':
|
Chris@87
|
698 f=f+1
|
Chris@87
|
699 cc = ')'
|
Chris@87
|
700 elif not cc and c=='\'' and (not l or l[-1]!='\\'):
|
Chris@87
|
701 f=f+1
|
Chris@87
|
702 cc = '\''
|
Chris@87
|
703 elif c==cc:
|
Chris@87
|
704 f=f-1
|
Chris@87
|
705 if f==0:
|
Chris@87
|
706 cc=''
|
Chris@87
|
707 elif c==comma and f==0:
|
Chris@87
|
708 l=l+'@'+comma+'@'
|
Chris@87
|
709 continue
|
Chris@87
|
710 l=l+c
|
Chris@87
|
711 assert not f, repr((f, line, l, cc))
|
Chris@87
|
712 return l
|
Chris@87
|
713 def unmarkouterparen(line):
|
Chris@87
|
714 r = line.replace('@(@', '(').replace('@)@', ')')
|
Chris@87
|
715 return r
|
Chris@87
|
716 def appenddecl(decl,decl2,force=1):
|
Chris@87
|
717 if not decl: decl={}
|
Chris@87
|
718 if not decl2: return decl
|
Chris@87
|
719 if decl is decl2: return decl
|
Chris@87
|
720 for k in list(decl2.keys()):
|
Chris@87
|
721 if k=='typespec':
|
Chris@87
|
722 if force or k not in decl:
|
Chris@87
|
723 decl[k]=decl2[k]
|
Chris@87
|
724 elif k=='attrspec':
|
Chris@87
|
725 for l in decl2[k]:
|
Chris@87
|
726 decl=setattrspec(decl, l, force)
|
Chris@87
|
727 elif k=='kindselector':
|
Chris@87
|
728 decl=setkindselector(decl, decl2[k], force)
|
Chris@87
|
729 elif k=='charselector':
|
Chris@87
|
730 decl=setcharselector(decl, decl2[k], force)
|
Chris@87
|
731 elif k in ['=', 'typename']:
|
Chris@87
|
732 if force or k not in decl:
|
Chris@87
|
733 decl[k]=decl2[k]
|
Chris@87
|
734 elif k=='note':
|
Chris@87
|
735 pass
|
Chris@87
|
736 elif k in ['intent', 'check', 'dimension', 'optional', 'required']:
|
Chris@87
|
737 errmess('appenddecl: "%s" not implemented.\n'%k)
|
Chris@87
|
738 else:
|
Chris@87
|
739 raise Exception('appenddecl: Unknown variable definition key:' + \
|
Chris@87
|
740 str(k))
|
Chris@87
|
741 return decl
|
Chris@87
|
742
|
Chris@87
|
743 selectpattern=re.compile(r'\s*(?P<this>(@\(@.*?@\)@|[*][\d*]+|[*]\s*@\(@.*?@\)@|))(?P<after>.*)\Z', re.I)
|
Chris@87
|
744 nameargspattern=re.compile(r'\s*(?P<name>\b[\w$]+\b)\s*(@\(@\s*(?P<args>[\w\s,]*)\s*@\)@|)\s*((result(\s*@\(@\s*(?P<result>\b[\w$]+\b)\s*@\)@|))|(bind\s*@\(@\s*(?P<bind>.*)\s*@\)@))*\s*\Z', re.I)
|
Chris@87
|
745 callnameargspattern=re.compile(r'\s*(?P<name>\b[\w$]+\b)\s*@\(@\s*(?P<args>.*)\s*@\)@\s*\Z', re.I)
|
Chris@87
|
746 real16pattern = re.compile(r'([-+]?(?:\d+(?:\.\d*)?|\d*\.\d+))[dD]((?:[-+]?\d+)?)')
|
Chris@87
|
747 real8pattern = re.compile(r'([-+]?((?:\d+(?:\.\d*)?|\d*\.\d+))[eE]((?:[-+]?\d+)?)|(\d+\.\d*))')
|
Chris@87
|
748
|
Chris@87
|
749 _intentcallbackpattern = re.compile(r'intent\s*\(.*?\bcallback\b', re.I)
|
Chris@87
|
750 def _is_intent_callback(vdecl):
|
Chris@87
|
751 for a in vdecl.get('attrspec', []):
|
Chris@87
|
752 if _intentcallbackpattern.match(a):
|
Chris@87
|
753 return 1
|
Chris@87
|
754 return 0
|
Chris@87
|
755
|
Chris@87
|
756 def _resolvenameargspattern(line):
|
Chris@87
|
757 line = markouterparen(line)
|
Chris@87
|
758 m1=nameargspattern.match(line)
|
Chris@87
|
759 if m1:
|
Chris@87
|
760 return m1.group('name'), m1.group('args'), m1.group('result'), m1.group('bind')
|
Chris@87
|
761 m1=callnameargspattern.match(line)
|
Chris@87
|
762 if m1:
|
Chris@87
|
763 return m1.group('name'), m1.group('args'), None, None
|
Chris@87
|
764 return None, [], None, None
|
Chris@87
|
765
|
Chris@87
|
766 def analyzeline(m, case, line):
|
Chris@87
|
767 global groupcounter, groupname, groupcache, grouplist, filepositiontext,\
|
Chris@87
|
768 currentfilename, f77modulename, neededinterface, neededmodule, expectbegin,\
|
Chris@87
|
769 gotnextfile, previous_context
|
Chris@87
|
770 block=m.group('this')
|
Chris@87
|
771 if case != 'multiline':
|
Chris@87
|
772 previous_context = None
|
Chris@87
|
773 if expectbegin and case not in ['begin', 'call', 'callfun', 'type'] \
|
Chris@87
|
774 and not skipemptyends and groupcounter<1:
|
Chris@87
|
775 newname=os.path.basename(currentfilename).split('.')[0]
|
Chris@87
|
776 outmess('analyzeline: no group yet. Creating program group with name "%s".\n'%newname)
|
Chris@87
|
777 gotnextfile=0
|
Chris@87
|
778 groupcounter=groupcounter+1
|
Chris@87
|
779 groupname[groupcounter]='program'
|
Chris@87
|
780 groupcache[groupcounter]={}
|
Chris@87
|
781 grouplist[groupcounter]=[]
|
Chris@87
|
782 groupcache[groupcounter]['body']=[]
|
Chris@87
|
783 groupcache[groupcounter]['vars']={}
|
Chris@87
|
784 groupcache[groupcounter]['block']='program'
|
Chris@87
|
785 groupcache[groupcounter]['name']=newname
|
Chris@87
|
786 groupcache[groupcounter]['from']='fromsky'
|
Chris@87
|
787 expectbegin=0
|
Chris@87
|
788 if case in ['begin', 'call', 'callfun']:
|
Chris@87
|
789 # Crack line => block,name,args,result
|
Chris@87
|
790 block = block.lower()
|
Chris@87
|
791 if re.match(r'block\s*data', block, re.I): block='block data'
|
Chris@87
|
792 if re.match(r'python\s*module', block, re.I): block='python module'
|
Chris@87
|
793 name, args, result, bind = _resolvenameargspattern(m.group('after'))
|
Chris@87
|
794 if name is None:
|
Chris@87
|
795 if block=='block data':
|
Chris@87
|
796 name = '_BLOCK_DATA_'
|
Chris@87
|
797 else:
|
Chris@87
|
798 name = ''
|
Chris@87
|
799 if block not in ['interface', 'block data']:
|
Chris@87
|
800 outmess('analyzeline: No name/args pattern found for line.\n')
|
Chris@87
|
801
|
Chris@87
|
802 previous_context = (block, name, groupcounter)
|
Chris@87
|
803 if args: args=rmbadname([x.strip() for x in markoutercomma(args).split('@,@')])
|
Chris@87
|
804 else: args=[]
|
Chris@87
|
805 if '' in args:
|
Chris@87
|
806 while '' in args:
|
Chris@87
|
807 args.remove('')
|
Chris@87
|
808 outmess('analyzeline: argument list is malformed (missing argument).\n')
|
Chris@87
|
809
|
Chris@87
|
810 # end of crack line => block,name,args,result
|
Chris@87
|
811 needmodule=0
|
Chris@87
|
812 needinterface=0
|
Chris@87
|
813
|
Chris@87
|
814 if case in ['call', 'callfun']:
|
Chris@87
|
815 needinterface=1
|
Chris@87
|
816 if 'args' not in groupcache[groupcounter]:
|
Chris@87
|
817 return
|
Chris@87
|
818 if name not in groupcache[groupcounter]['args']:
|
Chris@87
|
819 return
|
Chris@87
|
820 for it in grouplist[groupcounter]:
|
Chris@87
|
821 if it['name']==name:
|
Chris@87
|
822 return
|
Chris@87
|
823 if name in groupcache[groupcounter]['interfaced']:
|
Chris@87
|
824 return
|
Chris@87
|
825 block={'call':'subroutine','callfun':'function'}[case]
|
Chris@87
|
826 if f77modulename and neededmodule==-1 and groupcounter<=1:
|
Chris@87
|
827 neededmodule=groupcounter+2
|
Chris@87
|
828 needmodule=1
|
Chris@87
|
829 if block != 'interface':
|
Chris@87
|
830 needinterface=1
|
Chris@87
|
831 # Create new block(s)
|
Chris@87
|
832 groupcounter=groupcounter+1
|
Chris@87
|
833 groupcache[groupcounter]={}
|
Chris@87
|
834 grouplist[groupcounter]=[]
|
Chris@87
|
835 if needmodule:
|
Chris@87
|
836 if verbose>1:
|
Chris@87
|
837 outmess('analyzeline: Creating module block %s\n'%repr(f77modulename), 0)
|
Chris@87
|
838 groupname[groupcounter]='module'
|
Chris@87
|
839 groupcache[groupcounter]['block']='python module'
|
Chris@87
|
840 groupcache[groupcounter]['name']=f77modulename
|
Chris@87
|
841 groupcache[groupcounter]['from']=''
|
Chris@87
|
842 groupcache[groupcounter]['body']=[]
|
Chris@87
|
843 groupcache[groupcounter]['externals']=[]
|
Chris@87
|
844 groupcache[groupcounter]['interfaced']=[]
|
Chris@87
|
845 groupcache[groupcounter]['vars']={}
|
Chris@87
|
846 groupcounter=groupcounter+1
|
Chris@87
|
847 groupcache[groupcounter]={}
|
Chris@87
|
848 grouplist[groupcounter]=[]
|
Chris@87
|
849 if needinterface:
|
Chris@87
|
850 if verbose>1:
|
Chris@87
|
851 outmess('analyzeline: Creating additional interface block (groupcounter=%s).\n' % (groupcounter), 0)
|
Chris@87
|
852 groupname[groupcounter]='interface'
|
Chris@87
|
853 groupcache[groupcounter]['block']='interface'
|
Chris@87
|
854 groupcache[groupcounter]['name']='unknown_interface'
|
Chris@87
|
855 groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], groupcache[groupcounter-1]['name'])
|
Chris@87
|
856 groupcache[groupcounter]['body']=[]
|
Chris@87
|
857 groupcache[groupcounter]['externals']=[]
|
Chris@87
|
858 groupcache[groupcounter]['interfaced']=[]
|
Chris@87
|
859 groupcache[groupcounter]['vars']={}
|
Chris@87
|
860 groupcounter=groupcounter+1
|
Chris@87
|
861 groupcache[groupcounter]={}
|
Chris@87
|
862 grouplist[groupcounter]=[]
|
Chris@87
|
863 groupname[groupcounter]=block
|
Chris@87
|
864 groupcache[groupcounter]['block']=block
|
Chris@87
|
865 if not name: name='unknown_'+block
|
Chris@87
|
866 groupcache[groupcounter]['prefix']=m.group('before')
|
Chris@87
|
867 groupcache[groupcounter]['name']=rmbadname1(name)
|
Chris@87
|
868 groupcache[groupcounter]['result']=result
|
Chris@87
|
869 if groupcounter==1:
|
Chris@87
|
870 groupcache[groupcounter]['from']=currentfilename
|
Chris@87
|
871 else:
|
Chris@87
|
872 if f77modulename and groupcounter==3:
|
Chris@87
|
873 groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], currentfilename)
|
Chris@87
|
874 else:
|
Chris@87
|
875 groupcache[groupcounter]['from']='%s:%s'%(groupcache[groupcounter-1]['from'], groupcache[groupcounter-1]['name'])
|
Chris@87
|
876 for k in list(groupcache[groupcounter].keys()):
|
Chris@87
|
877 if not groupcache[groupcounter][k]:
|
Chris@87
|
878 del groupcache[groupcounter][k]
|
Chris@87
|
879
|
Chris@87
|
880 groupcache[groupcounter]['args']=args
|
Chris@87
|
881 groupcache[groupcounter]['body']=[]
|
Chris@87
|
882 groupcache[groupcounter]['externals']=[]
|
Chris@87
|
883 groupcache[groupcounter]['interfaced']=[]
|
Chris@87
|
884 groupcache[groupcounter]['vars']={}
|
Chris@87
|
885 groupcache[groupcounter]['entry']={}
|
Chris@87
|
886 # end of creation
|
Chris@87
|
887 if block=='type':
|
Chris@87
|
888 groupcache[groupcounter]['varnames'] = []
|
Chris@87
|
889
|
Chris@87
|
890 if case in ['call', 'callfun']: # set parents variables
|
Chris@87
|
891 if name not in groupcache[groupcounter-2]['externals']:
|
Chris@87
|
892 groupcache[groupcounter-2]['externals'].append(name)
|
Chris@87
|
893 groupcache[groupcounter]['vars']=copy.deepcopy(groupcache[groupcounter-2]['vars'])
|
Chris@87
|
894 #try: del groupcache[groupcounter]['vars'][groupcache[groupcounter-2]['name']]
|
Chris@87
|
895 #except: pass
|
Chris@87
|
896 try: del groupcache[groupcounter]['vars'][name][groupcache[groupcounter]['vars'][name]['attrspec'].index('external')]
|
Chris@87
|
897 except: pass
|
Chris@87
|
898 if block in ['function', 'subroutine']: # set global attributes
|
Chris@87
|
899 try: groupcache[groupcounter]['vars'][name]=appenddecl(groupcache[groupcounter]['vars'][name], groupcache[groupcounter-2]['vars'][''])
|
Chris@87
|
900 except: pass
|
Chris@87
|
901 if case=='callfun': # return type
|
Chris@87
|
902 if result and result in groupcache[groupcounter]['vars']:
|
Chris@87
|
903 if not name==result:
|
Chris@87
|
904 groupcache[groupcounter]['vars'][name]=appenddecl(groupcache[groupcounter]['vars'][name], groupcache[groupcounter]['vars'][result])
|
Chris@87
|
905 #if groupcounter>1: # name is interfaced
|
Chris@87
|
906 try: groupcache[groupcounter-2]['interfaced'].append(name)
|
Chris@87
|
907 except: pass
|
Chris@87
|
908 if block=='function':
|
Chris@87
|
909 t=typespattern[0].match(m.group('before')+' '+name)
|
Chris@87
|
910 if t:
|
Chris@87
|
911 typespec, selector, attr, edecl=cracktypespec0(t.group('this'), t.group('after'))
|
Chris@87
|
912 updatevars(typespec, selector, attr, edecl)
|
Chris@87
|
913
|
Chris@87
|
914 if case in ['call', 'callfun']:
|
Chris@87
|
915 grouplist[groupcounter-1].append(groupcache[groupcounter])
|
Chris@87
|
916 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
|
Chris@87
|
917 del grouplist[groupcounter]
|
Chris@87
|
918 groupcounter=groupcounter-1 # end routine
|
Chris@87
|
919 grouplist[groupcounter-1].append(groupcache[groupcounter])
|
Chris@87
|
920 grouplist[groupcounter-1][-1]['body']=grouplist[groupcounter]
|
Chris@87
|
921 del grouplist[groupcounter]
|
Chris@87
|
922 groupcounter=groupcounter-1 # end interface
|
Chris@87
|
923
|
Chris@87
|
924 elif case=='entry':
|
Chris@87
|
925 name, args, result, bind=_resolvenameargspattern(m.group('after'))
|
Chris@87
|
926 if name is not None:
|
Chris@87
|
927 if args:
|
Chris@87
|
928 args=rmbadname([x.strip() for x in markoutercomma(args).split('@,@')])
|
Chris@87
|
929 else: args=[]
|
Chris@87
|
930 assert result is None, repr(result)
|
Chris@87
|
931 groupcache[groupcounter]['entry'][name] = args
|
Chris@87
|
932 previous_context = ('entry', name, groupcounter)
|
Chris@87
|
933 elif case=='type':
|
Chris@87
|
934 typespec, selector, attr, edecl=cracktypespec0(block, m.group('after'))
|
Chris@87
|
935 last_name = updatevars(typespec, selector, attr, edecl)
|
Chris@87
|
936 if last_name is not None:
|
Chris@87
|
937 previous_context = ('variable', last_name, groupcounter)
|
Chris@87
|
938 elif case in ['dimension', 'intent', 'optional', 'required', 'external', 'public', 'private', 'intrisic']:
|
Chris@87
|
939 edecl=groupcache[groupcounter]['vars']
|
Chris@87
|
940 ll=m.group('after').strip()
|
Chris@87
|
941 i=ll.find('::')
|
Chris@87
|
942 if i<0 and case=='intent':
|
Chris@87
|
943 i=markouterparen(ll).find('@)@')-2
|
Chris@87
|
944 ll=ll[:i+1]+'::'+ll[i+1:]
|
Chris@87
|
945 i=ll.find('::')
|
Chris@87
|
946 if ll[i:]=='::' and 'args' in groupcache[groupcounter]:
|
Chris@87
|
947 outmess('All arguments will have attribute %s%s\n'%(m.group('this'), ll[:i]))
|
Chris@87
|
948 ll = ll + ','.join(groupcache[groupcounter]['args'])
|
Chris@87
|
949 if i<0:i=0;pl=''
|
Chris@87
|
950 else: pl=ll[:i].strip();ll=ll[i+2:]
|
Chris@87
|
951 ch = markoutercomma(pl).split('@,@')
|
Chris@87
|
952 if len(ch)>1:
|
Chris@87
|
953 pl = ch[0]
|
Chris@87
|
954 outmess('analyzeline: cannot handle multiple attributes without type specification. Ignoring %r.\n' % (','.join(ch[1:])))
|
Chris@87
|
955 last_name = None
|
Chris@87
|
956
|
Chris@87
|
957 for e in [x.strip() for x in markoutercomma(ll).split('@,@')]:
|
Chris@87
|
958 m1=namepattern.match(e)
|
Chris@87
|
959 if not m1:
|
Chris@87
|
960 if case in ['public', 'private']: k=''
|
Chris@87
|
961 else:
|
Chris@87
|
962 print(m.groupdict())
|
Chris@87
|
963 outmess('analyzeline: no name pattern found in %s statement for %s. Skipping.\n'%(case, repr(e)))
|
Chris@87
|
964 continue
|
Chris@87
|
965 else:
|
Chris@87
|
966 k=rmbadname1(m1.group('name'))
|
Chris@87
|
967 if k not in edecl:
|
Chris@87
|
968 edecl[k]={}
|
Chris@87
|
969 if case=='dimension':
|
Chris@87
|
970 ap=case+m1.group('after')
|
Chris@87
|
971 if case=='intent':
|
Chris@87
|
972 ap=m.group('this')+pl
|
Chris@87
|
973 if _intentcallbackpattern.match(ap):
|
Chris@87
|
974 if k not in groupcache[groupcounter]['args']:
|
Chris@87
|
975 if groupcounter>1:
|
Chris@87
|
976 if '__user__' not in groupcache[groupcounter-2]['name']:
|
Chris@87
|
977 outmess('analyzeline: missing __user__ module (could be nothing)\n')
|
Chris@87
|
978 if k!=groupcache[groupcounter]['name']: # fixes ticket 1693
|
Chris@87
|
979 outmess('analyzeline: appending intent(callback) %s'\
|
Chris@87
|
980 ' to %s arguments\n' % (k, groupcache[groupcounter]['name']))
|
Chris@87
|
981 groupcache[groupcounter]['args'].append(k)
|
Chris@87
|
982 else:
|
Chris@87
|
983 errmess('analyzeline: intent(callback) %s is ignored' % (k))
|
Chris@87
|
984 else:
|
Chris@87
|
985 errmess('analyzeline: intent(callback) %s is already'\
|
Chris@87
|
986 ' in argument list' % (k))
|
Chris@87
|
987 if case in ['optional', 'required', 'public', 'external', 'private', 'intrisic']:
|
Chris@87
|
988 ap=case
|
Chris@87
|
989 if 'attrspec' in edecl[k]:
|
Chris@87
|
990 edecl[k]['attrspec'].append(ap)
|
Chris@87
|
991 else:
|
Chris@87
|
992 edecl[k]['attrspec']=[ap]
|
Chris@87
|
993 if case=='external':
|
Chris@87
|
994 if groupcache[groupcounter]['block']=='program':
|
Chris@87
|
995 outmess('analyzeline: ignoring program arguments\n')
|
Chris@87
|
996 continue
|
Chris@87
|
997 if k not in groupcache[groupcounter]['args']:
|
Chris@87
|
998 #outmess('analyzeline: ignoring external %s (not in arguments list)\n'%(`k`))
|
Chris@87
|
999 continue
|
Chris@87
|
1000 if 'externals' not in groupcache[groupcounter]:
|
Chris@87
|
1001 groupcache[groupcounter]['externals']=[]
|
Chris@87
|
1002 groupcache[groupcounter]['externals'].append(k)
|
Chris@87
|
1003 last_name = k
|
Chris@87
|
1004 groupcache[groupcounter]['vars']=edecl
|
Chris@87
|
1005 if last_name is not None:
|
Chris@87
|
1006 previous_context = ('variable', last_name, groupcounter)
|
Chris@87
|
1007 elif case=='parameter':
|
Chris@87
|
1008 edecl=groupcache[groupcounter]['vars']
|
Chris@87
|
1009 ll=m.group('after').strip()[1:-1]
|
Chris@87
|
1010 last_name = None
|
Chris@87
|
1011 for e in markoutercomma(ll).split('@,@'):
|
Chris@87
|
1012 try:
|
Chris@87
|
1013 k, initexpr=[x.strip() for x in e.split('=')]
|
Chris@87
|
1014 except:
|
Chris@87
|
1015 outmess('analyzeline: could not extract name,expr in parameter statement "%s" of "%s"\n'%(e, ll));continue
|
Chris@87
|
1016 params = get_parameters(edecl)
|
Chris@87
|
1017 k=rmbadname1(k)
|
Chris@87
|
1018 if k not in edecl:
|
Chris@87
|
1019 edecl[k]={}
|
Chris@87
|
1020 if '=' in edecl[k] and (not edecl[k]['=']==initexpr):
|
Chris@87
|
1021 outmess('analyzeline: Overwriting the value of parameter "%s" ("%s") with "%s".\n'%(k, edecl[k]['='], initexpr))
|
Chris@87
|
1022 t = determineexprtype(initexpr, params)
|
Chris@87
|
1023 if t:
|
Chris@87
|
1024 if t.get('typespec')=='real':
|
Chris@87
|
1025 tt = list(initexpr)
|
Chris@87
|
1026 for m in real16pattern.finditer(initexpr):
|
Chris@87
|
1027 tt[m.start():m.end()] = list(\
|
Chris@87
|
1028 initexpr[m.start():m.end()].lower().replace('d', 'e'))
|
Chris@87
|
1029 initexpr = ''.join(tt)
|
Chris@87
|
1030 elif t.get('typespec')=='complex':
|
Chris@87
|
1031 initexpr = initexpr[1:].lower().replace('d', 'e').\
|
Chris@87
|
1032 replace(',', '+1j*(')
|
Chris@87
|
1033 try:
|
Chris@87
|
1034 v = eval(initexpr, {}, params)
|
Chris@87
|
1035 except (SyntaxError, NameError, TypeError) as msg:
|
Chris@87
|
1036 errmess('analyzeline: Failed to evaluate %r. Ignoring: %s\n'\
|
Chris@87
|
1037 % (initexpr, msg))
|
Chris@87
|
1038 continue
|
Chris@87
|
1039 edecl[k]['='] = repr(v)
|
Chris@87
|
1040 if 'attrspec' in edecl[k]:
|
Chris@87
|
1041 edecl[k]['attrspec'].append('parameter')
|
Chris@87
|
1042 else: edecl[k]['attrspec']=['parameter']
|
Chris@87
|
1043 last_name = k
|
Chris@87
|
1044 groupcache[groupcounter]['vars']=edecl
|
Chris@87
|
1045 if last_name is not None:
|
Chris@87
|
1046 previous_context = ('variable', last_name, groupcounter)
|
Chris@87
|
1047 elif case=='implicit':
|
Chris@87
|
1048 if m.group('after').strip().lower()=='none':
|
Chris@87
|
1049 groupcache[groupcounter]['implicit']=None
|
Chris@87
|
1050 elif m.group('after'):
|
Chris@87
|
1051 if 'implicit' in groupcache[groupcounter]:
|
Chris@87
|
1052 impl=groupcache[groupcounter]['implicit']
|
Chris@87
|
1053 else: impl={}
|
Chris@87
|
1054 if impl is None:
|
Chris@87
|
1055 outmess('analyzeline: Overwriting earlier "implicit none" statement.\n')
|
Chris@87
|
1056 impl={}
|
Chris@87
|
1057 for e in markoutercomma(m.group('after')).split('@,@'):
|
Chris@87
|
1058 decl={}
|
Chris@87
|
1059 m1=re.match(r'\s*(?P<this>.*?)\s*(\(\s*(?P<after>[a-z-, ]+)\s*\)\s*|)\Z', e, re.I)
|
Chris@87
|
1060 if not m1:
|
Chris@87
|
1061 outmess('analyzeline: could not extract info of implicit statement part "%s"\n'%(e));continue
|
Chris@87
|
1062 m2=typespattern4implicit.match(m1.group('this'))
|
Chris@87
|
1063 if not m2:
|
Chris@87
|
1064 outmess('analyzeline: could not extract types pattern of implicit statement part "%s"\n'%(e));continue
|
Chris@87
|
1065 typespec, selector, attr, edecl=cracktypespec0(m2.group('this'), m2.group('after'))
|
Chris@87
|
1066 kindselect, charselect, typename=cracktypespec(typespec, selector)
|
Chris@87
|
1067 decl['typespec']=typespec
|
Chris@87
|
1068 decl['kindselector']=kindselect
|
Chris@87
|
1069 decl['charselector']=charselect
|
Chris@87
|
1070 decl['typename']=typename
|
Chris@87
|
1071 for k in list(decl.keys()):
|
Chris@87
|
1072 if not decl[k]: del decl[k]
|
Chris@87
|
1073 for r in markoutercomma(m1.group('after')).split('@,@'):
|
Chris@87
|
1074 if '-' in r:
|
Chris@87
|
1075 try: begc, endc=[x.strip() for x in r.split('-')]
|
Chris@87
|
1076 except:
|
Chris@87
|
1077 outmess('analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement\n'%r);continue
|
Chris@87
|
1078 else: begc=endc=r.strip()
|
Chris@87
|
1079 if not len(begc)==len(endc)==1:
|
Chris@87
|
1080 outmess('analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement (2)\n'%r);continue
|
Chris@87
|
1081 for o in range(ord(begc), ord(endc)+1):
|
Chris@87
|
1082 impl[chr(o)]=decl
|
Chris@87
|
1083 groupcache[groupcounter]['implicit']=impl
|
Chris@87
|
1084 elif case=='data':
|
Chris@87
|
1085 ll=[]
|
Chris@87
|
1086 dl='';il='';f=0;fc=1;inp=0
|
Chris@87
|
1087 for c in m.group('after'):
|
Chris@87
|
1088 if not inp:
|
Chris@87
|
1089 if c=="'": fc=not fc
|
Chris@87
|
1090 if c=='/' and fc: f=f+1;continue
|
Chris@87
|
1091 if c=='(': inp = inp + 1
|
Chris@87
|
1092 elif c==')': inp = inp - 1
|
Chris@87
|
1093 if f==0: dl=dl+c
|
Chris@87
|
1094 elif f==1: il=il+c
|
Chris@87
|
1095 elif f==2:
|
Chris@87
|
1096 dl = dl.strip()
|
Chris@87
|
1097 if dl.startswith(','):
|
Chris@87
|
1098 dl = dl[1:].strip()
|
Chris@87
|
1099 ll.append([dl, il])
|
Chris@87
|
1100 dl=c;il='';f=0
|
Chris@87
|
1101 if f==2:
|
Chris@87
|
1102 dl = dl.strip()
|
Chris@87
|
1103 if dl.startswith(','):
|
Chris@87
|
1104 dl = dl[1:].strip()
|
Chris@87
|
1105 ll.append([dl, il])
|
Chris@87
|
1106 vars={}
|
Chris@87
|
1107 if 'vars' in groupcache[groupcounter]:
|
Chris@87
|
1108 vars=groupcache[groupcounter]['vars']
|
Chris@87
|
1109 last_name = None
|
Chris@87
|
1110 for l in ll:
|
Chris@87
|
1111 l=[x.strip() for x in l]
|
Chris@87
|
1112 if l[0][0]==',':l[0]=l[0][1:]
|
Chris@87
|
1113 if l[0][0]=='(':
|
Chris@87
|
1114 outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n'%l[0])
|
Chris@87
|
1115 continue
|
Chris@87
|
1116 #if '(' in l[0]:
|
Chris@87
|
1117 # #outmess('analyzeline: ignoring this data statement.\n')
|
Chris@87
|
1118 # continue
|
Chris@87
|
1119 i=0;j=0;llen=len(l[1])
|
Chris@87
|
1120 for v in rmbadname([x.strip() for x in markoutercomma(l[0]).split('@,@')]):
|
Chris@87
|
1121 if v[0]=='(':
|
Chris@87
|
1122 outmess('analyzeline: implied-DO list "%s" is not supported. Skipping.\n'%v)
|
Chris@87
|
1123 # XXX: subsequent init expressions may get wrong values.
|
Chris@87
|
1124 # Ignoring since data statements are irrelevant for wrapping.
|
Chris@87
|
1125 continue
|
Chris@87
|
1126 fc=0
|
Chris@87
|
1127 while (i<llen) and (fc or not l[1][i]==','):
|
Chris@87
|
1128 if l[1][i]=="'": fc=not fc
|
Chris@87
|
1129 i=i+1
|
Chris@87
|
1130 i=i+1
|
Chris@87
|
1131 #v,l[1][j:i-1]=name,initvalue
|
Chris@87
|
1132 if v not in vars:
|
Chris@87
|
1133 vars[v]={}
|
Chris@87
|
1134 if '=' in vars[v] and not vars[v]['=']==l[1][j:i-1]:
|
Chris@87
|
1135 outmess('analyzeline: changing init expression of "%s" ("%s") to "%s"\n'%(v, vars[v]['='], l[1][j:i-1]))
|
Chris@87
|
1136 vars[v]['=']=l[1][j:i-1]
|
Chris@87
|
1137 j=i
|
Chris@87
|
1138 last_name = v
|
Chris@87
|
1139 groupcache[groupcounter]['vars']=vars
|
Chris@87
|
1140 if last_name is not None:
|
Chris@87
|
1141 previous_context = ('variable', last_name, groupcounter)
|
Chris@87
|
1142 elif case=='common':
|
Chris@87
|
1143 line=m.group('after').strip()
|
Chris@87
|
1144 if not line[0]=='/':line='//'+line
|
Chris@87
|
1145 cl=[]
|
Chris@87
|
1146 f=0;bn='';ol=''
|
Chris@87
|
1147 for c in line:
|
Chris@87
|
1148 if c=='/':f=f+1;continue
|
Chris@87
|
1149 if f>=3:
|
Chris@87
|
1150 bn = bn.strip()
|
Chris@87
|
1151 if not bn: bn='_BLNK_'
|
Chris@87
|
1152 cl.append([bn, ol])
|
Chris@87
|
1153 f=f-2;bn='';ol=''
|
Chris@87
|
1154 if f%2: bn=bn+c
|
Chris@87
|
1155 else: ol=ol+c
|
Chris@87
|
1156 bn = bn.strip()
|
Chris@87
|
1157 if not bn: bn='_BLNK_'
|
Chris@87
|
1158 cl.append([bn, ol])
|
Chris@87
|
1159 commonkey={}
|
Chris@87
|
1160 if 'common' in groupcache[groupcounter]:
|
Chris@87
|
1161 commonkey=groupcache[groupcounter]['common']
|
Chris@87
|
1162 for c in cl:
|
Chris@87
|
1163 if c[0] in commonkey:
|
Chris@87
|
1164 outmess('analyzeline: previously defined common block encountered. Skipping.\n')
|
Chris@87
|
1165 continue
|
Chris@87
|
1166 commonkey[c[0]]=[]
|
Chris@87
|
1167 for i in [x.strip() for x in markoutercomma(c[1]).split('@,@')]:
|
Chris@87
|
1168 if i: commonkey[c[0]].append(i)
|
Chris@87
|
1169 groupcache[groupcounter]['common']=commonkey
|
Chris@87
|
1170 previous_context = ('common', bn, groupcounter)
|
Chris@87
|
1171 elif case=='use':
|
Chris@87
|
1172 m1=re.match(r'\A\s*(?P<name>\b[\w]+\b)\s*((,(\s*\bonly\b\s*:|(?P<notonly>))\s*(?P<list>.*))|)\s*\Z', m.group('after'), re.I)
|
Chris@87
|
1173 if m1:
|
Chris@87
|
1174 mm=m1.groupdict()
|
Chris@87
|
1175 if 'use' not in groupcache[groupcounter]:
|
Chris@87
|
1176 groupcache[groupcounter]['use']={}
|
Chris@87
|
1177 name=m1.group('name')
|
Chris@87
|
1178 groupcache[groupcounter]['use'][name]={}
|
Chris@87
|
1179 isonly=0
|
Chris@87
|
1180 if 'list' in mm and mm['list'] is not None:
|
Chris@87
|
1181 if 'notonly' in mm and mm['notonly'] is None:
|
Chris@87
|
1182 isonly=1
|
Chris@87
|
1183 groupcache[groupcounter]['use'][name]['only']=isonly
|
Chris@87
|
1184 ll=[x.strip() for x in mm['list'].split(',')]
|
Chris@87
|
1185 rl={}
|
Chris@87
|
1186 for l in ll:
|
Chris@87
|
1187 if '=' in l:
|
Chris@87
|
1188 m2=re.match(r'\A\s*(?P<local>\b[\w]+\b)\s*=\s*>\s*(?P<use>\b[\w]+\b)\s*\Z', l, re.I)
|
Chris@87
|
1189 if m2: rl[m2.group('local').strip()]=m2.group('use').strip()
|
Chris@87
|
1190 else:
|
Chris@87
|
1191 outmess('analyzeline: Not local=>use pattern found in %s\n'%repr(l))
|
Chris@87
|
1192 else:
|
Chris@87
|
1193 rl[l]=l
|
Chris@87
|
1194 groupcache[groupcounter]['use'][name]['map']=rl
|
Chris@87
|
1195 else:
|
Chris@87
|
1196 pass
|
Chris@87
|
1197 else:
|
Chris@87
|
1198 print(m.groupdict())
|
Chris@87
|
1199 outmess('analyzeline: Could not crack the use statement.\n')
|
Chris@87
|
1200 elif case in ['f2pyenhancements']:
|
Chris@87
|
1201 if 'f2pyenhancements' not in groupcache[groupcounter]:
|
Chris@87
|
1202 groupcache[groupcounter]['f2pyenhancements'] = {}
|
Chris@87
|
1203 d = groupcache[groupcounter]['f2pyenhancements']
|
Chris@87
|
1204 if m.group('this')=='usercode' and 'usercode' in d:
|
Chris@87
|
1205 if isinstance(d['usercode'], str):
|
Chris@87
|
1206 d['usercode'] = [d['usercode']]
|
Chris@87
|
1207 d['usercode'].append(m.group('after'))
|
Chris@87
|
1208 else:
|
Chris@87
|
1209 d[m.group('this')] = m.group('after')
|
Chris@87
|
1210 elif case=='multiline':
|
Chris@87
|
1211 if previous_context is None:
|
Chris@87
|
1212 if verbose:
|
Chris@87
|
1213 outmess('analyzeline: No context for multiline block.\n')
|
Chris@87
|
1214 return
|
Chris@87
|
1215 gc = groupcounter
|
Chris@87
|
1216 #gc = previous_context[2]
|
Chris@87
|
1217 appendmultiline(groupcache[gc],
|
Chris@87
|
1218 previous_context[:2],
|
Chris@87
|
1219 m.group('this'))
|
Chris@87
|
1220 else:
|
Chris@87
|
1221 if verbose>1:
|
Chris@87
|
1222 print(m.groupdict())
|
Chris@87
|
1223 outmess('analyzeline: No code implemented for line.\n')
|
Chris@87
|
1224
|
Chris@87
|
1225 def appendmultiline(group, context_name, ml):
|
Chris@87
|
1226 if 'f2pymultilines' not in group:
|
Chris@87
|
1227 group['f2pymultilines'] = {}
|
Chris@87
|
1228 d = group['f2pymultilines']
|
Chris@87
|
1229 if context_name not in d:
|
Chris@87
|
1230 d[context_name] = []
|
Chris@87
|
1231 d[context_name].append(ml)
|
Chris@87
|
1232 return
|
Chris@87
|
1233
|
Chris@87
|
1234 def cracktypespec0(typespec, ll):
|
Chris@87
|
1235 selector=None
|
Chris@87
|
1236 attr=None
|
Chris@87
|
1237 if re.match(r'double\s*complex', typespec, re.I): typespec='double complex'
|
Chris@87
|
1238 elif re.match(r'double\s*precision', typespec, re.I): typespec='double precision'
|
Chris@87
|
1239 else: typespec=typespec.strip().lower()
|
Chris@87
|
1240 m1=selectpattern.match(markouterparen(ll))
|
Chris@87
|
1241 if not m1:
|
Chris@87
|
1242 outmess('cracktypespec0: no kind/char_selector pattern found for line.\n')
|
Chris@87
|
1243 return
|
Chris@87
|
1244 d=m1.groupdict()
|
Chris@87
|
1245 for k in list(d.keys()): d[k]=unmarkouterparen(d[k])
|
Chris@87
|
1246 if typespec in ['complex', 'integer', 'logical', 'real', 'character', 'type']:
|
Chris@87
|
1247 selector=d['this']
|
Chris@87
|
1248 ll=d['after']
|
Chris@87
|
1249 i=ll.find('::')
|
Chris@87
|
1250 if i>=0:
|
Chris@87
|
1251 attr=ll[:i].strip()
|
Chris@87
|
1252 ll=ll[i+2:]
|
Chris@87
|
1253 return typespec, selector, attr, ll
|
Chris@87
|
1254 #####
|
Chris@87
|
1255 namepattern=re.compile(r'\s*(?P<name>\b[\w]+\b)\s*(?P<after>.*)\s*\Z', re.I)
|
Chris@87
|
1256 kindselector=re.compile(r'\s*(\(\s*(kind\s*=)?\s*(?P<kind>.*)\s*\)|[*]\s*(?P<kind2>.*?))\s*\Z', re.I)
|
Chris@87
|
1257 charselector=re.compile(r'\s*(\((?P<lenkind>.*)\)|[*]\s*(?P<charlen>.*))\s*\Z', re.I)
|
Chris@87
|
1258 lenkindpattern=re.compile(r'\s*(kind\s*=\s*(?P<kind>.*?)\s*(@,@\s*len\s*=\s*(?P<len>.*)|)|(len\s*=\s*|)(?P<len2>.*?)\s*(@,@\s*(kind\s*=\s*|)(?P<kind2>.*)|))\s*\Z', re.I)
|
Chris@87
|
1259 lenarraypattern=re.compile(r'\s*(@\(@\s*(?!/)\s*(?P<array>.*?)\s*@\)@\s*[*]\s*(?P<len>.*?)|([*]\s*(?P<len2>.*?)|)\s*(@\(@\s*(?!/)\s*(?P<array2>.*?)\s*@\)@|))\s*(=\s*(?P<init>.*?)|(@\(@|)/\s*(?P<init2>.*?)\s*/(@\)@|)|)\s*\Z', re.I)
|
Chris@87
|
1260 def removespaces(expr):
|
Chris@87
|
1261 expr=expr.strip()
|
Chris@87
|
1262 if len(expr)<=1: return expr
|
Chris@87
|
1263 expr2=expr[0]
|
Chris@87
|
1264 for i in range(1, len(expr)-1):
|
Chris@87
|
1265 if expr[i]==' ' and \
|
Chris@87
|
1266 ((expr[i+1] in "()[]{}=+-/* ") or (expr[i-1] in "()[]{}=+-/* ")): continue
|
Chris@87
|
1267 expr2=expr2+expr[i]
|
Chris@87
|
1268 expr2=expr2+expr[-1]
|
Chris@87
|
1269 return expr2
|
Chris@87
|
1270 def markinnerspaces(line):
|
Chris@87
|
1271 l='';f=0
|
Chris@87
|
1272 cc='\''
|
Chris@87
|
1273 cc1='"'
|
Chris@87
|
1274 cb=''
|
Chris@87
|
1275 for c in line:
|
Chris@87
|
1276 if cb=='\\' and c in ['\\', '\'', '"']:
|
Chris@87
|
1277 l=l+c
|
Chris@87
|
1278 cb=c
|
Chris@87
|
1279 continue
|
Chris@87
|
1280 if f==0 and c in ['\'', '"']: cc=c; cc1={'\'':'"','"':'\''}[c]
|
Chris@87
|
1281 if c==cc:f=f+1
|
Chris@87
|
1282 elif c==cc:f=f-1
|
Chris@87
|
1283 elif c==' ' and f==1: l=l+'@_@'; continue
|
Chris@87
|
1284 l=l+c;cb=c
|
Chris@87
|
1285 return l
|
Chris@87
|
1286 def updatevars(typespec, selector, attrspec, entitydecl):
|
Chris@87
|
1287 global groupcache, groupcounter
|
Chris@87
|
1288 last_name = None
|
Chris@87
|
1289 kindselect, charselect, typename=cracktypespec(typespec, selector)
|
Chris@87
|
1290 if attrspec:
|
Chris@87
|
1291 attrspec=[x.strip() for x in markoutercomma(attrspec).split('@,@')]
|
Chris@87
|
1292 l = []
|
Chris@87
|
1293 c = re.compile(r'(?P<start>[a-zA-Z]+)')
|
Chris@87
|
1294 for a in attrspec:
|
Chris@87
|
1295 if not a:
|
Chris@87
|
1296 continue
|
Chris@87
|
1297 m = c.match(a)
|
Chris@87
|
1298 if m:
|
Chris@87
|
1299 s = m.group('start').lower()
|
Chris@87
|
1300 a = s + a[len(s):]
|
Chris@87
|
1301 l.append(a)
|
Chris@87
|
1302 attrspec = l
|
Chris@87
|
1303 el=[x.strip() for x in markoutercomma(entitydecl).split('@,@')]
|
Chris@87
|
1304 el1=[]
|
Chris@87
|
1305 for e in el:
|
Chris@87
|
1306 for e1 in [x.strip() for x in markoutercomma(removespaces(markinnerspaces(e)), comma=' ').split('@ @')]:
|
Chris@87
|
1307 if e1: el1.append(e1.replace('@_@', ' '))
|
Chris@87
|
1308 for e in el1:
|
Chris@87
|
1309 m=namepattern.match(e)
|
Chris@87
|
1310 if not m:
|
Chris@87
|
1311 outmess('updatevars: no name pattern found for entity=%s. Skipping.\n'%(repr(e)))
|
Chris@87
|
1312 continue
|
Chris@87
|
1313 ename=rmbadname1(m.group('name'))
|
Chris@87
|
1314 edecl={}
|
Chris@87
|
1315 if ename in groupcache[groupcounter]['vars']:
|
Chris@87
|
1316 edecl=groupcache[groupcounter]['vars'][ename].copy()
|
Chris@87
|
1317 not_has_typespec = 'typespec' not in edecl
|
Chris@87
|
1318 if not_has_typespec:
|
Chris@87
|
1319 edecl['typespec']=typespec
|
Chris@87
|
1320 elif typespec and (not typespec==edecl['typespec']):
|
Chris@87
|
1321 outmess('updatevars: attempt to change the type of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['typespec'], typespec))
|
Chris@87
|
1322 if 'kindselector' not in edecl:
|
Chris@87
|
1323 edecl['kindselector']=copy.copy(kindselect)
|
Chris@87
|
1324 elif kindselect:
|
Chris@87
|
1325 for k in list(kindselect.keys()):
|
Chris@87
|
1326 if k in edecl['kindselector'] and (not kindselect[k]==edecl['kindselector'][k]):
|
Chris@87
|
1327 outmess('updatevars: attempt to change the kindselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (k, ename, edecl['kindselector'][k], kindselect[k]))
|
Chris@87
|
1328 else: edecl['kindselector'][k]=copy.copy(kindselect[k])
|
Chris@87
|
1329 if 'charselector' not in edecl and charselect:
|
Chris@87
|
1330 if not_has_typespec:
|
Chris@87
|
1331 edecl['charselector']=charselect
|
Chris@87
|
1332 else:
|
Chris@87
|
1333 errmess('updatevars:%s: attempt to change empty charselector to %r. Ignoring.\n' \
|
Chris@87
|
1334 %(ename, charselect))
|
Chris@87
|
1335 elif charselect:
|
Chris@87
|
1336 for k in list(charselect.keys()):
|
Chris@87
|
1337 if k in edecl['charselector'] and (not charselect[k]==edecl['charselector'][k]):
|
Chris@87
|
1338 outmess('updatevars: attempt to change the charselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (k, ename, edecl['charselector'][k], charselect[k]))
|
Chris@87
|
1339 else: edecl['charselector'][k]=copy.copy(charselect[k])
|
Chris@87
|
1340 if 'typename' not in edecl:
|
Chris@87
|
1341 edecl['typename']=typename
|
Chris@87
|
1342 elif typename and (not edecl['typename']==typename):
|
Chris@87
|
1343 outmess('updatevars: attempt to change the typename of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['typename'], typename))
|
Chris@87
|
1344 if 'attrspec' not in edecl:
|
Chris@87
|
1345 edecl['attrspec']=copy.copy(attrspec)
|
Chris@87
|
1346 elif attrspec:
|
Chris@87
|
1347 for a in attrspec:
|
Chris@87
|
1348 if a not in edecl['attrspec']:
|
Chris@87
|
1349 edecl['attrspec'].append(a)
|
Chris@87
|
1350 else:
|
Chris@87
|
1351 edecl['typespec']=copy.copy(typespec)
|
Chris@87
|
1352 edecl['kindselector']=copy.copy(kindselect)
|
Chris@87
|
1353 edecl['charselector']=copy.copy(charselect)
|
Chris@87
|
1354 edecl['typename']=typename
|
Chris@87
|
1355 edecl['attrspec']=copy.copy(attrspec)
|
Chris@87
|
1356 if m.group('after'):
|
Chris@87
|
1357 m1=lenarraypattern.match(markouterparen(m.group('after')))
|
Chris@87
|
1358 if m1:
|
Chris@87
|
1359 d1=m1.groupdict()
|
Chris@87
|
1360 for lk in ['len', 'array', 'init']:
|
Chris@87
|
1361 if d1[lk+'2'] is not None: d1[lk]=d1[lk+'2']; del d1[lk+'2']
|
Chris@87
|
1362 for k in list(d1.keys()):
|
Chris@87
|
1363 if d1[k] is not None: d1[k]=unmarkouterparen(d1[k])
|
Chris@87
|
1364 else: del d1[k]
|
Chris@87
|
1365 if 'len' in d1 and 'array' in d1:
|
Chris@87
|
1366 if d1['len']=='':
|
Chris@87
|
1367 d1['len']=d1['array']
|
Chris@87
|
1368 del d1['array']
|
Chris@87
|
1369 else:
|
Chris@87
|
1370 d1['array']=d1['array']+','+d1['len']
|
Chris@87
|
1371 del d1['len']
|
Chris@87
|
1372 errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n'%(typespec, e, typespec, ename, d1['array']))
|
Chris@87
|
1373 if 'array' in d1:
|
Chris@87
|
1374 dm = 'dimension(%s)'%d1['array']
|
Chris@87
|
1375 if 'attrspec' not in edecl or (not edecl['attrspec']):
|
Chris@87
|
1376 edecl['attrspec']=[dm]
|
Chris@87
|
1377 else:
|
Chris@87
|
1378 edecl['attrspec'].append(dm)
|
Chris@87
|
1379 for dm1 in edecl['attrspec']:
|
Chris@87
|
1380 if dm1[:9]=='dimension' and dm1!=dm:
|
Chris@87
|
1381 del edecl['attrspec'][-1]
|
Chris@87
|
1382 errmess('updatevars:%s: attempt to change %r to %r. Ignoring.\n' \
|
Chris@87
|
1383 % (ename, dm1, dm))
|
Chris@87
|
1384 break
|
Chris@87
|
1385
|
Chris@87
|
1386 if 'len' in d1:
|
Chris@87
|
1387 if typespec in ['complex', 'integer', 'logical', 'real']:
|
Chris@87
|
1388 if ('kindselector' not in edecl) or (not edecl['kindselector']):
|
Chris@87
|
1389 edecl['kindselector']={}
|
Chris@87
|
1390 edecl['kindselector']['*']=d1['len']
|
Chris@87
|
1391 elif typespec == 'character':
|
Chris@87
|
1392 if ('charselector' not in edecl) or (not edecl['charselector']):
|
Chris@87
|
1393 edecl['charselector']={}
|
Chris@87
|
1394 if 'len' in edecl['charselector']:
|
Chris@87
|
1395 del edecl['charselector']['len']
|
Chris@87
|
1396 edecl['charselector']['*']=d1['len']
|
Chris@87
|
1397 if 'init' in d1:
|
Chris@87
|
1398 if '=' in edecl and (not edecl['=']==d1['init']):
|
Chris@87
|
1399 outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % (ename, edecl['='], d1['init']))
|
Chris@87
|
1400 else:
|
Chris@87
|
1401 edecl['=']=d1['init']
|
Chris@87
|
1402 else:
|
Chris@87
|
1403 outmess('updatevars: could not crack entity declaration "%s". Ignoring.\n'%(ename+m.group('after')))
|
Chris@87
|
1404 for k in list(edecl.keys()):
|
Chris@87
|
1405 if not edecl[k]:
|
Chris@87
|
1406 del edecl[k]
|
Chris@87
|
1407 groupcache[groupcounter]['vars'][ename]=edecl
|
Chris@87
|
1408 if 'varnames' in groupcache[groupcounter]:
|
Chris@87
|
1409 groupcache[groupcounter]['varnames'].append(ename)
|
Chris@87
|
1410 last_name = ename
|
Chris@87
|
1411 return last_name
|
Chris@87
|
1412
|
Chris@87
|
1413 def cracktypespec(typespec, selector):
|
Chris@87
|
1414 kindselect=None
|
Chris@87
|
1415 charselect=None
|
Chris@87
|
1416 typename=None
|
Chris@87
|
1417 if selector:
|
Chris@87
|
1418 if typespec in ['complex', 'integer', 'logical', 'real']:
|
Chris@87
|
1419 kindselect=kindselector.match(selector)
|
Chris@87
|
1420 if not kindselect:
|
Chris@87
|
1421 outmess('cracktypespec: no kindselector pattern found for %s\n'%(repr(selector)))
|
Chris@87
|
1422 return
|
Chris@87
|
1423 kindselect=kindselect.groupdict()
|
Chris@87
|
1424 kindselect['*']=kindselect['kind2']
|
Chris@87
|
1425 del kindselect['kind2']
|
Chris@87
|
1426 for k in list(kindselect.keys()):
|
Chris@87
|
1427 if not kindselect[k]: del kindselect[k]
|
Chris@87
|
1428 for k, i in list(kindselect.items()):
|
Chris@87
|
1429 kindselect[k] = rmbadname1(i)
|
Chris@87
|
1430 elif typespec=='character':
|
Chris@87
|
1431 charselect=charselector.match(selector)
|
Chris@87
|
1432 if not charselect:
|
Chris@87
|
1433 outmess('cracktypespec: no charselector pattern found for %s\n'%(repr(selector)))
|
Chris@87
|
1434 return
|
Chris@87
|
1435 charselect=charselect.groupdict()
|
Chris@87
|
1436 charselect['*']=charselect['charlen']
|
Chris@87
|
1437 del charselect['charlen']
|
Chris@87
|
1438 if charselect['lenkind']:
|
Chris@87
|
1439 lenkind=lenkindpattern.match(markoutercomma(charselect['lenkind']))
|
Chris@87
|
1440 lenkind=lenkind.groupdict()
|
Chris@87
|
1441 for lk in ['len', 'kind']:
|
Chris@87
|
1442 if lenkind[lk+'2']:
|
Chris@87
|
1443 lenkind[lk]=lenkind[lk+'2']
|
Chris@87
|
1444 charselect[lk]=lenkind[lk]
|
Chris@87
|
1445 del lenkind[lk+'2']
|
Chris@87
|
1446 del charselect['lenkind']
|
Chris@87
|
1447 for k in list(charselect.keys()):
|
Chris@87
|
1448 if not charselect[k]: del charselect[k]
|
Chris@87
|
1449 for k, i in list(charselect.items()):
|
Chris@87
|
1450 charselect[k] = rmbadname1(i)
|
Chris@87
|
1451 elif typespec=='type':
|
Chris@87
|
1452 typename=re.match(r'\s*\(\s*(?P<name>\w+)\s*\)', selector, re.I)
|
Chris@87
|
1453 if typename: typename=typename.group('name')
|
Chris@87
|
1454 else: outmess('cracktypespec: no typename found in %s\n'%(repr(typespec+selector)))
|
Chris@87
|
1455 else:
|
Chris@87
|
1456 outmess('cracktypespec: no selector used for %s\n'%(repr(selector)))
|
Chris@87
|
1457 return kindselect, charselect, typename
|
Chris@87
|
1458 ######
|
Chris@87
|
1459 def setattrspec(decl,attr,force=0):
|
Chris@87
|
1460 if not decl:
|
Chris@87
|
1461 decl={}
|
Chris@87
|
1462 if not attr:
|
Chris@87
|
1463 return decl
|
Chris@87
|
1464 if 'attrspec' not in decl:
|
Chris@87
|
1465 decl['attrspec']=[attr]
|
Chris@87
|
1466 return decl
|
Chris@87
|
1467 if force: decl['attrspec'].append(attr)
|
Chris@87
|
1468 if attr in decl['attrspec']: return decl
|
Chris@87
|
1469 if attr=='static' and 'automatic' not in decl['attrspec']:
|
Chris@87
|
1470 decl['attrspec'].append(attr)
|
Chris@87
|
1471 elif attr=='automatic' and 'static' not in decl['attrspec']:
|
Chris@87
|
1472 decl['attrspec'].append(attr)
|
Chris@87
|
1473 elif attr=='public' and 'private' not in decl['attrspec']:
|
Chris@87
|
1474 decl['attrspec'].append(attr)
|
Chris@87
|
1475 elif attr=='private' and 'public' not in decl['attrspec']:
|
Chris@87
|
1476 decl['attrspec'].append(attr)
|
Chris@87
|
1477 else:
|
Chris@87
|
1478 decl['attrspec'].append(attr)
|
Chris@87
|
1479 return decl
|
Chris@87
|
1480
|
Chris@87
|
1481 def setkindselector(decl,sel,force=0):
|
Chris@87
|
1482 if not decl:
|
Chris@87
|
1483 decl={}
|
Chris@87
|
1484 if not sel:
|
Chris@87
|
1485 return decl
|
Chris@87
|
1486 if 'kindselector' not in decl:
|
Chris@87
|
1487 decl['kindselector']=sel
|
Chris@87
|
1488 return decl
|
Chris@87
|
1489 for k in list(sel.keys()):
|
Chris@87
|
1490 if force or k not in decl['kindselector']:
|
Chris@87
|
1491 decl['kindselector'][k]=sel[k]
|
Chris@87
|
1492 return decl
|
Chris@87
|
1493
|
Chris@87
|
1494 def setcharselector(decl,sel,force=0):
|
Chris@87
|
1495 if not decl:
|
Chris@87
|
1496 decl={}
|
Chris@87
|
1497 if not sel:
|
Chris@87
|
1498 return decl
|
Chris@87
|
1499 if 'charselector' not in decl:
|
Chris@87
|
1500 decl['charselector']=sel
|
Chris@87
|
1501 return decl
|
Chris@87
|
1502 for k in list(sel.keys()):
|
Chris@87
|
1503 if force or k not in decl['charselector']:
|
Chris@87
|
1504 decl['charselector'][k]=sel[k]
|
Chris@87
|
1505 return decl
|
Chris@87
|
1506
|
Chris@87
|
1507 def getblockname(block,unknown='unknown'):
|
Chris@87
|
1508 if 'name' in block:
|
Chris@87
|
1509 return block['name']
|
Chris@87
|
1510 return unknown
|
Chris@87
|
1511
|
Chris@87
|
1512 ###### post processing
|
Chris@87
|
1513
|
Chris@87
|
1514 def setmesstext(block):
|
Chris@87
|
1515 global filepositiontext
|
Chris@87
|
1516 try:
|
Chris@87
|
1517 filepositiontext='In: %s:%s\n'%(block['from'], block['name'])
|
Chris@87
|
1518 except:
|
Chris@87
|
1519 pass
|
Chris@87
|
1520
|
Chris@87
|
1521 def get_usedict(block):
|
Chris@87
|
1522 usedict = {}
|
Chris@87
|
1523 if 'parent_block' in block:
|
Chris@87
|
1524 usedict = get_usedict(block['parent_block'])
|
Chris@87
|
1525 if 'use' in block:
|
Chris@87
|
1526 usedict.update(block['use'])
|
Chris@87
|
1527 return usedict
|
Chris@87
|
1528
|
Chris@87
|
1529 def get_useparameters(block, param_map=None):
|
Chris@87
|
1530 global f90modulevars
|
Chris@87
|
1531 if param_map is None:
|
Chris@87
|
1532 param_map = {}
|
Chris@87
|
1533 usedict = get_usedict(block)
|
Chris@87
|
1534 if not usedict:
|
Chris@87
|
1535 return param_map
|
Chris@87
|
1536 for usename, mapping in list(usedict.items()):
|
Chris@87
|
1537 usename = usename.lower()
|
Chris@87
|
1538 if usename not in f90modulevars:
|
Chris@87
|
1539 outmess('get_useparameters: no module %s info used by %s\n' % (usename, block.get('name')))
|
Chris@87
|
1540 continue
|
Chris@87
|
1541 mvars = f90modulevars[usename]
|
Chris@87
|
1542 params = get_parameters(mvars)
|
Chris@87
|
1543 if not params:
|
Chris@87
|
1544 continue
|
Chris@87
|
1545 # XXX: apply mapping
|
Chris@87
|
1546 if mapping:
|
Chris@87
|
1547 errmess('get_useparameters: mapping for %s not impl.' % (mapping))
|
Chris@87
|
1548 for k, v in list(params.items()):
|
Chris@87
|
1549 if k in param_map:
|
Chris@87
|
1550 outmess('get_useparameters: overriding parameter %s with'\
|
Chris@87
|
1551 ' value from module %s' % (repr(k), repr(usename)))
|
Chris@87
|
1552 param_map[k] = v
|
Chris@87
|
1553
|
Chris@87
|
1554 return param_map
|
Chris@87
|
1555
|
Chris@87
|
1556 def postcrack2(block,tab='',param_map=None):
|
Chris@87
|
1557 global f90modulevars
|
Chris@87
|
1558 if not f90modulevars:
|
Chris@87
|
1559 return block
|
Chris@87
|
1560 if isinstance(block, list):
|
Chris@87
|
1561 ret = []
|
Chris@87
|
1562 for g in block:
|
Chris@87
|
1563 g = postcrack2(g, tab=tab+'\t', param_map=param_map)
|
Chris@87
|
1564 ret.append(g)
|
Chris@87
|
1565 return ret
|
Chris@87
|
1566 setmesstext(block)
|
Chris@87
|
1567 outmess('%sBlock: %s\n'%(tab, block['name']), 0)
|
Chris@87
|
1568
|
Chris@87
|
1569 if param_map is None:
|
Chris@87
|
1570 param_map = get_useparameters(block)
|
Chris@87
|
1571
|
Chris@87
|
1572 if param_map is not None and 'vars' in block:
|
Chris@87
|
1573 vars = block['vars']
|
Chris@87
|
1574 for n in list(vars.keys()):
|
Chris@87
|
1575 var = vars[n]
|
Chris@87
|
1576 if 'kindselector' in var:
|
Chris@87
|
1577 kind = var['kindselector']
|
Chris@87
|
1578 if 'kind' in kind:
|
Chris@87
|
1579 val = kind['kind']
|
Chris@87
|
1580 if val in param_map:
|
Chris@87
|
1581 kind['kind'] = param_map[val]
|
Chris@87
|
1582 new_body = []
|
Chris@87
|
1583 for b in block['body']:
|
Chris@87
|
1584 b = postcrack2(b, tab=tab+'\t', param_map=param_map)
|
Chris@87
|
1585 new_body.append(b)
|
Chris@87
|
1586 block['body'] = new_body
|
Chris@87
|
1587
|
Chris@87
|
1588 return block
|
Chris@87
|
1589
|
Chris@87
|
1590 def postcrack(block,args=None,tab=''):
|
Chris@87
|
1591 """
|
Chris@87
|
1592 TODO:
|
Chris@87
|
1593 function return values
|
Chris@87
|
1594 determine expression types if in argument list
|
Chris@87
|
1595 """
|
Chris@87
|
1596 global usermodules, onlyfunctions
|
Chris@87
|
1597 if isinstance(block, list):
|
Chris@87
|
1598 gret=[]
|
Chris@87
|
1599 uret=[]
|
Chris@87
|
1600 for g in block:
|
Chris@87
|
1601 setmesstext(g)
|
Chris@87
|
1602 g=postcrack(g, tab=tab+'\t')
|
Chris@87
|
1603 if 'name' in g and '__user__' in g['name']: # sort user routines to appear first
|
Chris@87
|
1604 uret.append(g)
|
Chris@87
|
1605 else:
|
Chris@87
|
1606 gret.append(g)
|
Chris@87
|
1607 return uret+gret
|
Chris@87
|
1608 setmesstext(block)
|
Chris@87
|
1609 if not isinstance(block, dict) and 'block' not in block:
|
Chris@87
|
1610 raise Exception('postcrack: Expected block dictionary instead of ' + \
|
Chris@87
|
1611 str(block))
|
Chris@87
|
1612 if 'name' in block and not block['name']=='unknown_interface':
|
Chris@87
|
1613 outmess('%sBlock: %s\n'%(tab, block['name']), 0)
|
Chris@87
|
1614 blocktype=block['block']
|
Chris@87
|
1615 block=analyzeargs(block)
|
Chris@87
|
1616 block=analyzecommon(block)
|
Chris@87
|
1617 block['vars']=analyzevars(block)
|
Chris@87
|
1618 block['sortvars']=sortvarnames(block['vars'])
|
Chris@87
|
1619 if 'args' in block and block['args']:
|
Chris@87
|
1620 args=block['args']
|
Chris@87
|
1621 block['body']=analyzebody(block, args, tab=tab)
|
Chris@87
|
1622
|
Chris@87
|
1623 userisdefined=[]
|
Chris@87
|
1624 ## fromuser = []
|
Chris@87
|
1625 if 'use' in block:
|
Chris@87
|
1626 useblock=block['use']
|
Chris@87
|
1627 for k in list(useblock.keys()):
|
Chris@87
|
1628 if '__user__' in k:
|
Chris@87
|
1629 userisdefined.append(k)
|
Chris@87
|
1630 ## if 'map' in useblock[k]:
|
Chris@87
|
1631 ## for n in useblock[k]['map'].itervalues():
|
Chris@87
|
1632 ## if n not in fromuser: fromuser.append(n)
|
Chris@87
|
1633 else: useblock={}
|
Chris@87
|
1634 name=''
|
Chris@87
|
1635 if 'name' in block:
|
Chris@87
|
1636 name=block['name']
|
Chris@87
|
1637 if 'externals' in block and block['externals']:# and not userisdefined: # Build a __user__ module
|
Chris@87
|
1638 interfaced=[]
|
Chris@87
|
1639 if 'interfaced' in block:
|
Chris@87
|
1640 interfaced=block['interfaced']
|
Chris@87
|
1641 mvars=copy.copy(block['vars'])
|
Chris@87
|
1642 if name:
|
Chris@87
|
1643 mname=name+'__user__routines'
|
Chris@87
|
1644 else:
|
Chris@87
|
1645 mname='unknown__user__routines'
|
Chris@87
|
1646 if mname in userisdefined:
|
Chris@87
|
1647 i=1
|
Chris@87
|
1648 while '%s_%i'%(mname, i) in userisdefined: i=i+1
|
Chris@87
|
1649 mname='%s_%i'%(mname, i)
|
Chris@87
|
1650 interface={'block':'interface','body':[],'vars':{},'name':name+'_user_interface'}
|
Chris@87
|
1651 for e in block['externals']:
|
Chris@87
|
1652 ## if e in fromuser:
|
Chris@87
|
1653 ## outmess(' Skipping %s that is defined explicitly in another use statement\n'%(`e`))
|
Chris@87
|
1654 ## continue
|
Chris@87
|
1655 if e in interfaced:
|
Chris@87
|
1656 edef=[]
|
Chris@87
|
1657 j=-1
|
Chris@87
|
1658 for b in block['body']:
|
Chris@87
|
1659 j=j+1
|
Chris@87
|
1660 if b['block']=='interface':
|
Chris@87
|
1661 i=-1
|
Chris@87
|
1662 for bb in b['body']:
|
Chris@87
|
1663 i=i+1
|
Chris@87
|
1664 if 'name' in bb and bb['name']==e:
|
Chris@87
|
1665 edef=copy.copy(bb)
|
Chris@87
|
1666 del b['body'][i]
|
Chris@87
|
1667 break
|
Chris@87
|
1668 if edef:
|
Chris@87
|
1669 if not b['body']: del block['body'][j]
|
Chris@87
|
1670 del interfaced[interfaced.index(e)]
|
Chris@87
|
1671 break
|
Chris@87
|
1672 interface['body'].append(edef)
|
Chris@87
|
1673 else:
|
Chris@87
|
1674 if e in mvars and not isexternal(mvars[e]):
|
Chris@87
|
1675 interface['vars'][e]=mvars[e]
|
Chris@87
|
1676 if interface['vars'] or interface['body']:
|
Chris@87
|
1677 block['interfaced']=interfaced
|
Chris@87
|
1678 mblock={'block':'python module','body':[interface],'vars':{},'name':mname,'interfaced':block['externals']}
|
Chris@87
|
1679 useblock[mname]={}
|
Chris@87
|
1680 usermodules.append(mblock)
|
Chris@87
|
1681 if useblock:
|
Chris@87
|
1682 block['use']=useblock
|
Chris@87
|
1683 return block
|
Chris@87
|
1684
|
Chris@87
|
1685 def sortvarnames(vars):
|
Chris@87
|
1686 indep = []
|
Chris@87
|
1687 dep = []
|
Chris@87
|
1688 for v in list(vars.keys()):
|
Chris@87
|
1689 if 'depend' in vars[v] and vars[v]['depend']:
|
Chris@87
|
1690 dep.append(v)
|
Chris@87
|
1691 #print '%s depends on %s'%(v,vars[v]['depend'])
|
Chris@87
|
1692 else: indep.append(v)
|
Chris@87
|
1693 n = len(dep)
|
Chris@87
|
1694 i = 0
|
Chris@87
|
1695 while dep: #XXX: How to catch dependence cycles correctly?
|
Chris@87
|
1696 v = dep[0]
|
Chris@87
|
1697 fl = 0
|
Chris@87
|
1698 for w in dep[1:]:
|
Chris@87
|
1699 if w in vars[v]['depend']:
|
Chris@87
|
1700 fl = 1
|
Chris@87
|
1701 break
|
Chris@87
|
1702 if fl:
|
Chris@87
|
1703 dep = dep[1:]+[v]
|
Chris@87
|
1704 i = i + 1
|
Chris@87
|
1705 if i>n:
|
Chris@87
|
1706 errmess('sortvarnames: failed to compute dependencies because'
|
Chris@87
|
1707 ' of cyclic dependencies between '
|
Chris@87
|
1708 +', '.join(dep)+'\n')
|
Chris@87
|
1709 indep = indep + dep
|
Chris@87
|
1710 break
|
Chris@87
|
1711 else:
|
Chris@87
|
1712 indep.append(v)
|
Chris@87
|
1713 dep = dep[1:]
|
Chris@87
|
1714 n = len(dep)
|
Chris@87
|
1715 i = 0
|
Chris@87
|
1716 #print indep
|
Chris@87
|
1717 return indep
|
Chris@87
|
1718
|
Chris@87
|
1719 def analyzecommon(block):
|
Chris@87
|
1720 if not hascommon(block): return block
|
Chris@87
|
1721 commonvars=[]
|
Chris@87
|
1722 for k in list(block['common'].keys()):
|
Chris@87
|
1723 comvars=[]
|
Chris@87
|
1724 for e in block['common'][k]:
|
Chris@87
|
1725 m=re.match(r'\A\s*\b(?P<name>.*?)\b\s*(\((?P<dims>.*?)\)|)\s*\Z', e, re.I)
|
Chris@87
|
1726 if m:
|
Chris@87
|
1727 dims=[]
|
Chris@87
|
1728 if m.group('dims'):
|
Chris@87
|
1729 dims=[x.strip() for x in markoutercomma(m.group('dims')).split('@,@')]
|
Chris@87
|
1730 n=m.group('name').strip()
|
Chris@87
|
1731 if n in block['vars']:
|
Chris@87
|
1732 if 'attrspec' in block['vars'][n]:
|
Chris@87
|
1733 block['vars'][n]['attrspec'].append('dimension(%s)'%(','.join(dims)))
|
Chris@87
|
1734 else:
|
Chris@87
|
1735 block['vars'][n]['attrspec']=['dimension(%s)'%(','.join(dims))]
|
Chris@87
|
1736 else:
|
Chris@87
|
1737 if dims:
|
Chris@87
|
1738 block['vars'][n]={'attrspec':['dimension(%s)'%(','.join(dims))]}
|
Chris@87
|
1739 else: block['vars'][n]={}
|
Chris@87
|
1740 if n not in commonvars: commonvars.append(n)
|
Chris@87
|
1741 else:
|
Chris@87
|
1742 n=e
|
Chris@87
|
1743 errmess('analyzecommon: failed to extract "<name>[(<dims>)]" from "%s" in common /%s/.\n'%(e, k))
|
Chris@87
|
1744 comvars.append(n)
|
Chris@87
|
1745 block['common'][k]=comvars
|
Chris@87
|
1746 if 'commonvars' not in block:
|
Chris@87
|
1747 block['commonvars']=commonvars
|
Chris@87
|
1748 else:
|
Chris@87
|
1749 block['commonvars']=block['commonvars']+commonvars
|
Chris@87
|
1750 return block
|
Chris@87
|
1751
|
Chris@87
|
1752 def analyzebody(block,args,tab=''):
|
Chris@87
|
1753 global usermodules, skipfuncs, onlyfuncs, f90modulevars
|
Chris@87
|
1754 setmesstext(block)
|
Chris@87
|
1755 body=[]
|
Chris@87
|
1756 for b in block['body']:
|
Chris@87
|
1757 b['parent_block'] = block
|
Chris@87
|
1758 if b['block'] in ['function', 'subroutine']:
|
Chris@87
|
1759 if args is not None and b['name'] not in args:
|
Chris@87
|
1760 continue
|
Chris@87
|
1761 else:
|
Chris@87
|
1762 as_=b['args']
|
Chris@87
|
1763 if b['name'] in skipfuncs:
|
Chris@87
|
1764 continue
|
Chris@87
|
1765 if onlyfuncs and b['name'] not in onlyfuncs:
|
Chris@87
|
1766 continue
|
Chris@87
|
1767 b['saved_interface'] = crack2fortrangen(b, '\n'+' '*6, as_interface=True)
|
Chris@87
|
1768
|
Chris@87
|
1769 else: as_=args
|
Chris@87
|
1770 b=postcrack(b, as_, tab=tab+'\t')
|
Chris@87
|
1771 if b['block']=='interface' and not b['body']:
|
Chris@87
|
1772 if 'f2pyenhancements' not in b:
|
Chris@87
|
1773 continue
|
Chris@87
|
1774 if b['block'].replace(' ', '')=='pythonmodule':
|
Chris@87
|
1775 usermodules.append(b)
|
Chris@87
|
1776 else:
|
Chris@87
|
1777 if b['block']=='module':
|
Chris@87
|
1778 f90modulevars[b['name']] = b['vars']
|
Chris@87
|
1779 body.append(b)
|
Chris@87
|
1780 return body
|
Chris@87
|
1781
|
Chris@87
|
1782 def buildimplicitrules(block):
|
Chris@87
|
1783 setmesstext(block)
|
Chris@87
|
1784 implicitrules=defaultimplicitrules
|
Chris@87
|
1785 attrrules={}
|
Chris@87
|
1786 if 'implicit' in block:
|
Chris@87
|
1787 if block['implicit'] is None:
|
Chris@87
|
1788 implicitrules=None
|
Chris@87
|
1789 if verbose>1:
|
Chris@87
|
1790 outmess('buildimplicitrules: no implicit rules for routine %s.\n'%repr(block['name']))
|
Chris@87
|
1791 else:
|
Chris@87
|
1792 for k in list(block['implicit'].keys()):
|
Chris@87
|
1793 if block['implicit'][k].get('typespec') not in ['static', 'automatic']:
|
Chris@87
|
1794 implicitrules[k]=block['implicit'][k]
|
Chris@87
|
1795 else:
|
Chris@87
|
1796 attrrules[k]=block['implicit'][k]['typespec']
|
Chris@87
|
1797 return implicitrules, attrrules
|
Chris@87
|
1798
|
Chris@87
|
1799 def myeval(e,g=None,l=None):
|
Chris@87
|
1800 r = eval(e, g, l)
|
Chris@87
|
1801 if type(r) in [type(0), type(0.0)]:
|
Chris@87
|
1802 return r
|
Chris@87
|
1803 raise ValueError('r=%r' % (r))
|
Chris@87
|
1804
|
Chris@87
|
1805 getlincoef_re_1 = re.compile(r'\A\b\w+\b\Z', re.I)
|
Chris@87
|
1806 def getlincoef(e, xset): # e = a*x+b ; x in xset
|
Chris@87
|
1807 try:
|
Chris@87
|
1808 c = int(myeval(e, {}, {}))
|
Chris@87
|
1809 return 0, c, None
|
Chris@87
|
1810 except: pass
|
Chris@87
|
1811 if getlincoef_re_1.match(e):
|
Chris@87
|
1812 return 1, 0, e
|
Chris@87
|
1813 len_e = len(e)
|
Chris@87
|
1814 for x in xset:
|
Chris@87
|
1815 if len(x)>len_e: continue
|
Chris@87
|
1816 if re.search(r'\w\s*\([^)]*\b'+x+r'\b', e):
|
Chris@87
|
1817 # skip function calls having x as an argument, e.g max(1, x)
|
Chris@87
|
1818 continue
|
Chris@87
|
1819 re_1 = re.compile(r'(?P<before>.*?)\b'+x+r'\b(?P<after>.*)', re.I)
|
Chris@87
|
1820 m = re_1.match(e)
|
Chris@87
|
1821 if m:
|
Chris@87
|
1822 try:
|
Chris@87
|
1823 m1 = re_1.match(e)
|
Chris@87
|
1824 while m1:
|
Chris@87
|
1825 ee = '%s(%s)%s'%(m1.group('before'), 0, m1.group('after'))
|
Chris@87
|
1826 m1 = re_1.match(ee)
|
Chris@87
|
1827 b = myeval(ee, {}, {})
|
Chris@87
|
1828 m1 = re_1.match(e)
|
Chris@87
|
1829 while m1:
|
Chris@87
|
1830 ee = '%s(%s)%s'%(m1.group('before'), 1, m1.group('after'))
|
Chris@87
|
1831 m1 = re_1.match(ee)
|
Chris@87
|
1832 a = myeval(ee, {}, {}) - b
|
Chris@87
|
1833 m1 = re_1.match(e)
|
Chris@87
|
1834 while m1:
|
Chris@87
|
1835 ee = '%s(%s)%s'%(m1.group('before'), 0.5, m1.group('after'))
|
Chris@87
|
1836 m1 = re_1.match(ee)
|
Chris@87
|
1837 c = myeval(ee, {}, {})
|
Chris@87
|
1838 # computing another point to be sure that expression is linear
|
Chris@87
|
1839 m1 = re_1.match(e)
|
Chris@87
|
1840 while m1:
|
Chris@87
|
1841 ee = '%s(%s)%s'%(m1.group('before'), 1.5, m1.group('after'))
|
Chris@87
|
1842 m1 = re_1.match(ee)
|
Chris@87
|
1843 c2 = myeval(ee, {}, {})
|
Chris@87
|
1844 if (a*0.5+b==c and a*1.5+b==c2):
|
Chris@87
|
1845 return a, b, x
|
Chris@87
|
1846 except: pass
|
Chris@87
|
1847 break
|
Chris@87
|
1848 return None, None, None
|
Chris@87
|
1849
|
Chris@87
|
1850 _varname_match = re.compile(r'\A[a-z]\w*\Z').match
|
Chris@87
|
1851 def getarrlen(dl,args,star='*'):
|
Chris@87
|
1852 edl = []
|
Chris@87
|
1853 try: edl.append(myeval(dl[0], {}, {}))
|
Chris@87
|
1854 except: edl.append(dl[0])
|
Chris@87
|
1855 try: edl.append(myeval(dl[1], {}, {}))
|
Chris@87
|
1856 except: edl.append(dl[1])
|
Chris@87
|
1857 if isinstance(edl[0], int):
|
Chris@87
|
1858 p1 = 1-edl[0]
|
Chris@87
|
1859 if p1==0: d = str(dl[1])
|
Chris@87
|
1860 elif p1<0: d = '%s-%s'%(dl[1], -p1)
|
Chris@87
|
1861 else: d = '%s+%s'%(dl[1], p1)
|
Chris@87
|
1862 elif isinstance(edl[1], int):
|
Chris@87
|
1863 p1 = 1+edl[1]
|
Chris@87
|
1864 if p1==0: d='-(%s)' % (dl[0])
|
Chris@87
|
1865 else: d='%s-(%s)' % (p1, dl[0])
|
Chris@87
|
1866 else: d = '%s-(%s)+1'%(dl[1], dl[0])
|
Chris@87
|
1867 try: return repr(myeval(d, {}, {})), None, None
|
Chris@87
|
1868 except: pass
|
Chris@87
|
1869 d1, d2=getlincoef(dl[0], args), getlincoef(dl[1], args)
|
Chris@87
|
1870 if None not in [d1[0], d2[0]]:
|
Chris@87
|
1871 if (d1[0], d2[0])==(0, 0):
|
Chris@87
|
1872 return repr(d2[1]-d1[1]+1), None, None
|
Chris@87
|
1873 b = d2[1] - d1[1] + 1
|
Chris@87
|
1874 d1 = (d1[0], 0, d1[2])
|
Chris@87
|
1875 d2 = (d2[0], b, d2[2])
|
Chris@87
|
1876 if d1[0]==0 and d2[2] in args:
|
Chris@87
|
1877 if b<0: return '%s * %s - %s'%(d2[0], d2[2], -b), d2[2], '+%s)/(%s)'%(-b, d2[0])
|
Chris@87
|
1878 elif b: return '%s * %s + %s'%(d2[0], d2[2], b), d2[2], '-%s)/(%s)'%(b, d2[0])
|
Chris@87
|
1879 else: return '%s * %s'%(d2[0], d2[2]), d2[2], ')/(%s)'%(d2[0])
|
Chris@87
|
1880 if d2[0]==0 and d1[2] in args:
|
Chris@87
|
1881
|
Chris@87
|
1882 if b<0: return '%s * %s - %s'%(-d1[0], d1[2], -b), d1[2], '+%s)/(%s)'%(-b, -d1[0])
|
Chris@87
|
1883 elif b: return '%s * %s + %s'%(-d1[0], d1[2], b), d1[2], '-%s)/(%s)'%(b, -d1[0])
|
Chris@87
|
1884 else: return '%s * %s'%(-d1[0], d1[2]), d1[2], ')/(%s)'%(-d1[0])
|
Chris@87
|
1885 if d1[2]==d2[2] and d1[2] in args:
|
Chris@87
|
1886 a = d2[0] - d1[0]
|
Chris@87
|
1887 if not a: return repr(b), None, None
|
Chris@87
|
1888 if b<0: return '%s * %s - %s'%(a, d1[2], -b), d2[2], '+%s)/(%s)'%(-b, a)
|
Chris@87
|
1889 elif b: return '%s * %s + %s'%(a, d1[2], b), d2[2], '-%s)/(%s)'%(b, a)
|
Chris@87
|
1890 else: return '%s * %s'%(a, d1[2]), d2[2], ')/(%s)'%(a)
|
Chris@87
|
1891 if d1[0]==d2[0]==1:
|
Chris@87
|
1892 c = str(d1[2])
|
Chris@87
|
1893 if c not in args:
|
Chris@87
|
1894 if _varname_match(c):
|
Chris@87
|
1895 outmess('\tgetarrlen:variable "%s" undefined\n' % (c))
|
Chris@87
|
1896 c = '(%s)'%c
|
Chris@87
|
1897 if b==0: d='%s-%s' % (d2[2], c)
|
Chris@87
|
1898 elif b<0: d='%s-%s-%s' % (d2[2], c, -b)
|
Chris@87
|
1899 else: d='%s-%s+%s' % (d2[2], c, b)
|
Chris@87
|
1900 elif d1[0]==0:
|
Chris@87
|
1901 c2 = str(d2[2])
|
Chris@87
|
1902 if c2 not in args:
|
Chris@87
|
1903 if _varname_match(c2):
|
Chris@87
|
1904 outmess('\tgetarrlen:variable "%s" undefined\n' % (c2))
|
Chris@87
|
1905 c2 = '(%s)'%c2
|
Chris@87
|
1906 if d2[0]==1: pass
|
Chris@87
|
1907 elif d2[0]==-1: c2='-%s' %c2
|
Chris@87
|
1908 else: c2='%s*%s'%(d2[0], c2)
|
Chris@87
|
1909
|
Chris@87
|
1910 if b==0: d=c2
|
Chris@87
|
1911 elif b<0: d='%s-%s' % (c2, -b)
|
Chris@87
|
1912 else: d='%s+%s' % (c2, b)
|
Chris@87
|
1913 elif d2[0]==0:
|
Chris@87
|
1914 c1 = str(d1[2])
|
Chris@87
|
1915 if c1 not in args:
|
Chris@87
|
1916 if _varname_match(c1):
|
Chris@87
|
1917 outmess('\tgetarrlen:variable "%s" undefined\n' % (c1))
|
Chris@87
|
1918 c1 = '(%s)'%c1
|
Chris@87
|
1919 if d1[0]==1: c1='-%s'%c1
|
Chris@87
|
1920 elif d1[0]==-1: c1='+%s'%c1
|
Chris@87
|
1921 elif d1[0]<0: c1='+%s*%s'%(-d1[0], c1)
|
Chris@87
|
1922 else: c1 = '-%s*%s' % (d1[0], c1)
|
Chris@87
|
1923
|
Chris@87
|
1924 if b==0: d=c1
|
Chris@87
|
1925 elif b<0: d='%s-%s' % (c1, -b)
|
Chris@87
|
1926 else: d='%s+%s' % (c1, b)
|
Chris@87
|
1927 else:
|
Chris@87
|
1928 c1 = str(d1[2])
|
Chris@87
|
1929 if c1 not in args:
|
Chris@87
|
1930 if _varname_match(c1):
|
Chris@87
|
1931 outmess('\tgetarrlen:variable "%s" undefined\n' % (c1))
|
Chris@87
|
1932 c1 = '(%s)'%c1
|
Chris@87
|
1933 if d1[0]==1: c1='-%s'%c1
|
Chris@87
|
1934 elif d1[0]==-1: c1='+%s'%c1
|
Chris@87
|
1935 elif d1[0]<0: c1='+%s*%s'%(-d1[0], c1)
|
Chris@87
|
1936 else: c1 = '-%s*%s' % (d1[0], c1)
|
Chris@87
|
1937
|
Chris@87
|
1938 c2 = str(d2[2])
|
Chris@87
|
1939 if c2 not in args:
|
Chris@87
|
1940 if _varname_match(c2):
|
Chris@87
|
1941 outmess('\tgetarrlen:variable "%s" undefined\n' % (c2))
|
Chris@87
|
1942 c2 = '(%s)'%c2
|
Chris@87
|
1943 if d2[0]==1: pass
|
Chris@87
|
1944 elif d2[0]==-1: c2='-%s' %c2
|
Chris@87
|
1945 else: c2='%s*%s'%(d2[0], c2)
|
Chris@87
|
1946
|
Chris@87
|
1947 if b==0: d='%s%s' % (c2, c1)
|
Chris@87
|
1948 elif b<0: d='%s%s-%s' % (c2, c1, -b)
|
Chris@87
|
1949 else: d='%s%s+%s' % (c2, c1, b)
|
Chris@87
|
1950 return d, None, None
|
Chris@87
|
1951
|
Chris@87
|
1952 word_pattern = re.compile(r'\b[a-z][\w$]*\b', re.I)
|
Chris@87
|
1953
|
Chris@87
|
1954 def _get_depend_dict(name, vars, deps):
|
Chris@87
|
1955 if name in vars:
|
Chris@87
|
1956 words = vars[name].get('depend', [])
|
Chris@87
|
1957
|
Chris@87
|
1958 if '=' in vars[name] and not isstring(vars[name]):
|
Chris@87
|
1959 for word in word_pattern.findall(vars[name]['=']):
|
Chris@87
|
1960 if word not in words and word in vars:
|
Chris@87
|
1961 words.append(word)
|
Chris@87
|
1962 for word in words[:]:
|
Chris@87
|
1963 for w in deps.get(word, []) \
|
Chris@87
|
1964 or _get_depend_dict(word, vars, deps):
|
Chris@87
|
1965 if w not in words:
|
Chris@87
|
1966 words.append(w)
|
Chris@87
|
1967 else:
|
Chris@87
|
1968 outmess('_get_depend_dict: no dependence info for %s\n' % (repr(name)))
|
Chris@87
|
1969 words = []
|
Chris@87
|
1970 deps[name] = words
|
Chris@87
|
1971 return words
|
Chris@87
|
1972
|
Chris@87
|
1973 def _calc_depend_dict(vars):
|
Chris@87
|
1974 names = list(vars.keys())
|
Chris@87
|
1975 depend_dict = {}
|
Chris@87
|
1976 for n in names:
|
Chris@87
|
1977 _get_depend_dict(n, vars, depend_dict)
|
Chris@87
|
1978 return depend_dict
|
Chris@87
|
1979
|
Chris@87
|
1980 def get_sorted_names(vars):
|
Chris@87
|
1981 """
|
Chris@87
|
1982 """
|
Chris@87
|
1983 depend_dict = _calc_depend_dict(vars)
|
Chris@87
|
1984 names = []
|
Chris@87
|
1985 for name in list(depend_dict.keys()):
|
Chris@87
|
1986 if not depend_dict[name]:
|
Chris@87
|
1987 names.append(name)
|
Chris@87
|
1988 del depend_dict[name]
|
Chris@87
|
1989 while depend_dict:
|
Chris@87
|
1990 for name, lst in list(depend_dict.items()):
|
Chris@87
|
1991 new_lst = [n for n in lst if n in depend_dict]
|
Chris@87
|
1992 if not new_lst:
|
Chris@87
|
1993 names.append(name)
|
Chris@87
|
1994 del depend_dict[name]
|
Chris@87
|
1995 else:
|
Chris@87
|
1996 depend_dict[name] = new_lst
|
Chris@87
|
1997 return [name for name in names if name in vars]
|
Chris@87
|
1998
|
Chris@87
|
1999 def _kind_func(string):
|
Chris@87
|
2000 #XXX: return something sensible.
|
Chris@87
|
2001 if string[0] in "'\"":
|
Chris@87
|
2002 string = string[1:-1]
|
Chris@87
|
2003 if real16pattern.match(string):
|
Chris@87
|
2004 return 8
|
Chris@87
|
2005 elif real8pattern.match(string):
|
Chris@87
|
2006 return 4
|
Chris@87
|
2007 return 'kind('+string+')'
|
Chris@87
|
2008
|
Chris@87
|
2009 def _selected_int_kind_func(r):
|
Chris@87
|
2010 #XXX: This should be processor dependent
|
Chris@87
|
2011 m = 10**r
|
Chris@87
|
2012 if m<=2**8: return 1
|
Chris@87
|
2013 if m<=2**16: return 2
|
Chris@87
|
2014 if m<=2**32: return 4
|
Chris@87
|
2015 if m<=2**63: return 8
|
Chris@87
|
2016 if m<=2**128: return 16
|
Chris@87
|
2017 return -1
|
Chris@87
|
2018
|
Chris@87
|
2019 def _selected_real_kind_func(p, r=0, radix=0):
|
Chris@87
|
2020 #XXX: This should be processor dependent
|
Chris@87
|
2021 # This is only good for 0 <= p <= 20
|
Chris@87
|
2022 if p < 7: return 4
|
Chris@87
|
2023 if p < 16: return 8
|
Chris@87
|
2024 if platform.machine().lower().startswith('power'):
|
Chris@87
|
2025 if p <= 20:
|
Chris@87
|
2026 return 16
|
Chris@87
|
2027 else:
|
Chris@87
|
2028 if p < 19:
|
Chris@87
|
2029 return 10
|
Chris@87
|
2030 elif p <= 20:
|
Chris@87
|
2031 return 16
|
Chris@87
|
2032 return -1
|
Chris@87
|
2033
|
Chris@87
|
2034 def get_parameters(vars, global_params={}):
|
Chris@87
|
2035 params = copy.copy(global_params)
|
Chris@87
|
2036 g_params = copy.copy(global_params)
|
Chris@87
|
2037 for name, func in [('kind', _kind_func),
|
Chris@87
|
2038 ('selected_int_kind', _selected_int_kind_func),
|
Chris@87
|
2039 ('selected_real_kind', _selected_real_kind_func),
|
Chris@87
|
2040 ]:
|
Chris@87
|
2041 if name not in g_params:
|
Chris@87
|
2042 g_params[name] = func
|
Chris@87
|
2043 param_names = []
|
Chris@87
|
2044 for n in get_sorted_names(vars):
|
Chris@87
|
2045 if 'attrspec' in vars[n] and 'parameter' in vars[n]['attrspec']:
|
Chris@87
|
2046 param_names.append(n)
|
Chris@87
|
2047 kind_re = re.compile(r'\bkind\s*\(\s*(?P<value>.*)\s*\)', re.I)
|
Chris@87
|
2048 selected_int_kind_re = re.compile(r'\bselected_int_kind\s*\(\s*(?P<value>.*)\s*\)', re.I)
|
Chris@87
|
2049 selected_kind_re = re.compile(r'\bselected_(int|real)_kind\s*\(\s*(?P<value>.*)\s*\)', re.I)
|
Chris@87
|
2050 for n in param_names:
|
Chris@87
|
2051 if '=' in vars[n]:
|
Chris@87
|
2052 v = vars[n]['=']
|
Chris@87
|
2053 if islogical(vars[n]):
|
Chris@87
|
2054 v = v.lower()
|
Chris@87
|
2055 for repl in [
|
Chris@87
|
2056 ('.false.', 'False'),
|
Chris@87
|
2057 ('.true.', 'True'),
|
Chris@87
|
2058 #TODO: test .eq., .neq., etc replacements.
|
Chris@87
|
2059 ]:
|
Chris@87
|
2060 v = v.replace(*repl)
|
Chris@87
|
2061 v = kind_re.sub(r'kind("\1")', v)
|
Chris@87
|
2062 v = selected_int_kind_re.sub(r'selected_int_kind(\1)', v)
|
Chris@87
|
2063 if isinteger(vars[n]) and not selected_kind_re.match(v):
|
Chris@87
|
2064 v = v.split('_')[0]
|
Chris@87
|
2065 if isdouble(vars[n]):
|
Chris@87
|
2066 tt = list(v)
|
Chris@87
|
2067 for m in real16pattern.finditer(v):
|
Chris@87
|
2068 tt[m.start():m.end()] = list(\
|
Chris@87
|
2069 v[m.start():m.end()].lower().replace('d', 'e'))
|
Chris@87
|
2070 v = ''.join(tt)
|
Chris@87
|
2071 if iscomplex(vars[n]):
|
Chris@87
|
2072 if v[0]=='(' and v[-1]==')':
|
Chris@87
|
2073 l = markoutercomma(v[1:-1]).split('@,@')
|
Chris@87
|
2074 try:
|
Chris@87
|
2075 params[n] = eval(v, g_params, params)
|
Chris@87
|
2076 except Exception as msg:
|
Chris@87
|
2077 params[n] = v
|
Chris@87
|
2078 #print params
|
Chris@87
|
2079 outmess('get_parameters: got "%s" on %s\n' % (msg, repr(v)))
|
Chris@87
|
2080 if isstring(vars[n]) and isinstance(params[n], int):
|
Chris@87
|
2081 params[n] = chr(params[n])
|
Chris@87
|
2082 nl = n.lower()
|
Chris@87
|
2083 if nl!=n:
|
Chris@87
|
2084 params[nl] = params[n]
|
Chris@87
|
2085 else:
|
Chris@87
|
2086 print(vars[n])
|
Chris@87
|
2087 outmess('get_parameters:parameter %s does not have value?!\n'%(repr(n)))
|
Chris@87
|
2088 return params
|
Chris@87
|
2089
|
Chris@87
|
2090 def _eval_length(length, params):
|
Chris@87
|
2091 if length in ['(:)', '(*)', '*']:
|
Chris@87
|
2092 return '(*)'
|
Chris@87
|
2093 return _eval_scalar(length, params)
|
Chris@87
|
2094
|
Chris@87
|
2095 _is_kind_number = re.compile(r'\d+_').match
|
Chris@87
|
2096
|
Chris@87
|
2097 def _eval_scalar(value, params):
|
Chris@87
|
2098 if _is_kind_number(value):
|
Chris@87
|
2099 value = value.split('_')[0]
|
Chris@87
|
2100 try:
|
Chris@87
|
2101 value = str(eval(value, {}, params))
|
Chris@87
|
2102 except (NameError, SyntaxError):
|
Chris@87
|
2103 return value
|
Chris@87
|
2104 except Exception as msg:
|
Chris@87
|
2105 errmess('"%s" in evaluating %r '\
|
Chris@87
|
2106 '(available names: %s)\n' \
|
Chris@87
|
2107 % (msg, value, list(params.keys())))
|
Chris@87
|
2108 return value
|
Chris@87
|
2109
|
Chris@87
|
2110 def analyzevars(block):
|
Chris@87
|
2111 global f90modulevars
|
Chris@87
|
2112 setmesstext(block)
|
Chris@87
|
2113 implicitrules, attrrules=buildimplicitrules(block)
|
Chris@87
|
2114 vars=copy.copy(block['vars'])
|
Chris@87
|
2115 if block['block']=='function' and block['name'] not in vars:
|
Chris@87
|
2116 vars[block['name']]={}
|
Chris@87
|
2117 if '' in block['vars']:
|
Chris@87
|
2118 del vars['']
|
Chris@87
|
2119 if 'attrspec' in block['vars']['']:
|
Chris@87
|
2120 gen=block['vars']['']['attrspec']
|
Chris@87
|
2121 for n in list(vars.keys()):
|
Chris@87
|
2122 for k in ['public', 'private']:
|
Chris@87
|
2123 if k in gen:
|
Chris@87
|
2124 vars[n]=setattrspec(vars[n], k)
|
Chris@87
|
2125 svars=[]
|
Chris@87
|
2126 args = block['args']
|
Chris@87
|
2127 for a in args:
|
Chris@87
|
2128 try:
|
Chris@87
|
2129 vars[a]
|
Chris@87
|
2130 svars.append(a)
|
Chris@87
|
2131 except KeyError:
|
Chris@87
|
2132 pass
|
Chris@87
|
2133 for n in list(vars.keys()):
|
Chris@87
|
2134 if n not in args: svars.append(n)
|
Chris@87
|
2135
|
Chris@87
|
2136 params = get_parameters(vars, get_useparameters(block))
|
Chris@87
|
2137
|
Chris@87
|
2138 dep_matches = {}
|
Chris@87
|
2139 name_match = re.compile(r'\w[\w\d_$]*').match
|
Chris@87
|
2140 for v in list(vars.keys()):
|
Chris@87
|
2141 m = name_match(v)
|
Chris@87
|
2142 if m:
|
Chris@87
|
2143 n = v[m.start():m.end()]
|
Chris@87
|
2144 try:
|
Chris@87
|
2145 dep_matches[n]
|
Chris@87
|
2146 except KeyError:
|
Chris@87
|
2147 dep_matches[n] = re.compile(r'.*\b%s\b'%(v), re.I).match
|
Chris@87
|
2148 for n in svars:
|
Chris@87
|
2149 if n[0] in list(attrrules.keys()):
|
Chris@87
|
2150 vars[n]=setattrspec(vars[n], attrrules[n[0]])
|
Chris@87
|
2151 if 'typespec' not in vars[n]:
|
Chris@87
|
2152 if not('attrspec' in vars[n] and 'external' in vars[n]['attrspec']):
|
Chris@87
|
2153 if implicitrules:
|
Chris@87
|
2154 ln0 = n[0].lower()
|
Chris@87
|
2155 for k in list(implicitrules[ln0].keys()):
|
Chris@87
|
2156 if k=='typespec' and implicitrules[ln0][k]=='undefined':
|
Chris@87
|
2157 continue
|
Chris@87
|
2158 if k not in vars[n]:
|
Chris@87
|
2159 vars[n][k]=implicitrules[ln0][k]
|
Chris@87
|
2160 elif k=='attrspec':
|
Chris@87
|
2161 for l in implicitrules[ln0][k]:
|
Chris@87
|
2162 vars[n]=setattrspec(vars[n], l)
|
Chris@87
|
2163 elif n in block['args']:
|
Chris@87
|
2164 outmess('analyzevars: typespec of variable %s is not defined in routine %s.\n'%(repr(n), block['name']))
|
Chris@87
|
2165
|
Chris@87
|
2166 if 'charselector' in vars[n]:
|
Chris@87
|
2167 if 'len' in vars[n]['charselector']:
|
Chris@87
|
2168 l = vars[n]['charselector']['len']
|
Chris@87
|
2169 try:
|
Chris@87
|
2170 l = str(eval(l, {}, params))
|
Chris@87
|
2171 except:
|
Chris@87
|
2172 pass
|
Chris@87
|
2173 vars[n]['charselector']['len'] = l
|
Chris@87
|
2174
|
Chris@87
|
2175 if 'kindselector' in vars[n]:
|
Chris@87
|
2176 if 'kind' in vars[n]['kindselector']:
|
Chris@87
|
2177 l = vars[n]['kindselector']['kind']
|
Chris@87
|
2178 try:
|
Chris@87
|
2179 l = str(eval(l, {}, params))
|
Chris@87
|
2180 except:
|
Chris@87
|
2181 pass
|
Chris@87
|
2182 vars[n]['kindselector']['kind'] = l
|
Chris@87
|
2183
|
Chris@87
|
2184 savelindims = {}
|
Chris@87
|
2185 if 'attrspec' in vars[n]:
|
Chris@87
|
2186 attr=vars[n]['attrspec']
|
Chris@87
|
2187 attr.reverse()
|
Chris@87
|
2188 vars[n]['attrspec']=[]
|
Chris@87
|
2189 dim, intent, depend, check, note=None, None, None, None, None
|
Chris@87
|
2190 for a in attr:
|
Chris@87
|
2191 if a[:9]=='dimension': dim=(a[9:].strip())[1:-1]
|
Chris@87
|
2192 elif a[:6]=='intent': intent=(a[6:].strip())[1:-1]
|
Chris@87
|
2193 elif a[:6]=='depend': depend=(a[6:].strip())[1:-1]
|
Chris@87
|
2194 elif a[:5]=='check': check=(a[5:].strip())[1:-1]
|
Chris@87
|
2195 elif a[:4]=='note': note=(a[4:].strip())[1:-1]
|
Chris@87
|
2196 else: vars[n]=setattrspec(vars[n], a)
|
Chris@87
|
2197 if intent:
|
Chris@87
|
2198 if 'intent' not in vars[n]:
|
Chris@87
|
2199 vars[n]['intent']=[]
|
Chris@87
|
2200 for c in [x.strip() for x in markoutercomma(intent).split('@,@')]:
|
Chris@87
|
2201 # Remove spaces so that 'in out' becomes 'inout'
|
Chris@87
|
2202 tmp = c.replace(' ', '')
|
Chris@87
|
2203 if tmp not in vars[n]['intent']:
|
Chris@87
|
2204 vars[n]['intent'].append(tmp)
|
Chris@87
|
2205 intent=None
|
Chris@87
|
2206 if note:
|
Chris@87
|
2207 note=note.replace('\\n\\n', '\n\n')
|
Chris@87
|
2208 note=note.replace('\\n ', '\n')
|
Chris@87
|
2209 if 'note' not in vars[n]:
|
Chris@87
|
2210 vars[n]['note']=[note]
|
Chris@87
|
2211 else:
|
Chris@87
|
2212 vars[n]['note'].append(note)
|
Chris@87
|
2213 note=None
|
Chris@87
|
2214 if depend is not None:
|
Chris@87
|
2215 if 'depend' not in vars[n]:
|
Chris@87
|
2216 vars[n]['depend']=[]
|
Chris@87
|
2217 for c in rmbadname([x.strip() for x in markoutercomma(depend).split('@,@')]):
|
Chris@87
|
2218 if c not in vars[n]['depend']:
|
Chris@87
|
2219 vars[n]['depend'].append(c)
|
Chris@87
|
2220 depend=None
|
Chris@87
|
2221 if check is not None:
|
Chris@87
|
2222 if 'check' not in vars[n]:
|
Chris@87
|
2223 vars[n]['check']=[]
|
Chris@87
|
2224 for c in [x.strip() for x in markoutercomma(check).split('@,@')]:
|
Chris@87
|
2225 if c not in vars[n]['check']:
|
Chris@87
|
2226 vars[n]['check'].append(c)
|
Chris@87
|
2227 check=None
|
Chris@87
|
2228 if dim and 'dimension' not in vars[n]:
|
Chris@87
|
2229 vars[n]['dimension']=[]
|
Chris@87
|
2230 for d in rmbadname([x.strip() for x in markoutercomma(dim).split('@,@')]):
|
Chris@87
|
2231 star = '*'
|
Chris@87
|
2232 if d==':':
|
Chris@87
|
2233 star=':'
|
Chris@87
|
2234 if d in params:
|
Chris@87
|
2235 d = str(params[d])
|
Chris@87
|
2236 for p in list(params.keys()):
|
Chris@87
|
2237 m = re.match(r'(?P<before>.*?)\b'+p+r'\b(?P<after>.*)', d, re.I)
|
Chris@87
|
2238 if m:
|
Chris@87
|
2239 #outmess('analyzevars:replacing parameter %s in %s (dimension of %s) with %s\n'%(`p`,`d`,`n`,`params[p]`))
|
Chris@87
|
2240 d = m.group('before')+str(params[p])+m.group('after')
|
Chris@87
|
2241 if d==star:
|
Chris@87
|
2242 dl = [star]
|
Chris@87
|
2243 else:
|
Chris@87
|
2244 dl=markoutercomma(d, ':').split('@:@')
|
Chris@87
|
2245 if len(dl)==2 and '*' in dl: # e.g. dimension(5:*)
|
Chris@87
|
2246 dl = ['*']
|
Chris@87
|
2247 d = '*'
|
Chris@87
|
2248 if len(dl)==1 and not dl[0]==star: dl = ['1', dl[0]]
|
Chris@87
|
2249 if len(dl)==2:
|
Chris@87
|
2250 d, v, di = getarrlen(dl, list(block['vars'].keys()))
|
Chris@87
|
2251 if d[:4] == '1 * ': d = d[4:]
|
Chris@87
|
2252 if di and di[-4:] == '/(1)': di = di[:-4]
|
Chris@87
|
2253 if v: savelindims[d] = v, di
|
Chris@87
|
2254 vars[n]['dimension'].append(d)
|
Chris@87
|
2255 if 'dimension' in vars[n]:
|
Chris@87
|
2256 if isintent_c(vars[n]):
|
Chris@87
|
2257 shape_macro = 'shape'
|
Chris@87
|
2258 else:
|
Chris@87
|
2259 shape_macro = 'shape'#'fshape'
|
Chris@87
|
2260 if isstringarray(vars[n]):
|
Chris@87
|
2261 if 'charselector' in vars[n]:
|
Chris@87
|
2262 d = vars[n]['charselector']
|
Chris@87
|
2263 if '*' in d:
|
Chris@87
|
2264 d = d['*']
|
Chris@87
|
2265 errmess('analyzevars: character array "character*%s %s(%s)" is considered as "character %s(%s)"; "intent(c)" is forced.\n'\
|
Chris@87
|
2266 %(d, n,
|
Chris@87
|
2267 ','.join(vars[n]['dimension']),
|
Chris@87
|
2268 n, ','.join(vars[n]['dimension']+[d])))
|
Chris@87
|
2269 vars[n]['dimension'].append(d)
|
Chris@87
|
2270 del vars[n]['charselector']
|
Chris@87
|
2271 if 'intent' not in vars[n]:
|
Chris@87
|
2272 vars[n]['intent'] = []
|
Chris@87
|
2273 if 'c' not in vars[n]['intent']:
|
Chris@87
|
2274 vars[n]['intent'].append('c')
|
Chris@87
|
2275 else:
|
Chris@87
|
2276 errmess("analyzevars: charselector=%r unhandled." % (d))
|
Chris@87
|
2277 if 'check' not in vars[n] and 'args' in block and n in block['args']:
|
Chris@87
|
2278 flag = 'depend' not in vars[n]
|
Chris@87
|
2279 if flag:
|
Chris@87
|
2280 vars[n]['depend']=[]
|
Chris@87
|
2281 vars[n]['check']=[]
|
Chris@87
|
2282 if 'dimension' in vars[n]:
|
Chris@87
|
2283 #/----< no check
|
Chris@87
|
2284 #vars[n]['check'].append('rank(%s)==%s'%(n,len(vars[n]['dimension'])))
|
Chris@87
|
2285 i=-1; ni=len(vars[n]['dimension'])
|
Chris@87
|
2286 for d in vars[n]['dimension']:
|
Chris@87
|
2287 ddeps=[] # dependecies of 'd'
|
Chris@87
|
2288 ad=''
|
Chris@87
|
2289 pd=''
|
Chris@87
|
2290 #origd = d
|
Chris@87
|
2291 if d not in vars:
|
Chris@87
|
2292 if d in savelindims:
|
Chris@87
|
2293 pd, ad='(', savelindims[d][1]
|
Chris@87
|
2294 d = savelindims[d][0]
|
Chris@87
|
2295 else:
|
Chris@87
|
2296 for r in block['args']:
|
Chris@87
|
2297 #for r in block['vars'].iterkeys():
|
Chris@87
|
2298 if r not in vars:
|
Chris@87
|
2299 continue
|
Chris@87
|
2300 if re.match(r'.*?\b'+r+r'\b', d, re.I):
|
Chris@87
|
2301 ddeps.append(r)
|
Chris@87
|
2302 if d in vars:
|
Chris@87
|
2303 if 'attrspec' in vars[d]:
|
Chris@87
|
2304 for aa in vars[d]['attrspec']:
|
Chris@87
|
2305 if aa[:6]=='depend':
|
Chris@87
|
2306 ddeps += aa[6:].strip()[1:-1].split(',')
|
Chris@87
|
2307 if 'depend' in vars[d]:
|
Chris@87
|
2308 ddeps=ddeps+vars[d]['depend']
|
Chris@87
|
2309 i=i+1
|
Chris@87
|
2310 if d in vars and ('depend' not in vars[d]) \
|
Chris@87
|
2311 and ('=' not in vars[d]) and (d not in vars[n]['depend']) \
|
Chris@87
|
2312 and l_or(isintent_in, isintent_inout, isintent_inplace)(vars[n]):
|
Chris@87
|
2313 vars[d]['depend']=[n]
|
Chris@87
|
2314 if ni>1:
|
Chris@87
|
2315 vars[d]['=']='%s%s(%s,%s)%s'% (pd, shape_macro, n, i, ad)
|
Chris@87
|
2316 else:
|
Chris@87
|
2317 vars[d]['=']='%slen(%s)%s'% (pd, n, ad)
|
Chris@87
|
2318 # /---< no check
|
Chris@87
|
2319 if 1 and 'check' not in vars[d]:
|
Chris@87
|
2320 if ni>1:
|
Chris@87
|
2321 vars[d]['check']=['%s%s(%s,%i)%s==%s'\
|
Chris@87
|
2322 %(pd, shape_macro, n, i, ad, d)]
|
Chris@87
|
2323 else:
|
Chris@87
|
2324 vars[d]['check']=['%slen(%s)%s>=%s'%(pd, n, ad, d)]
|
Chris@87
|
2325 if 'attrspec' not in vars[d]:
|
Chris@87
|
2326 vars[d]['attrspec']=['optional']
|
Chris@87
|
2327 if ('optional' not in vars[d]['attrspec']) and\
|
Chris@87
|
2328 ('required' not in vars[d]['attrspec']):
|
Chris@87
|
2329 vars[d]['attrspec'].append('optional')
|
Chris@87
|
2330 elif d not in ['*', ':']:
|
Chris@87
|
2331 #/----< no check
|
Chris@87
|
2332 #if ni>1: vars[n]['check'].append('shape(%s,%i)==%s'%(n,i,d))
|
Chris@87
|
2333 #else: vars[n]['check'].append('len(%s)>=%s'%(n,d))
|
Chris@87
|
2334 if flag:
|
Chris@87
|
2335 if d in vars:
|
Chris@87
|
2336 if n not in ddeps:
|
Chris@87
|
2337 vars[n]['depend'].append(d)
|
Chris@87
|
2338 else:
|
Chris@87
|
2339 vars[n]['depend'] = vars[n]['depend'] + ddeps
|
Chris@87
|
2340 elif isstring(vars[n]):
|
Chris@87
|
2341 length='1'
|
Chris@87
|
2342 if 'charselector' in vars[n]:
|
Chris@87
|
2343 if '*' in vars[n]['charselector']:
|
Chris@87
|
2344 length = _eval_length(vars[n]['charselector']['*'],
|
Chris@87
|
2345 params)
|
Chris@87
|
2346 vars[n]['charselector']['*']=length
|
Chris@87
|
2347 elif 'len' in vars[n]['charselector']:
|
Chris@87
|
2348 length = _eval_length(vars[n]['charselector']['len'],
|
Chris@87
|
2349 params)
|
Chris@87
|
2350 del vars[n]['charselector']['len']
|
Chris@87
|
2351 vars[n]['charselector']['*']=length
|
Chris@87
|
2352
|
Chris@87
|
2353 if not vars[n]['check']:
|
Chris@87
|
2354 del vars[n]['check']
|
Chris@87
|
2355 if flag and not vars[n]['depend']:
|
Chris@87
|
2356 del vars[n]['depend']
|
Chris@87
|
2357 if '=' in vars[n]:
|
Chris@87
|
2358 if 'attrspec' not in vars[n]:
|
Chris@87
|
2359 vars[n]['attrspec']=[]
|
Chris@87
|
2360 if ('optional' not in vars[n]['attrspec']) and \
|
Chris@87
|
2361 ('required' not in vars[n]['attrspec']):
|
Chris@87
|
2362 vars[n]['attrspec'].append('optional')
|
Chris@87
|
2363 if 'depend' not in vars[n]:
|
Chris@87
|
2364 vars[n]['depend']=[]
|
Chris@87
|
2365 for v, m in list(dep_matches.items()):
|
Chris@87
|
2366 if m(vars[n]['=']): vars[n]['depend'].append(v)
|
Chris@87
|
2367 if not vars[n]['depend']: del vars[n]['depend']
|
Chris@87
|
2368 if isscalar(vars[n]):
|
Chris@87
|
2369 vars[n]['='] = _eval_scalar(vars[n]['='], params)
|
Chris@87
|
2370
|
Chris@87
|
2371 for n in list(vars.keys()):
|
Chris@87
|
2372 if n==block['name']: # n is block name
|
Chris@87
|
2373 if 'note' in vars[n]:
|
Chris@87
|
2374 block['note']=vars[n]['note']
|
Chris@87
|
2375 if block['block']=='function':
|
Chris@87
|
2376 if 'result' in block and block['result'] in vars:
|
Chris@87
|
2377 vars[n]=appenddecl(vars[n], vars[block['result']])
|
Chris@87
|
2378 if 'prefix' in block:
|
Chris@87
|
2379 pr=block['prefix']; ispure=0; isrec=1
|
Chris@87
|
2380 pr1=pr.replace('pure', '')
|
Chris@87
|
2381 ispure=(not pr==pr1)
|
Chris@87
|
2382 pr=pr1.replace('recursive', '')
|
Chris@87
|
2383 isrec=(not pr==pr1)
|
Chris@87
|
2384 m=typespattern[0].match(pr)
|
Chris@87
|
2385 if m:
|
Chris@87
|
2386 typespec, selector, attr, edecl=cracktypespec0(m.group('this'), m.group('after'))
|
Chris@87
|
2387 kindselect, charselect, typename=cracktypespec(typespec, selector)
|
Chris@87
|
2388 vars[n]['typespec']=typespec
|
Chris@87
|
2389 if kindselect:
|
Chris@87
|
2390 if 'kind' in kindselect:
|
Chris@87
|
2391 try:
|
Chris@87
|
2392 kindselect['kind'] = eval(kindselect['kind'], {}, params)
|
Chris@87
|
2393 except:
|
Chris@87
|
2394 pass
|
Chris@87
|
2395 vars[n]['kindselector']=kindselect
|
Chris@87
|
2396 if charselect: vars[n]['charselector']=charselect
|
Chris@87
|
2397 if typename: vars[n]['typename']=typename
|
Chris@87
|
2398 if ispure: vars[n]=setattrspec(vars[n], 'pure')
|
Chris@87
|
2399 if isrec: vars[n]=setattrspec(vars[n], 'recursive')
|
Chris@87
|
2400 else:
|
Chris@87
|
2401 outmess('analyzevars: prefix (%s) were not used\n'%repr(block['prefix']))
|
Chris@87
|
2402 if not block['block'] in ['module', 'pythonmodule', 'python module', 'block data']:
|
Chris@87
|
2403 if 'commonvars' in block:
|
Chris@87
|
2404 neededvars=copy.copy(block['args']+block['commonvars'])
|
Chris@87
|
2405 else:
|
Chris@87
|
2406 neededvars=copy.copy(block['args'])
|
Chris@87
|
2407 for n in list(vars.keys()):
|
Chris@87
|
2408 if l_or(isintent_callback, isintent_aux)(vars[n]):
|
Chris@87
|
2409 neededvars.append(n)
|
Chris@87
|
2410 if 'entry' in block:
|
Chris@87
|
2411 neededvars.extend(list(block['entry'].keys()))
|
Chris@87
|
2412 for k in list(block['entry'].keys()):
|
Chris@87
|
2413 for n in block['entry'][k]:
|
Chris@87
|
2414 if n not in neededvars:
|
Chris@87
|
2415 neededvars.append(n)
|
Chris@87
|
2416 if block['block']=='function':
|
Chris@87
|
2417 if 'result' in block:
|
Chris@87
|
2418 neededvars.append(block['result'])
|
Chris@87
|
2419 else:
|
Chris@87
|
2420 neededvars.append(block['name'])
|
Chris@87
|
2421 if block['block'] in ['subroutine', 'function']:
|
Chris@87
|
2422 name = block['name']
|
Chris@87
|
2423 if name in vars and 'intent' in vars[name]:
|
Chris@87
|
2424 block['intent'] = vars[name]['intent']
|
Chris@87
|
2425 if block['block'] == 'type':
|
Chris@87
|
2426 neededvars.extend(list(vars.keys()))
|
Chris@87
|
2427 for n in list(vars.keys()):
|
Chris@87
|
2428 if n not in neededvars:
|
Chris@87
|
2429 del vars[n]
|
Chris@87
|
2430 return vars
|
Chris@87
|
2431
|
Chris@87
|
2432 analyzeargs_re_1 = re.compile(r'\A[a-z]+[\w$]*\Z', re.I)
|
Chris@87
|
2433 def expr2name(a, block, args=[]):
|
Chris@87
|
2434 orig_a = a
|
Chris@87
|
2435 a_is_expr = not analyzeargs_re_1.match(a)
|
Chris@87
|
2436 if a_is_expr: # `a` is an expression
|
Chris@87
|
2437 implicitrules, attrrules=buildimplicitrules(block)
|
Chris@87
|
2438 at=determineexprtype(a, block['vars'], implicitrules)
|
Chris@87
|
2439 na='e_'
|
Chris@87
|
2440 for c in a:
|
Chris@87
|
2441 c = c.lower()
|
Chris@87
|
2442 if c not in string.ascii_lowercase+string.digits: c='_'
|
Chris@87
|
2443 na=na+c
|
Chris@87
|
2444 if na[-1]=='_': na=na+'e'
|
Chris@87
|
2445 else: na=na+'_e'
|
Chris@87
|
2446 a=na
|
Chris@87
|
2447 while a in block['vars'] or a in block['args']:
|
Chris@87
|
2448 a=a+'r'
|
Chris@87
|
2449 if a in args:
|
Chris@87
|
2450 k = 1
|
Chris@87
|
2451 while a + str(k) in args:
|
Chris@87
|
2452 k = k + 1
|
Chris@87
|
2453 a = a + str(k)
|
Chris@87
|
2454 if a_is_expr:
|
Chris@87
|
2455 block['vars'][a]=at
|
Chris@87
|
2456 else:
|
Chris@87
|
2457 if a not in block['vars']:
|
Chris@87
|
2458 if orig_a in block['vars']:
|
Chris@87
|
2459 block['vars'][a] = block['vars'][orig_a]
|
Chris@87
|
2460 else:
|
Chris@87
|
2461 block['vars'][a]={}
|
Chris@87
|
2462 if 'externals' in block and orig_a in block['externals']+block['interfaced']:
|
Chris@87
|
2463 block['vars'][a]=setattrspec(block['vars'][a], 'external')
|
Chris@87
|
2464 return a
|
Chris@87
|
2465
|
Chris@87
|
2466 def analyzeargs(block):
|
Chris@87
|
2467 setmesstext(block)
|
Chris@87
|
2468 implicitrules, attrrules=buildimplicitrules(block)
|
Chris@87
|
2469 if 'args' not in block:
|
Chris@87
|
2470 block['args']=[]
|
Chris@87
|
2471 args=[]
|
Chris@87
|
2472 for a in block['args']:
|
Chris@87
|
2473 a = expr2name(a, block, args)
|
Chris@87
|
2474 args.append(a)
|
Chris@87
|
2475 block['args']=args
|
Chris@87
|
2476 if 'entry' in block:
|
Chris@87
|
2477 for k, args1 in list(block['entry'].items()):
|
Chris@87
|
2478 for a in args1:
|
Chris@87
|
2479 if a not in block['vars']:
|
Chris@87
|
2480 block['vars'][a]={}
|
Chris@87
|
2481
|
Chris@87
|
2482 for b in block['body']:
|
Chris@87
|
2483 if b['name'] in args:
|
Chris@87
|
2484 if 'externals' not in block:
|
Chris@87
|
2485 block['externals']=[]
|
Chris@87
|
2486 if b['name'] not in block['externals']:
|
Chris@87
|
2487 block['externals'].append(b['name'])
|
Chris@87
|
2488 if 'result' in block and block['result'] not in block['vars']:
|
Chris@87
|
2489 block['vars'][block['result']]={}
|
Chris@87
|
2490 return block
|
Chris@87
|
2491
|
Chris@87
|
2492 determineexprtype_re_1 = re.compile(r'\A\(.+?[,].+?\)\Z', re.I)
|
Chris@87
|
2493 determineexprtype_re_2 = re.compile(r'\A[+-]?\d+(_(P<name>[\w]+)|)\Z', re.I)
|
Chris@87
|
2494 determineexprtype_re_3 = re.compile(r'\A[+-]?[\d.]+[\d+-de.]*(_(P<name>[\w]+)|)\Z', re.I)
|
Chris@87
|
2495 determineexprtype_re_4 = re.compile(r'\A\(.*\)\Z', re.I)
|
Chris@87
|
2496 determineexprtype_re_5 = re.compile(r'\A(?P<name>\w+)\s*\(.*?\)\s*\Z', re.I)
|
Chris@87
|
2497 def _ensure_exprdict(r):
|
Chris@87
|
2498 if isinstance(r, int):
|
Chris@87
|
2499 return {'typespec':'integer'}
|
Chris@87
|
2500 if isinstance(r, float):
|
Chris@87
|
2501 return {'typespec':'real'}
|
Chris@87
|
2502 if isinstance(r, complex):
|
Chris@87
|
2503 return {'typespec':'complex'}
|
Chris@87
|
2504 if isinstance(r, dict):
|
Chris@87
|
2505 return r
|
Chris@87
|
2506 raise AssertionError(repr(r))
|
Chris@87
|
2507
|
Chris@87
|
2508 def determineexprtype(expr,vars,rules={}):
|
Chris@87
|
2509 if expr in vars:
|
Chris@87
|
2510 return _ensure_exprdict(vars[expr])
|
Chris@87
|
2511 expr=expr.strip()
|
Chris@87
|
2512 if determineexprtype_re_1.match(expr):
|
Chris@87
|
2513 return {'typespec':'complex'}
|
Chris@87
|
2514 m=determineexprtype_re_2.match(expr)
|
Chris@87
|
2515 if m:
|
Chris@87
|
2516 if 'name' in m.groupdict() and m.group('name'):
|
Chris@87
|
2517 outmess('determineexprtype: selected kind types not supported (%s)\n'%repr(expr))
|
Chris@87
|
2518 return {'typespec':'integer'}
|
Chris@87
|
2519 m = determineexprtype_re_3.match(expr)
|
Chris@87
|
2520 if m:
|
Chris@87
|
2521 if 'name' in m.groupdict() and m.group('name'):
|
Chris@87
|
2522 outmess('determineexprtype: selected kind types not supported (%s)\n'%repr(expr))
|
Chris@87
|
2523 return {'typespec':'real'}
|
Chris@87
|
2524 for op in ['+', '-', '*', '/']:
|
Chris@87
|
2525 for e in [x.strip() for x in markoutercomma(expr, comma=op).split('@'+op+'@')]:
|
Chris@87
|
2526 if e in vars:
|
Chris@87
|
2527 return _ensure_exprdict(vars[e])
|
Chris@87
|
2528 t={}
|
Chris@87
|
2529 if determineexprtype_re_4.match(expr): # in parenthesis
|
Chris@87
|
2530 t=determineexprtype(expr[1:-1], vars, rules)
|
Chris@87
|
2531 else:
|
Chris@87
|
2532 m = determineexprtype_re_5.match(expr)
|
Chris@87
|
2533 if m:
|
Chris@87
|
2534 rn=m.group('name')
|
Chris@87
|
2535 t=determineexprtype(m.group('name'), vars, rules)
|
Chris@87
|
2536 if t and 'attrspec' in t:
|
Chris@87
|
2537 del t['attrspec']
|
Chris@87
|
2538 if not t:
|
Chris@87
|
2539 if rn[0] in rules:
|
Chris@87
|
2540 return _ensure_exprdict(rules[rn[0]])
|
Chris@87
|
2541 if expr[0] in '\'"':
|
Chris@87
|
2542 return {'typespec':'character','charselector':{'*':'*'}}
|
Chris@87
|
2543 if not t:
|
Chris@87
|
2544 outmess('determineexprtype: could not determine expressions (%s) type.\n'%(repr(expr)))
|
Chris@87
|
2545 return t
|
Chris@87
|
2546
|
Chris@87
|
2547 ######
|
Chris@87
|
2548 def crack2fortrangen(block,tab='\n', as_interface=False):
|
Chris@87
|
2549 global skipfuncs, onlyfuncs
|
Chris@87
|
2550 setmesstext(block)
|
Chris@87
|
2551 ret=''
|
Chris@87
|
2552 if isinstance(block, list):
|
Chris@87
|
2553 for g in block:
|
Chris@87
|
2554 if g and g['block'] in ['function', 'subroutine']:
|
Chris@87
|
2555 if g['name'] in skipfuncs:
|
Chris@87
|
2556 continue
|
Chris@87
|
2557 if onlyfuncs and g['name'] not in onlyfuncs:
|
Chris@87
|
2558 continue
|
Chris@87
|
2559 ret=ret+crack2fortrangen(g, tab, as_interface=as_interface)
|
Chris@87
|
2560 return ret
|
Chris@87
|
2561 prefix=''
|
Chris@87
|
2562 name=''
|
Chris@87
|
2563 args=''
|
Chris@87
|
2564 blocktype=block['block']
|
Chris@87
|
2565 if blocktype=='program': return ''
|
Chris@87
|
2566 argsl = []
|
Chris@87
|
2567 if 'name' in block:
|
Chris@87
|
2568 name=block['name']
|
Chris@87
|
2569 if 'args' in block:
|
Chris@87
|
2570 vars = block['vars']
|
Chris@87
|
2571 for a in block['args']:
|
Chris@87
|
2572 a = expr2name(a, block, argsl)
|
Chris@87
|
2573 if not isintent_callback(vars[a]):
|
Chris@87
|
2574 argsl.append(a)
|
Chris@87
|
2575 if block['block']=='function' or argsl:
|
Chris@87
|
2576 args='(%s)'%','.join(argsl)
|
Chris@87
|
2577 f2pyenhancements = ''
|
Chris@87
|
2578 if 'f2pyenhancements' in block:
|
Chris@87
|
2579 for k in list(block['f2pyenhancements'].keys()):
|
Chris@87
|
2580 f2pyenhancements = '%s%s%s %s'%(f2pyenhancements, tab+tabchar, k, block['f2pyenhancements'][k])
|
Chris@87
|
2581 intent_lst = block.get('intent', [])[:]
|
Chris@87
|
2582 if blocktype=='function' and 'callback' in intent_lst:
|
Chris@87
|
2583 intent_lst.remove('callback')
|
Chris@87
|
2584 if intent_lst:
|
Chris@87
|
2585 f2pyenhancements = '%s%sintent(%s) %s'%\
|
Chris@87
|
2586 (f2pyenhancements, tab+tabchar,
|
Chris@87
|
2587 ','.join(intent_lst), name)
|
Chris@87
|
2588 use=''
|
Chris@87
|
2589 if 'use' in block:
|
Chris@87
|
2590 use=use2fortran(block['use'], tab+tabchar)
|
Chris@87
|
2591 common=''
|
Chris@87
|
2592 if 'common' in block:
|
Chris@87
|
2593 common=common2fortran(block['common'], tab+tabchar)
|
Chris@87
|
2594 if name=='unknown_interface': name=''
|
Chris@87
|
2595 result=''
|
Chris@87
|
2596 if 'result' in block:
|
Chris@87
|
2597 result=' result (%s)'%block['result']
|
Chris@87
|
2598 if block['result'] not in argsl:
|
Chris@87
|
2599 argsl.append(block['result'])
|
Chris@87
|
2600 #if 'prefix' in block:
|
Chris@87
|
2601 # prefix=block['prefix']+' '
|
Chris@87
|
2602 body=crack2fortrangen(block['body'], tab+tabchar)
|
Chris@87
|
2603 vars=vars2fortran(block, block['vars'], argsl, tab+tabchar, as_interface=as_interface)
|
Chris@87
|
2604 mess=''
|
Chris@87
|
2605 if 'from' in block and not as_interface:
|
Chris@87
|
2606 mess='! in %s'%block['from']
|
Chris@87
|
2607 if 'entry' in block:
|
Chris@87
|
2608 entry_stmts = ''
|
Chris@87
|
2609 for k, i in list(block['entry'].items()):
|
Chris@87
|
2610 entry_stmts = '%s%sentry %s(%s)' \
|
Chris@87
|
2611 % (entry_stmts, tab+tabchar, k, ','.join(i))
|
Chris@87
|
2612 body = body + entry_stmts
|
Chris@87
|
2613 if blocktype=='block data' and name=='_BLOCK_DATA_':
|
Chris@87
|
2614 name = ''
|
Chris@87
|
2615 ret='%s%s%s %s%s%s %s%s%s%s%s%s%send %s %s'%(tab, prefix, blocktype, name, args, result, mess, f2pyenhancements, use, vars, common, body, tab, blocktype, name)
|
Chris@87
|
2616 return ret
|
Chris@87
|
2617
|
Chris@87
|
2618 def common2fortran(common,tab=''):
|
Chris@87
|
2619 ret=''
|
Chris@87
|
2620 for k in list(common.keys()):
|
Chris@87
|
2621 if k=='_BLNK_':
|
Chris@87
|
2622 ret='%s%scommon %s'%(ret, tab, ','.join(common[k]))
|
Chris@87
|
2623 else:
|
Chris@87
|
2624 ret='%s%scommon /%s/ %s'%(ret, tab, k, ','.join(common[k]))
|
Chris@87
|
2625 return ret
|
Chris@87
|
2626
|
Chris@87
|
2627 def use2fortran(use,tab=''):
|
Chris@87
|
2628 ret=''
|
Chris@87
|
2629 for m in list(use.keys()):
|
Chris@87
|
2630 ret='%s%suse %s,'%(ret, tab, m)
|
Chris@87
|
2631 if use[m]=={}:
|
Chris@87
|
2632 if ret and ret[-1]==',': ret=ret[:-1]
|
Chris@87
|
2633 continue
|
Chris@87
|
2634 if 'only' in use[m] and use[m]['only']:
|
Chris@87
|
2635 ret='%s only:'%(ret)
|
Chris@87
|
2636 if 'map' in use[m] and use[m]['map']:
|
Chris@87
|
2637 c=' '
|
Chris@87
|
2638 for k in list(use[m]['map'].keys()):
|
Chris@87
|
2639 if k==use[m]['map'][k]:
|
Chris@87
|
2640 ret='%s%s%s'%(ret, c, k); c=','
|
Chris@87
|
2641 else:
|
Chris@87
|
2642 ret='%s%s%s=>%s'%(ret, c, k, use[m]['map'][k]); c=','
|
Chris@87
|
2643 if ret and ret[-1]==',': ret=ret[:-1]
|
Chris@87
|
2644 return ret
|
Chris@87
|
2645
|
Chris@87
|
2646 def true_intent_list(var):
|
Chris@87
|
2647 lst = var['intent']
|
Chris@87
|
2648 ret = []
|
Chris@87
|
2649 for intent in lst:
|
Chris@87
|
2650 try:
|
Chris@87
|
2651 c = eval('isintent_%s(var)' % intent)
|
Chris@87
|
2652 except NameError:
|
Chris@87
|
2653 c = 0
|
Chris@87
|
2654 if c:
|
Chris@87
|
2655 ret.append(intent)
|
Chris@87
|
2656 return ret
|
Chris@87
|
2657
|
Chris@87
|
2658 def vars2fortran(block,vars,args,tab='', as_interface=False):
|
Chris@87
|
2659 """
|
Chris@87
|
2660 TODO:
|
Chris@87
|
2661 public sub
|
Chris@87
|
2662 ...
|
Chris@87
|
2663 """
|
Chris@87
|
2664 setmesstext(block)
|
Chris@87
|
2665 ret=''
|
Chris@87
|
2666 nout=[]
|
Chris@87
|
2667 for a in args:
|
Chris@87
|
2668 if a in block['vars']:
|
Chris@87
|
2669 nout.append(a)
|
Chris@87
|
2670 if 'commonvars' in block:
|
Chris@87
|
2671 for a in block['commonvars']:
|
Chris@87
|
2672 if a in vars:
|
Chris@87
|
2673 if a not in nout:
|
Chris@87
|
2674 nout.append(a)
|
Chris@87
|
2675 else:
|
Chris@87
|
2676 errmess('vars2fortran: Confused?!: "%s" is not defined in vars.\n'%a)
|
Chris@87
|
2677 if 'varnames' in block:
|
Chris@87
|
2678 nout.extend(block['varnames'])
|
Chris@87
|
2679 if not as_interface:
|
Chris@87
|
2680 for a in list(vars.keys()):
|
Chris@87
|
2681 if a not in nout:
|
Chris@87
|
2682 nout.append(a)
|
Chris@87
|
2683 for a in nout:
|
Chris@87
|
2684 if 'depend' in vars[a]:
|
Chris@87
|
2685 for d in vars[a]['depend']:
|
Chris@87
|
2686 if d in vars and 'depend' in vars[d] and a in vars[d]['depend']:
|
Chris@87
|
2687 errmess('vars2fortran: Warning: cross-dependence between variables "%s" and "%s"\n'%(a, d))
|
Chris@87
|
2688 if 'externals' in block and a in block['externals']:
|
Chris@87
|
2689 if isintent_callback(vars[a]):
|
Chris@87
|
2690 ret='%s%sintent(callback) %s'%(ret, tab, a)
|
Chris@87
|
2691 ret='%s%sexternal %s'%(ret, tab, a)
|
Chris@87
|
2692 if isoptional(vars[a]):
|
Chris@87
|
2693 ret='%s%soptional %s'%(ret, tab, a)
|
Chris@87
|
2694 if a in vars and 'typespec' not in vars[a]:
|
Chris@87
|
2695 continue
|
Chris@87
|
2696 cont=1
|
Chris@87
|
2697 for b in block['body']:
|
Chris@87
|
2698 if a==b['name'] and b['block']=='function':
|
Chris@87
|
2699 cont=0;break
|
Chris@87
|
2700 if cont:
|
Chris@87
|
2701 continue
|
Chris@87
|
2702 if a not in vars:
|
Chris@87
|
2703 show(vars)
|
Chris@87
|
2704 outmess('vars2fortran: No definition for argument "%s".\n'%a)
|
Chris@87
|
2705 continue
|
Chris@87
|
2706 if a==block['name'] and not block['block']=='function':
|
Chris@87
|
2707 continue
|
Chris@87
|
2708 if 'typespec' not in vars[a]:
|
Chris@87
|
2709 if 'attrspec' in vars[a] and 'external' in vars[a]['attrspec']:
|
Chris@87
|
2710 if a in args:
|
Chris@87
|
2711 ret='%s%sexternal %s'%(ret, tab, a)
|
Chris@87
|
2712 continue
|
Chris@87
|
2713 show(vars[a])
|
Chris@87
|
2714 outmess('vars2fortran: No typespec for argument "%s".\n'%a)
|
Chris@87
|
2715 continue
|
Chris@87
|
2716 vardef=vars[a]['typespec']
|
Chris@87
|
2717 if vardef=='type' and 'typename' in vars[a]:
|
Chris@87
|
2718 vardef='%s(%s)'%(vardef, vars[a]['typename'])
|
Chris@87
|
2719 selector={}
|
Chris@87
|
2720 if 'kindselector' in vars[a]:
|
Chris@87
|
2721 selector=vars[a]['kindselector']
|
Chris@87
|
2722 elif 'charselector' in vars[a]:
|
Chris@87
|
2723 selector=vars[a]['charselector']
|
Chris@87
|
2724 if '*' in selector:
|
Chris@87
|
2725 if selector['*'] in ['*', ':']:
|
Chris@87
|
2726 vardef='%s*(%s)'%(vardef, selector['*'])
|
Chris@87
|
2727 else:
|
Chris@87
|
2728 vardef='%s*%s'%(vardef, selector['*'])
|
Chris@87
|
2729 else:
|
Chris@87
|
2730 if 'len' in selector:
|
Chris@87
|
2731 vardef='%s(len=%s'%(vardef, selector['len'])
|
Chris@87
|
2732 if 'kind' in selector:
|
Chris@87
|
2733 vardef='%s,kind=%s)'%(vardef, selector['kind'])
|
Chris@87
|
2734 else:
|
Chris@87
|
2735 vardef='%s)'%(vardef)
|
Chris@87
|
2736 elif 'kind' in selector:
|
Chris@87
|
2737 vardef='%s(kind=%s)'%(vardef, selector['kind'])
|
Chris@87
|
2738 c=' '
|
Chris@87
|
2739 if 'attrspec' in vars[a]:
|
Chris@87
|
2740 attr=[]
|
Chris@87
|
2741 for l in vars[a]['attrspec']:
|
Chris@87
|
2742 if l not in ['external']:
|
Chris@87
|
2743 attr.append(l)
|
Chris@87
|
2744 if attr:
|
Chris@87
|
2745 vardef='%s, %s'%(vardef, ','.join(attr))
|
Chris@87
|
2746 c=','
|
Chris@87
|
2747 if 'dimension' in vars[a]:
|
Chris@87
|
2748 # if not isintent_c(vars[a]):
|
Chris@87
|
2749 # vars[a]['dimension'].reverse()
|
Chris@87
|
2750 vardef='%s%sdimension(%s)'%(vardef, c, ','.join(vars[a]['dimension']))
|
Chris@87
|
2751 c=','
|
Chris@87
|
2752 if 'intent' in vars[a]:
|
Chris@87
|
2753 lst = true_intent_list(vars[a])
|
Chris@87
|
2754 if lst:
|
Chris@87
|
2755 vardef='%s%sintent(%s)'%(vardef, c, ','.join(lst))
|
Chris@87
|
2756 c=','
|
Chris@87
|
2757 if 'check' in vars[a]:
|
Chris@87
|
2758 vardef='%s%scheck(%s)'%(vardef, c, ','.join(vars[a]['check']))
|
Chris@87
|
2759 c=','
|
Chris@87
|
2760 if 'depend' in vars[a]:
|
Chris@87
|
2761 vardef='%s%sdepend(%s)'%(vardef, c, ','.join(vars[a]['depend']))
|
Chris@87
|
2762 c=','
|
Chris@87
|
2763 if '=' in vars[a]:
|
Chris@87
|
2764 v = vars[a]['=']
|
Chris@87
|
2765 if vars[a]['typespec'] in ['complex', 'double complex']:
|
Chris@87
|
2766 try:
|
Chris@87
|
2767 v = eval(v)
|
Chris@87
|
2768 v = '(%s,%s)' % (v.real, v.imag)
|
Chris@87
|
2769 except:
|
Chris@87
|
2770 pass
|
Chris@87
|
2771 vardef='%s :: %s=%s'%(vardef, a, v)
|
Chris@87
|
2772 else:
|
Chris@87
|
2773 vardef='%s :: %s'%(vardef, a)
|
Chris@87
|
2774 ret='%s%s%s'%(ret, tab, vardef)
|
Chris@87
|
2775 return ret
|
Chris@87
|
2776 ######
|
Chris@87
|
2777
|
Chris@87
|
2778 def crackfortran(files):
|
Chris@87
|
2779 global usermodules
|
Chris@87
|
2780 outmess('Reading fortran codes...\n', 0)
|
Chris@87
|
2781 readfortrancode(files, crackline)
|
Chris@87
|
2782 outmess('Post-processing...\n', 0)
|
Chris@87
|
2783 usermodules=[]
|
Chris@87
|
2784 postlist=postcrack(grouplist[0])
|
Chris@87
|
2785 outmess('Post-processing (stage 2)...\n', 0)
|
Chris@87
|
2786 postlist=postcrack2(postlist)
|
Chris@87
|
2787 return usermodules+postlist
|
Chris@87
|
2788
|
Chris@87
|
2789 def crack2fortran(block):
|
Chris@87
|
2790 global f2py_version
|
Chris@87
|
2791 pyf=crack2fortrangen(block)+'\n'
|
Chris@87
|
2792 header="""! -*- f90 -*-
|
Chris@87
|
2793 ! Note: the context of this file is case sensitive.
|
Chris@87
|
2794 """
|
Chris@87
|
2795 footer="""
|
Chris@87
|
2796 ! This file was auto-generated with f2py (version:%s).
|
Chris@87
|
2797 ! See http://cens.ioc.ee/projects/f2py2e/
|
Chris@87
|
2798 """%(f2py_version)
|
Chris@87
|
2799 return header+pyf+footer
|
Chris@87
|
2800
|
Chris@87
|
2801 if __name__ == "__main__":
|
Chris@87
|
2802 files=[]
|
Chris@87
|
2803 funcs=[]
|
Chris@87
|
2804 f=1;f2=0;f3=0
|
Chris@87
|
2805 showblocklist=0
|
Chris@87
|
2806 for l in sys.argv[1:]:
|
Chris@87
|
2807 if l=='': pass
|
Chris@87
|
2808 elif l[0]==':':
|
Chris@87
|
2809 f=0
|
Chris@87
|
2810 elif l=='-quiet':
|
Chris@87
|
2811 quiet=1
|
Chris@87
|
2812 verbose=0
|
Chris@87
|
2813 elif l=='-verbose':
|
Chris@87
|
2814 verbose=2
|
Chris@87
|
2815 quiet=0
|
Chris@87
|
2816 elif l=='-fix':
|
Chris@87
|
2817 if strictf77:
|
Chris@87
|
2818 outmess('Use option -f90 before -fix if Fortran 90 code is in fix form.\n', 0)
|
Chris@87
|
2819 skipemptyends=1
|
Chris@87
|
2820 sourcecodeform='fix'
|
Chris@87
|
2821 elif l=='-skipemptyends':
|
Chris@87
|
2822 skipemptyends=1
|
Chris@87
|
2823 elif l=='--ignore-contains':
|
Chris@87
|
2824 ignorecontains=1
|
Chris@87
|
2825 elif l=='-f77':
|
Chris@87
|
2826 strictf77=1
|
Chris@87
|
2827 sourcecodeform='fix'
|
Chris@87
|
2828 elif l=='-f90':
|
Chris@87
|
2829 strictf77=0
|
Chris@87
|
2830 sourcecodeform='free'
|
Chris@87
|
2831 skipemptyends=1
|
Chris@87
|
2832 elif l=='-h':
|
Chris@87
|
2833 f2=1
|
Chris@87
|
2834 elif l=='-show':
|
Chris@87
|
2835 showblocklist=1
|
Chris@87
|
2836 elif l=='-m':
|
Chris@87
|
2837 f3=1
|
Chris@87
|
2838 elif l[0]=='-':
|
Chris@87
|
2839 errmess('Unknown option %s\n'%repr(l))
|
Chris@87
|
2840 elif f2:
|
Chris@87
|
2841 f2=0
|
Chris@87
|
2842 pyffilename=l
|
Chris@87
|
2843 elif f3:
|
Chris@87
|
2844 f3=0
|
Chris@87
|
2845 f77modulename=l
|
Chris@87
|
2846 elif f:
|
Chris@87
|
2847 try:
|
Chris@87
|
2848 open(l).close()
|
Chris@87
|
2849 files.append(l)
|
Chris@87
|
2850 except IOError as detail:
|
Chris@87
|
2851 errmess('IOError: %s\n'%str(detail))
|
Chris@87
|
2852 else:
|
Chris@87
|
2853 funcs.append(l)
|
Chris@87
|
2854 if not strictf77 and f77modulename and not skipemptyends:
|
Chris@87
|
2855 outmess("""\
|
Chris@87
|
2856 Warning: You have specifyied module name for non Fortran 77 code
|
Chris@87
|
2857 that should not need one (expect if you are scanning F90 code
|
Chris@87
|
2858 for non module blocks but then you should use flag -skipemptyends
|
Chris@87
|
2859 and also be sure that the files do not contain programs without program statement).
|
Chris@87
|
2860 """, 0)
|
Chris@87
|
2861
|
Chris@87
|
2862 postlist=crackfortran(files, funcs)
|
Chris@87
|
2863 if pyffilename:
|
Chris@87
|
2864 outmess('Writing fortran code to file %s\n'%repr(pyffilename), 0)
|
Chris@87
|
2865 pyf=crack2fortran(postlist)
|
Chris@87
|
2866 f=open(pyffilename, 'w')
|
Chris@87
|
2867 f.write(pyf)
|
Chris@87
|
2868 f.close()
|
Chris@87
|
2869 if showblocklist:
|
Chris@87
|
2870 show(postlist)
|