• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rjfarmer / gfModParser / 18325561673

07 Oct 2025 08:37PM UTC coverage: 88.694% (-1.2%) from 89.901%
18325561673

push

github

rjfarmer
Typing

84 of 99 new or added lines in 13 files covered. (84.85%)

2 existing lines in 1 file now uncovered.

1012 of 1141 relevant lines covered (88.69%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.1
/gfModParser/modules/expressions.py
1
# SPDX-License-Identifier: GPL-2.0+
2

3
import numpy as np
1✔
4
from typing import List, Tuple
1✔
5

6
from .. import utils
1✔
7

8
from . import procedures
1✔
9

10

11
class Expression:
1✔
12
    def __init__(self, expression, *, version):
1✔
13
        self._expression = expression
1✔
14
        self.version = version
1✔
15
        t = self._expression[0]
1✔
16

17
        map = {
1✔
18
            "OP": ExpOp,
19
            "FUNCTION": ExpFunction,
20
            "CONSTANT": ExpConstant,
21
            "VARIABLE": ExpVariable,
22
            "SUBSTRING": ExpSubString,
23
            "STRUCTURE": ExpStructure,
24
            "ARRAY": ExpArray,
25
            "NULL": ExpNull,
26
            "COMPCALL": ExpCompCall,
27
            "PPC": ExpPPC,
28
            "UNKNOWN": ExpUnknown,
29
        }
30

31
        self._exp = map[t](
1✔
32
            self.typespec.type,
33
            self.typespec.kind,
34
            self._expression,
35
            version=self.version,
36
        )
37

38
    @property
1✔
39
    def type(self):
1✔
40
        return self._exp
1✔
41

42
    @property
1✔
43
    def typespec(self):
1✔
44
        return typespec(self._expression[1], version=self.version)
1✔
45

46
    @property
1✔
47
    def rank(self) -> int:
1✔
48
        return int(self._expression[2])
1✔
49

50
    @property
1✔
51
    def arglist(self) -> List:
1✔
52
        if len(self._exp._args) == 7:
×
53
            return procedures.actual_arglist(self._exp._args[6])
×
NEW
54
        return []
×
55

56
    @property
1✔
57
    def value(self):
1✔
58
        return self._exp.value
1✔
59

60
    def __str__(self):
1✔
61
        return self._exp.__str__()
1✔
62

63
    def __repr__(self):
1✔
64
        return self._exp.__repr__()
1✔
65

66
    @property
1✔
67
    def len(self) -> int:
1✔
68
        return self._exp.len
1✔
69

70
    @property
1✔
71
    def kind(self) -> int:
1✔
72
        return self.typespec.kind
1✔
73

74

75
class ExpGeneric:
1✔
76
    def __init__(self, type, kind, args, *, version):
1✔
77
        self._args = args
1✔
78
        self.version = version
1✔
79
        self._type = type
1✔
80
        self._kind = kind
1✔
81

82
    def __str__(self):
1✔
83
        return self._type
×
84

85
    def __repr__(self):
1✔
86
        return self._type
1✔
87

88
    @property
1✔
89
    def value(self):
1✔
90
        return None
×
91

92
    def __eq__(self, key):
1✔
93
        return self._type == key
1✔
94

95
    @property
1✔
96
    def kind(self) -> int:
1✔
97
        return self._kind
1✔
98

99

100
class ExpOp(ExpGeneric):
1✔
101

102
    @property
1✔
103
    def unary_op(self):
1✔
104
        return self._args[3]
×
105

106
    @property
1✔
107
    def unary_args(self):
1✔
108
        return Expression(self._args[4], version=self.version), Expression(
×
109
            self._args[5], version=self.version
110
        )
111

112

113
class ExpNotImplemented(ExpGeneric):
1✔
114
    @property
1✔
115
    def value(self):
1✔
116
        raise NotImplementedError
×
117

118

119
class ExpFunction(ExpGeneric):
1✔
120
    @property
1✔
121
    def value(self):
1✔
122
        return self._args[3]
×
123

124
    @property
1✔
125
    def args(self):
1✔
126
        return Expression(self._args[4], version=self.version)
×
127

128

129
class ExpConstant(ExpGeneric):
1✔
130
    @property
1✔
131
    def value(self):
1✔
132
        if self._type == "REAL":
1✔
133
            return utils.hextofloat(utils.string_clean(self._args[3]), self._kind)
1✔
134
        elif self._type == "INTEGER" or self._type == "UNSIGNED":
1✔
135
            return int(utils.string_clean(self._args[3]))
1✔
136
        elif self._type == "CHARACTER":
1✔
137
            return utils.string_clean(self._args[4])
1✔
138
        elif self._type == "COMPLEX":
1✔
139
            return complex(
1✔
140
                utils.hextofloat(utils.string_clean(self._args[3]), self._kind),
141
                utils.hextofloat(utils.string_clean(self._args[4]), self._kind),
142
            )
143
        elif self._type == "LOGICAL":
1✔
144
            return int(self._args[3]) == 1
1✔
145
        else:
146
            raise NotImplementedError(f"Type={self._type} args3={self._args[3]}")
×
147

148
    @property
1✔
149
    def len(self):
1✔
150
        if self._type == "CHARACTER":
1✔
151
            return int(self._args[3])
1✔
152

153
    def __str__(self):
1✔
154
        if self._type == "CHARACTER":
1✔
155
            return f"CHARACTER(kind={self.kind},len={self.len})"
1✔
156
        else:
157
            return f"{self.type}(kind={self.kind})"
1✔
158

159
    @property
1✔
160
    def type(self):
1✔
161
        return self._type
1✔
162

163
    @property
1✔
164
    def raw(self) -> str:
1✔
165
        return utils.string_clean(self._args[3])
×
166

167

168
class ExpVariable(ExpGeneric):
1✔
169
    @property
1✔
170
    def value(self):
1✔
171
        return self._args[3]
×
172

173
    def __str__(self):
1✔
174
        if self.type == "CHARACTER":
×
175
            return f"CHARACTER(kind={self.kind},len={self.len})"
×
176
        else:
177
            return f"{self.type}"
×
178

179

180
class ExpArray(ExpGeneric):
1✔
181
    def __init__(self, *args, **kwargs):
1✔
182
        super().__init__(*args, **kwargs)
1✔
183
        self._value = None
1✔
184

185
    @property
1✔
186
    def value(self) -> np.ndarray:
1✔
187
        if self._value is None:
1✔
188
            self._value = []
1✔
189
            for i in self._args[3]:
1✔
190
                self._value.append(Expression(i[0], version=self.version))
1✔
191

192
        value = []
1✔
193

194
        for v in self._value:
1✔
195
            value.append(v.value)
1✔
196

197
        return np.array(value, dtype=self.dtype).reshape(self.shape)
1✔
198

199
    @property
1✔
200
    def shape(self) -> Tuple:
1✔
201
        return tuple([int(utils.string_clean(i)) for i in self._args[4]])
1✔
202

203
    @property
1✔
204
    def dtype(self) -> np.dtype:
1✔
205
        v = Expression(self._args[3][0][0], version=self.version)
1✔
206
        return utils.dtype(v.type, self.kind, len=v.len)
1✔
207

208
    def __str__(self):
1✔
209
        v = Expression(self._args[3][0][0], version=self.version)
1✔
210
        if v.type == "CHARACTER":
1✔
211
            return f"CHARACTER(kind={v.kind},len={v.len}),dimension{self.shape}"
1✔
212
        else:
213
            return f"{v.type},dimension{self.shape}"
1✔
214

215

216
class ExpSubString(ExpNotImplemented):
1✔
217
    pass
1✔
218

219

220
class ExpStructure(ExpNotImplemented):
1✔
221
    pass
1✔
222

223

224
class ExpNull(ExpNotImplemented):
1✔
225
    pass
1✔
226

227

228
class ExpCompCall(ExpNotImplemented):
1✔
229
    pass
1✔
230

231

232
class ExpPPC(ExpNotImplemented):
1✔
233
    pass
1✔
234

235

236
class ExpUnknown(ExpNotImplemented):
1✔
237
    pass
1✔
238

239

240
# Need to store this here as we get a cyclic dependency
241
# between expressions and typespec
242
class typespec:
1✔
243
    def __init__(self, typespec, *, version):
1✔
244
        self._typespec = typespec
1✔
245
        self.version = version
1✔
246

247
    @property
1✔
248
    def type(self) -> str:
1✔
249
        return self._typespec[0]
1✔
250

251
    def _isclass(self):
1✔
252
        return self.type == "CLASS" or self.type == "DERIVED"
1✔
253

254
    @property
1✔
255
    def kind(self) -> int:
1✔
256
        if not self._isclass():
1✔
257
            return int(self._typespec[1])
1✔
NEW
258
        return -1
×
259

260
    @property
1✔
261
    def class_ref(self) -> int:
1✔
262
        if self._isclass():
×
263
            return int(self._typespec[1])
×
NEW
264
        return -1
×
265

266
    @property
1✔
267
    def interface(self):
1✔
268
        return self._typespec[2]
×
269

270
    @property
1✔
271
    def is_c_interop(self) -> bool:
1✔
272
        return int(self._typespec[3]) == 1
1✔
273

274
    @property
1✔
275
    def is_iso_c(self) -> bool:
1✔
276
        return int(self._typespec[4]) == 1
1✔
277

278
    @property
1✔
279
    def type2(self):
1✔
280
        # Whats this?
281
        return self._typespec[5]
×
282

283
    @property
1✔
284
    def charlen(self) -> int:
1✔
285
        return self._typespec[6]
×
286

287
    #     try:
288
    #         if not args[6][0]:
289
    #             self.charlen = -1
290
    #         else:
291
    #             self.charlen = Expression(
292
    #                 *args[6][0]
293
    #             )  # TODO: might this need to be iterated for mulit-d strings?
294
    #     except IndexError:
295
    #         self.charlen = -1
296

297
    @property
1✔
298
    def deferred_cl(self) -> bool:
1✔
299
        if len(self._typespec) == 8:
×
300
            return self._typespec[7] == "DEFERRED_CL"
×
301

302
        return False
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc