Coverage for src/castep_linter/fortran/variable_declaration.py: 100%

53 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-23 18:07 +0000

1"""Module holding the VariableDeclaration type""" 

2from enum import Enum, auto 

3from typing import ClassVar, Dict, List, Optional, Set, Tuple 

4 

5from castep_linter.fortran.argument_parser import ArgParser, ArgType 

6from castep_linter.fortran.fortran_node import Fortran, FortranNode 

7from castep_linter.fortran.fortran_statement import FortranStatementParser 

8from castep_linter.fortran.identifier import Identifier 

9 

10 

11class FType(Enum): 

12 """Intrinsic variable types in fortran""" 

13 

14 REAL = auto() 

15 DOUBLE = auto() 

16 COMPLEX = auto() 

17 INTEGER = auto() 

18 LOGICAL = auto() 

19 CHARACTER = auto() 

20 OTHER = auto() 

21 

22 

23def parse_fort_type(var_decl_node: FortranNode) -> FType: 

24 """Parse a variable declaration for type""" 

25 try: 

26 fortran_type = var_decl_node.get(Fortran.INTRINSIC_TYPE).raw.upper() 

27 if fortran_type == "DOUBLE PRECISION": 

28 return FType.DOUBLE 

29 else: 

30 return FType[fortran_type] 

31 except KeyError: 

32 return FType.OTHER 

33 

34 

35def parse_fort_type_qualifiers(var_decl_node: FortranNode) -> Set[str]: 

36 """Parse a variable declaration for qualifiers, eg parameter""" 

37 qualifiers = set() 

38 for type_qualifier in var_decl_node.get_children_by_name(Fortran.TYPE_QUALIFIER): 

39 qualifier = type_qualifier.raw.lower() 

40 qualifiers.add(qualifier) 

41 return qualifiers 

42 

43 

44def parse_fort_var_size(var_decl_node: FortranNode) -> ArgParser: 

45 """Parse a variable declaration for a size, eg kind=8""" 

46 try: 

47 fortran_size = var_decl_node.get(Fortran.SIZE) 

48 except KeyError: 

49 return ArgParser() 

50 

51 return ArgParser(fortran_size.get(Fortran.ARGUMENT_LIST)) 

52 

53 

54def parse_fort_var_names(var_decl_node: FortranNode) -> Dict[Identifier, Optional[str]]: 

55 """Parse variable declaration statement for variables and optionally assignments""" 

56 myvars: Dict[Identifier, Optional[str]] = {} 

57 for assignment in var_decl_node.get_children_by_name(Fortran.ASSIGNMENT_STMT): 

58 lhs, rhs = assignment.split() 

59 # lhs, rhs = split_relational_node(assignment) 

60 varname = Identifier.from_node(lhs) 

61 if rhs.is_type(Fortran.STRING_LITERAL): 

62 myvars[varname] = rhs.parse_string_literal() 

63 else: 

64 myvars[varname] = None 

65 return myvars 

66 

67 

68class VariableDeclaration(FortranStatementParser): 

69 """Class representing a variable declaration""" 

70 

71 ALLOWED_NODES: ClassVar[List[Fortran]] = [Fortran.VARIABLE_DECLARATION] 

72 

73 def __init__(self, var_decl_node: FortranNode) -> None: 

74 super().__init__(var_decl_node) 

75 

76 self.type = parse_fort_type(var_decl_node) 

77 self.qualifiers = parse_fort_type_qualifiers(var_decl_node) 

78 self.vars = parse_fort_var_names(var_decl_node) 

79 self.args = parse_fort_var_size(var_decl_node) 

80 

81 def get_arg( 

82 self, keyword: Identifier, position: Optional[int] = None 

83 ) -> Tuple[ArgType, FortranNode]: 

84 """Get an argument from the call expression""" 

85 return self.args.get(keyword, position)