diff options
Diffstat (limited to 'numpy/f2py/crackfortran.py')
-rwxr-xr-x | numpy/f2py/crackfortran.py | 59 |
1 files changed, 52 insertions, 7 deletions
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py index b02eb68b7..0374ae8d7 100755 --- a/numpy/f2py/crackfortran.py +++ b/numpy/f2py/crackfortran.py @@ -574,11 +574,16 @@ beginpattern90 = re.compile( groupends = (r'end|endprogram|endblockdata|endmodule|endpythonmodule|' r'endinterface|endsubroutine|endfunction') endpattern = re.compile( - beforethisafter % ('', groupends, groupends, r'[\w\s]*'), re.I), 'end' -endifs = r'(end\s*(if|do|where|select|while|forall|associate|block|critical|enum|team))|(module\s*procedure)' + beforethisafter % ('', groupends, groupends, r'.*'), re.I), 'end' +endifs = r'end\s*(if|do|where|select|while|forall|associate|block|' + \ + r'critical|enum|team)' endifpattern = re.compile( beforethisafter % (r'[\w]*?', endifs, endifs, r'[\w\s]*'), re.I), 'endif' # +moduleprocedures = r'module\s*procedure' +moduleprocedurepattern = re.compile( + beforethisafter % ('', moduleprocedures, moduleprocedures, r'.*'), re.I), \ + 'moduleprocedure' implicitpattern = re.compile( beforethisafter % ('', 'implicit', 'implicit', '.*'), re.I), 'implicit' dimensionpattern = re.compile(beforethisafter % ( @@ -727,7 +732,8 @@ def crackline(line, reset=0): callpattern, usepattern, containspattern, entrypattern, f2pyenhancementspattern, - multilinepattern + multilinepattern, + moduleprocedurepattern ]: m = pat[0].match(line) if m: @@ -797,6 +803,8 @@ def crackline(line, reset=0): expectbegin = 0 elif pat[1] == 'endif': pass + elif pat[1] == 'moduleprocedure': + analyzeline(m, pat[1], line) elif pat[1] == 'contains': if ignorecontains: return @@ -884,8 +892,14 @@ def appenddecl(decl, decl2, force=1): selectpattern = re.compile( r'\s*(?P<this>(@\(@.*?@\)@|\*[\d*]+|\*\s*@\(@.*?@\)@|))(?P<after>.*)\Z', re.I) +typedefpattern = re.compile( + r'(?:,(?P<attributes>[\w(),]+))?(::)?(?P<name>\b[a-z$_][\w$]*\b)' + r'(?:\((?P<params>[\w,]*)\))?\Z', re.I) 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) +operatorpattern = re.compile( + r'\s*(?P<scheme>(operator|assignment))' + r'@\(@\s*(?P<name>[^)]+)\s*@\)@\s*\Z', re.I) callnameargspattern = re.compile( r'\s*(?P<name>\b[\w$]+\b)\s*@\(@\s*(?P<args>.*)\s*@\)@\s*\Z', re.I) real16pattern = re.compile( @@ -903,11 +917,26 @@ def _is_intent_callback(vdecl): return 0 +def _resolvetypedefpattern(line): + line = ''.join(line.split()) # removes whitespace + m1 = typedefpattern.match(line) + print(line, m1) + if m1: + attrs = m1.group('attributes') + attrs = [a.lower() for a in attrs.split(',')] if attrs else [] + return m1.group('name'), attrs, m1.group('params') + return None, [], None + + def _resolvenameargspattern(line): line = markouterparen(line) m1 = nameargspattern.match(line) if m1: return m1.group('name'), m1.group('args'), m1.group('result'), m1.group('bind') + m1 = operatorpattern.match(line) + if m1: + name = m1.group('scheme') + '(' + m1.group('name') + ')' + return name, [], None, None m1 = callnameargspattern.match(line) if m1: return m1.group('name'), m1.group('args'), None, None @@ -947,7 +976,13 @@ def analyzeline(m, case, line): block = 'python module' elif re.match(r'abstract\s*interface', block, re.I): block = 'abstract interface' - name, args, result, bind = _resolvenameargspattern(m.group('after')) + if block == 'type': + name, attrs, _ = _resolvetypedefpattern(m.group('after')) + groupcache[groupcounter]['vars'][name] = dict(attrspec = attrs) + args = [] + result = None + else: + name, args, result, _ = _resolvenameargspattern(m.group('after')) if name is None: if block == 'block data': name = '_BLOCK_DATA_' @@ -1151,6 +1186,9 @@ def analyzeline(m, case, line): continue else: k = rmbadname1(m1.group('name')) + if case in ['public', 'private'] and \ + (k == 'operator' or k == 'assignment'): + k += m1.group('after') if k not in edecl: edecl[k] = {} if case == 'dimension': @@ -1193,6 +1231,9 @@ def analyzeline(m, case, line): groupcache[groupcounter]['vars'] = edecl if last_name is not None: previous_context = ('variable', last_name, groupcounter) + elif case == 'moduleprocedure': + groupcache[groupcounter]['implementedby'] = \ + [x.strip() for x in m.group('after').split(',')] elif case == 'parameter': edecl = groupcache[groupcounter]['vars'] ll = m.group('after').strip()[1:-1] @@ -2105,7 +2146,8 @@ def analyzebody(block, args, tab=''): else: as_ = args b = postcrack(b, as_, tab=tab + '\t') - if b['block'] in ['interface', 'abstract interface'] and not b['body']: + if b['block'] in ['interface', 'abstract interface'] and \ + not b['body'] and not b['implementedby']: if 'f2pyenhancements' not in b: continue if b['block'].replace(' ', '') == 'pythonmodule': @@ -2591,7 +2633,10 @@ def analyzevars(block): if dsize.contains(s): try: a, b = dsize.linear_solve(s) - solve_v = lambda s: (s - b) / a + + def solve_v(s, a=a, b=b): + return (s - b) / a + all_symbols = set(a.symbols()) all_symbols.update(b.symbols()) except RuntimeError as msg: @@ -2661,7 +2706,7 @@ def analyzevars(block): # Skip a variable that # - n depends on # - has user-defined initialization expression - # - has user-defined dependecies + # - has user-defined dependencies continue if solver is not None: # v can be solved from d, hence, we |