5
5
import os
6
6
import re
7
7
import sys
8
+ from typing import Literal
8
9
9
10
from fortls .constants import (
10
11
DO_TYPE_ID ,
11
12
INTERFACE_TYPE_ID ,
12
13
PY3K ,
13
14
SELECT_TYPE_ID ,
14
15
SUBMODULE_TYPE_ID ,
16
+ FUN_sig ,
17
+ RESULT_sig ,
15
18
log ,
16
19
)
17
20
from fortls .helper_functions import (
27
30
)
28
31
from fortls .objects import (
29
32
CLASS_info ,
30
- FUN_info ,
31
33
GEN_info ,
32
34
INT_info ,
33
35
SELECT_info ,
@@ -266,8 +268,8 @@ def read_var_def(line: str, type_word: str = None, fun_only: bool = False):
266
268
return None
267
269
#
268
270
keywords , trailing_line = parse_var_keywords (trailing_line )
269
- # Check if function
270
- fun_def = read_fun_def (trailing_line , [ type_word , keywords ] )
271
+ # Check if this is a function definition
272
+ fun_def = read_fun_def (trailing_line , RESULT_sig ( type = type_word , keywords = keywords ) )
271
273
if (fun_def is not None ) or fun_only :
272
274
return fun_def
273
275
#
@@ -287,34 +289,42 @@ def read_var_def(line: str, type_word: str = None, fun_only: bool = False):
287
289
return "var" , VAR_info (type_word , keywords , var_words )
288
290
289
291
290
- def read_fun_def (line : str , result_type = None , mod_flag : bool = False ):
292
+ def read_fun_def (
293
+ line : str , result : RESULT_sig = RESULT_sig (), mod_flag : bool = False
294
+ ) -> tuple [Literal ["fun" ], FUN_sig ] | None :
291
295
"""Attempt to read FUNCTION definition line
292
296
297
+ To infer the `result` `type` and `name` the variable definition is called
298
+ with the function only flag
299
+
293
300
Parameters
294
301
----------
295
302
line : str
296
303
file line
297
- result_type : str , optional
298
- type of function e.g. INTEGER, REAL, etc., by default None
304
+ result : RESULT_sig , optional
305
+ a dataclass containing the result signature of the function
299
306
mod_flag : bool, optional
300
307
flag for module and module procedure parsing, by default False
301
308
302
309
Returns
303
310
-------
304
- tuple[Literal[' fun' ], FUN_info]
311
+ tuple[Literal[" fun" ], FUN_sig] | None
305
312
a named tuple
306
313
"""
307
- mod_match = SUB_MOD_REGEX .match (line )
308
- mods_found = False
309
- keywords : list [str ] = []
310
- while mod_match is not None :
311
- mods_found = True
312
- line = line [mod_match .end (0 ) :]
313
- keywords .append (mod_match .group (1 ))
314
- mod_match = SUB_MOD_REGEX .match (line )
315
- if mods_found :
314
+ # Get all the keyword modifier mathces
315
+ keywords = re .findall (SUB_MOD_REGEX , line )
316
+ # remove modifiers from line
317
+ for modifier in keywords :
318
+ line = line .replace (modifier , "" )
319
+
320
+ # Try and get the result type
321
+ # Recursively will call read_var_def which will then call read_fun_def
322
+ # with the variable result having been populated
323
+ if keywords :
316
324
tmp_var = read_var_def (line , fun_only = True )
317
325
if tmp_var is not None :
326
+ # Update keywords for function into dataclass
327
+ tmp_var [1 ].keywords = keywords
318
328
return tmp_var
319
329
fun_match = FUN_REGEX .match (line )
320
330
if fun_match is None :
@@ -334,12 +344,11 @@ def read_fun_def(line: str, result_type=None, mod_flag: bool = False):
334
344
trailing_line = trailing_line [paren_match .end (0 ) :]
335
345
336
346
# Extract if possible the variable name of the result()
337
- result_name = None
338
347
trailing_line = trailing_line .strip ()
339
348
results_match = RESULT_REGEX .match (trailing_line )
340
349
if results_match :
341
- result_name = results_match .group (1 ).strip ().lower ()
342
- return "fun" , FUN_info (name , args , result_type , result_name , mod_flag , keywords )
350
+ result . name = results_match .group (1 ).strip ().lower ()
351
+ return "fun" , FUN_sig (name , args , keywords , mod_flag , result = result )
343
352
344
353
345
354
def read_sub_def (line : str , mod_flag : bool = False ):
@@ -548,7 +557,8 @@ def read_mod_def(line: str):
548
557
return sub_res
549
558
fun_res = read_var_def (trailing_line , fun_only = True )
550
559
if fun_res is not None :
551
- return fun_res [0 ], fun_res [1 ]._replace (mod_flag = True )
560
+ fun_res [1 ].mod_flag = True
561
+ return fun_res [0 ], fun_res [1 ]
552
562
fun_res = read_fun_def (trailing_line , mod_flag = True )
553
563
if fun_res is not None :
554
564
return fun_res
@@ -1787,24 +1797,21 @@ def parser_debug_msg(msg: str, line: str, ln: int):
1787
1797
args = obj_info .args ,
1788
1798
mod_flag = obj_info .mod_flag ,
1789
1799
keywords = keywords ,
1790
- result_type = obj_info .return_type ,
1791
- result_name = obj_info .return_var ,
1800
+ result_type = obj_info .result . type ,
1801
+ result_name = obj_info .result . name ,
1792
1802
)
1793
1803
file_ast .add_scope (new_fun , END_FUN_REGEX )
1794
1804
# function type is present without result(), register the automatic
1795
1805
# result() variable that is the function name
1796
- if obj_info .return_type :
1797
- result_name = obj_info .name
1798
- if obj_info .return_var :
1799
- result_name = obj_info .return_var
1800
- keywords , keyword_info = map_keywords (obj_info .return_type [1 ])
1806
+ if obj_info .result .type :
1807
+ keywords , keyword_info = map_keywords (obj_info .result .keywords )
1801
1808
new_obj = fortran_var (
1802
1809
file_ast ,
1803
1810
line_number ,
1804
- result_name ,
1805
- obj_info .return_type [ 0 ] ,
1806
- keywords ,
1807
- keyword_info ,
1811
+ name = obj_info . result . name ,
1812
+ var_desc = obj_info .result . type ,
1813
+ keywords = keywords ,
1814
+ keyword_info = keyword_info ,
1808
1815
)
1809
1816
file_ast .add_variable (new_obj )
1810
1817
parser_debug_msg ("FUNCTION" , line , line_number )
0 commit comments