1515listed.
1616"""
1717from collections import namedtuple
18+ import json
1819import re
1920from ompi_bindings import compiler , consts , util
2021from ompi_bindings .fortran_type import FortranType
2122
2223
2324FortranParameter = namedtuple ('FortranParameter' , ['type_name' , 'name' , 'dep_params' ])
24- FortranPrototype = namedtuple ('FortranPrototype' , ['fn_name' , 'lno' , 'parameters' ])
25-
26-
27- def parse_prototype (lno , line ):
28- """Parse a prototype for the given line and string."""
29- if consts .PROTOTYPE_RE .match (line ) is None :
30- raise util .BindingError (
31- f'Invalid function prototype for Fortran interface starting on line { lno } '
32- )
33-
34- start = line .index ('(' )
35- end = line .index (')' )
36- fn_name = line [1 :start ].strip ()
37- parameters = line [start + 1 :end ].split (',' )
38-
39- # Attempt to parse each parameter
40- parsed_parameters = []
41- try :
42- for param in parameters :
43- param = param .strip ()
44- param_parts = param .split ()
45- type_name = param_parts [0 ]
46- name = '' .join (param_parts [1 :])
47- type_ = FortranType .get (type_name )
48- dep_params = None
49-
50- # Check for 'param[name=param(;name=param)]' parameters,
51- # indicating a dependency on that other parameter
52- if '[' in name :
53- idx = name .index ('[' )
54- dep_params = [part .split ('=' ) for part in name [idx + 1 :- 1 ].split (';' )]
55- dep_params = dict (dep_params )
56- name = name [:idx ]
57-
58- # Validate the parameter key values (or an empty list if not found)
59- type_ .validate_dep_param_keys (name , [] if dep_params is None else dep_params .keys ())
60-
61- parsed_parameters .append (FortranParameter (type_name , name , dep_params ))
62- return FortranPrototype (fn_name , lno , parsed_parameters )
63- except util .BindingError as err :
64- raise util .BindingError (
65- f'Failed to parse prototype starting on line { lno } : { err } '
66- ) from None
67- except KeyError as err :
68- raise util .BindingError (
69- f'Found invalid type starting on line { lno } : { err } '
70- ) from None
25+ FortranPrototype = namedtuple ('FortranPrototype' , ['fn_name' , 'parameters' ])
7126
7227
7328def load_prototypes (fname ):
74- """Load the prototypes from a file."""
29+ """Load the prototypes from a JSON file."""
7530 with open (fname ) as fp :
76- tmp_proto_string = []
77- proto_strings = []
78- cur_lno = 0
79- reading_proto = False
80-
81- # The loop below is designed to read in each prototype, each delimited
82- # by a '.' preceding the name of the subroutine, allowing for the
83- # prototype to run across multiple lines.
84- for i , line in enumerate (fp ):
85- lno = i + 1
86- line = line .strip ()
87-
88- # First strip comments
89- comm_idx = line .find ('#' )
90- if comm_idx != - 1 :
91- line = line [:comm_idx ]
92- if not line :
93- continue
94-
95- # Set the current line for the prototype
96- if not tmp_proto_string :
97- cur_lno = lno
98-
99- # Check for initial '.' character, indicating the start of a prototype
100- reading_proto = reading_proto or line [0 ] == '.'
101- if line [0 ] == '.' and tmp_proto_string :
102- # If the buffer is not empty, then the previous prototype
103- # string is complete and can be saved
104- proto_strings .append ((cur_lno , ' ' .join (tmp_proto_string )))
105- cur_lno = lno
106- tmp_proto_string = []
107- # Only add the line to the current buffer if we already encountered
108- # a '.' at the start of this or a previous line
109- if reading_proto :
110- tmp_proto_string .append (line )
111-
112- if tmp_proto_string :
113- proto_strings .append ((cur_lno , ' ' .join (tmp_proto_string )))
114-
115- return [parse_prototype (lno , proto_string ) for lno , proto_string in proto_strings ]
31+ data = json .load (fp )
32+ prototypes = []
33+ for proto in data :
34+ fn_name = proto ['name' ]
35+ parameters = []
36+ for param in proto ['parameters' ]:
37+ type_name = param ['type' ]
38+ type_ = FortranType .get (type_name )
39+ param_name = param ['name' ]
40+ dep_params = param ['dep_params' ] if 'dep_params' in param else None
41+ try :
42+ type_ .validate_dep_param_keys (param_name , [] if dep_params is None else dep_params .keys ())
43+ except util .BindingError as err :
44+ raise util .BindingError (f'Invalid prototype "{ fn_name } ": { err } ' ) from None
45+ parameters .append (FortranParameter (type_name , param_name , dep_params ))
46+ prototypes .append (FortranPrototype (fn_name , parameters ))
47+ return prototypes
11648
11749
11850class FortranBinding :
@@ -136,13 +68,13 @@ def __init__(self, prototype, out, bigcount=False, ts=False):
13668 if param .dep_params is not None :
13769 dep_params [param .name ] = param .dep_params
13870 # Set dependent parameters for those that need them
139- try :
140- for name , deps in dep_params . items () :
71+ for name , deps in dep_params . items () :
72+ try :
14173 param_map [name ].dep_params = {key : param_map [dep_name ] for key , dep_name in deps .items ()}
142- except KeyError as err :
143- raise util .BindingError (
144- f'Invalid dependent type in prototype starting on line { prototype .lno } : { err } '
145- )
74+ except KeyError as err :
75+ raise util .BindingError (
76+ f'Invalid dependent type for parameter " { name } " (prototype " { prototype .fn_name } ") : { err } '
77+ ) from None
14678
14779 def dump (self , * pargs , ** kwargs ):
14880 """Write to the output file."""
@@ -370,7 +302,7 @@ def print_binding(prototype, lang, out, bigcount=False, ts=False):
370302
371303def generate_code (args , out ):
372304 """Generate binding code based on arguments."""
373- prototypes = load_prototypes (args .template )
305+ prototypes = load_prototypes (args .prototypes )
374306 if args .lang == 'fortran' :
375307 print_f_source_header (out )
376308 out .dump ()
@@ -388,7 +320,7 @@ def generate_code(args, out):
388320
389321def generate_interface (args , out ):
390322 """Generate the Fortran interface files."""
391- prototypes = load_prototypes (args .template )
323+ prototypes = load_prototypes (args .prototypes )
392324 out .dump (f'! { consts .GENERATED_MESSAGE } ' )
393325 for prototype in prototypes :
394326 ext_name = util .ext_api_func_name (prototype .fn_name )
0 commit comments