19
19
class FortranAST :
20
20
def __init__ (self , file_obj = None ):
21
21
self .file = file_obj
22
- self .path : str = None
23
- if file_obj is not None :
24
- self .path = file_obj .path
22
+ self .path : str | None = file_obj .path if file_obj is not None else None
25
23
self .global_dict : dict = {}
26
24
self .scope_list : list = []
27
25
self .variable_list : list = []
@@ -39,10 +37,10 @@ def __init__(self, file_obj=None):
39
37
self .none_scope = None
40
38
self .inc_scope = None
41
39
self .current_scope = None
42
- self .END_SCOPE_REGEX : Pattern = None
43
- self .enc_scope_name : str = None
40
+ self .end_scope_regex : Pattern | None = None
41
+ self .enc_scope_name : str | None = None
44
42
self .last_obj = None
45
- self .pending_doc : str = None
43
+ self .pending_doc : str | None = None
46
44
47
45
def create_none_scope (self ):
48
46
"""Create empty scope to hold non-module contained items"""
@@ -60,7 +58,7 @@ def get_enc_scope_name(self):
60
58
def add_scope (
61
59
self ,
62
60
new_scope : Scope ,
63
- END_SCOPE_REGEX : Pattern [str ],
61
+ end_scope_regex : Pattern [str ],
64
62
exportable : bool = True ,
65
63
req_container : bool = False ,
66
64
):
@@ -80,10 +78,10 @@ def add_scope(
80
78
else :
81
79
self .current_scope .add_child (new_scope )
82
80
self .scope_stack .append (self .current_scope )
83
- if self .END_SCOPE_REGEX is not None :
84
- self .end_stack .append (self .END_SCOPE_REGEX )
81
+ if self .end_scope_regex is not None :
82
+ self .end_stack .append (self .end_scope_regex )
85
83
self .current_scope = new_scope
86
- self .END_SCOPE_REGEX = END_SCOPE_REGEX
84
+ self .end_scope_regex = end_scope_regex
87
85
self .enc_scope_name = self .get_enc_scope_name ()
88
86
self .last_obj = new_scope
89
87
if self .pending_doc is not None :
@@ -102,9 +100,9 @@ def end_scope(self, line_number: int, check: bool = True):
102
100
else :
103
101
self .current_scope = None
104
102
if len (self .end_stack ) > 0 :
105
- self .END_SCOPE_REGEX = self .end_stack .pop ()
103
+ self .end_scope_regex = self .end_stack .pop ()
106
104
else :
107
- self .END_SCOPE_REGEX = None
105
+ self .end_scope_regex = None
108
106
self .enc_scope_name = self .get_enc_scope_name ()
109
107
110
108
def add_variable (self , new_var : Variable ):
@@ -170,11 +168,11 @@ def add_error(self, msg: str, sev: int, ln: int, sch: int, ech: int = None):
170
168
def start_ppif (self , line_number : int ):
171
169
self .pp_if .append ([line_number - 1 , - 1 ])
172
170
173
- def end_ppif (self , line_number ):
171
+ def end_ppif (self , line_number : int ):
174
172
if len (self .pp_if ) > 0 :
175
173
self .pp_if [- 1 ][1 ] = line_number - 1
176
174
177
- def get_scopes (self , line_number : int = None ):
175
+ def get_scopes (self , line_number : int | None = None ):
178
176
"""Get a list of all the scopes present in the line number provided.
179
177
180
178
Parameters
@@ -191,65 +189,69 @@ def get_scopes(self, line_number: int = None):
191
189
return self .scope_list
192
190
scope_list = []
193
191
for scope in self .scope_list :
194
- if (line_number >= scope .sline ) and (line_number <= scope .eline ):
195
- if type (scope .parent ) == Interface :
196
- for use_stmnt in scope .use :
197
- if type (use_stmnt ) != Import :
198
- continue
199
- # Exclude the parent and all other scopes
200
- if use_stmnt .import_type == ImportTypes .NONE :
201
- return [scope ]
202
- scope_list .append (scope )
203
- scope_list .extend (iter (scope .get_ancestors ()))
192
+ if not scope .sline <= line_number <= scope .eline :
193
+ continue
194
+ if type (scope .parent ) is Interface :
195
+ for use_stmnt in scope .use :
196
+ if type (use_stmnt ) is not Import :
197
+ continue
198
+ # Exclude the parent and all other scopes
199
+ if use_stmnt .import_type == ImportTypes .NONE :
200
+ return [scope ]
201
+ scope_list .append (scope )
202
+ scope_list .extend (iter (scope .get_ancestors ()))
204
203
if scope_list or self .none_scope is None :
205
204
return scope_list
206
- else :
207
- return [self .none_scope ]
205
+ return [self .none_scope ]
208
206
209
207
def get_inner_scope (self , line_number : int ):
210
208
scope_sline = - 1
211
209
curr_scope = None
212
210
for scope in self .scope_list :
213
- if scope .sline > scope_sline and (
214
- (line_number >= scope .sline ) and (line_number <= scope .eline )
215
- ):
211
+ if scope .sline > scope_sline and scope .sline <= line_number <= scope .eline :
216
212
curr_scope = scope
217
213
scope_sline = scope .sline
218
214
if (curr_scope is None ) and (self .none_scope is not None ):
219
215
return self .none_scope
220
216
return curr_scope
221
217
222
218
def get_object (self , FQSN : str ):
223
- FQSN_split = FQSN .split ("::" )
224
- curr_obj = self .global_dict .get (FQSN_split [0 ])
225
- if curr_obj is None :
226
- # Look for non-exportable scopes
227
- for scope in self .scope_list :
228
- if FQSN_split [0 ] == scope .FQSN :
229
- curr_obj = scope
230
- break
231
- if curr_obj is None :
219
+ def find_child_by_name (parent , name ):
220
+ for child in parent .children :
221
+ if child .name == name :
222
+ return child
223
+ if child .name .startswith ("#GEN_INT" ):
224
+ found = next (
225
+ (
226
+ int_child
227
+ for int_child in child .get_children ()
228
+ if int_child .name == name
229
+ ),
230
+ None ,
231
+ )
232
+ if found :
233
+ return found
232
234
return None
233
- if len ( FQSN_split ) > 1 :
234
- for name in FQSN_split [ 1 :]:
235
- next_obj = None
236
- for child in curr_obj . children :
237
- if child . name . startswith ( "#GEN_INT" ):
238
- for int_child in child . get_children () :
239
- if int_child . name == name :
240
- next_obj = int_child
241
- break
242
- if next_obj is not None :
243
- break
244
- if child . name == name :
245
- next_obj = child
246
- break
247
- if next_obj is None :
248
- return None
249
- curr_obj = next_obj
250
- return curr_obj
251
-
252
- def resolve_includes (self , workspace , path : str = None ):
235
+
236
+ parts = FQSN . split ( "::" )
237
+ current = self . global_dict . get ( parts [ 0 ])
238
+
239
+ # Look for non-exportable scopes
240
+ if current is None :
241
+ current = next (
242
+ ( scope for scope in self . scope_list if scope . FQSN == parts [ 0 ]), None
243
+ )
244
+ if current is None :
245
+ return None
246
+
247
+ for part in parts [ 1 :]:
248
+ current = find_child_by_name ( current , part )
249
+ if current is None :
250
+ return None
251
+
252
+ return current
253
+
254
+ def resolve_includes (self , workspace , path : str | None = None ):
253
255
file_dir = os .path .dirname (self .path )
254
256
for inc in self .include_statements :
255
257
file_path = os .path .normpath (os .path .join (file_dir , inc .path ))
0 commit comments