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

rjfarmer / gfModParser / 18107002290

29 Sep 2025 06:21PM UTC coverage: 90.669%. First build
18107002290

push

github

rjfarmer
Fix hextofloat

Closes #15

9 of 11 new or added lines in 2 files covered. (81.82%)

962 of 1061 relevant lines covered (90.67%)

0.91 hits per line

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

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

3
import numpy as np
1✔
4

5
from .. import utils
1✔
6

7
from . import procedures
1✔
8

9

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

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

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

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

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

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

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

54
    @property
1✔
55
    def value(self):
1✔
56
        return self._exp.value
1✔
57

58
    def __str__(self):
1✔
59
        return self._exp.__str__()
1✔
60

61
    def __repr__(self):
1✔
62
        return self._exp.__repr__()
1✔
63

64
    @property
1✔
65
    def len(self):
1✔
66
        return self._exp.len
1✔
67

68
    @property
1✔
69
    def kind(self):
1✔
70
        return self._exp._kind
1✔
71

72

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

80
    def __str__(self):
1✔
81
        return self._type
×
82

83
    def __repr__(self):
1✔
84
        return self._type
1✔
85

86
    @property
1✔
87
    def value(self):
1✔
88
        return None
×
89

90
    def __eq__(self, key):
1✔
91
        return self._type == key
1✔
92

93
    @property
1✔
94
    def kind(self):
1✔
95
        return self._kind
1✔
96

97

98
class ExpOp(ExpGeneric):
1✔
99

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

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

110

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

116

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

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

126

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

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

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

157
    @property
1✔
158
    def type(self):
1✔
159
        return self._type
1✔
160

161
    @property
1✔
162
    def raw(self):
1✔
NEW
163
        return utils.string_clean(self._args[3])
×
164

165

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

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

177

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

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

190
        value = []
1✔
191

192
        for v in self._value:
1✔
193
            value.append(v.value)
1✔
194

195
        return np.array(value, dtype=self.dtype).reshape(self.shape)
1✔
196

197
    @property
1✔
198
    def shape(self):
1✔
199
        return tuple([int(utils.string_clean(i)) for i in self._args[4]])
1✔
200

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

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

213

214
class ExpSubString(ExpNotImplemented):
1✔
215
    pass
1✔
216

217

218
class ExpStructure(ExpNotImplemented):
1✔
219
    pass
1✔
220

221

222
class ExpNull(ExpNotImplemented):
1✔
223
    pass
1✔
224

225

226
class ExpCompCall(ExpNotImplemented):
1✔
227
    pass
1✔
228

229

230
class ExpPPC(ExpNotImplemented):
1✔
231
    pass
1✔
232

233

234
class ExpUnknown(ExpNotImplemented):
1✔
235
    pass
1✔
236

237

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

245
    @property
1✔
246
    def type(self):
1✔
247
        return self._typespec[0]
1✔
248

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

252
    @property
1✔
253
    def kind(self):
1✔
254
        if not self._isclass():
1✔
255
            return int(self._typespec[1])
1✔
256

257
    @property
1✔
258
    def class_ref(self):
1✔
259
        if self._isclass():
×
260
            return int(self._typespec[1])
×
261

262
    @property
1✔
263
    def interface(self):
1✔
264
        return self._typespec[2]
×
265

266
    @property
1✔
267
    def is_c_interop(self):
1✔
268
        return int(self._typespec[3]) == 1
1✔
269

270
    @property
1✔
271
    def is_iso_c(self):
1✔
272
        return int(self._typespec[4]) == 1
1✔
273

274
    @property
1✔
275
    def type2(self):
1✔
276
        # Whats this?
277
        return self._typespec[5]
×
278

279
    @property
1✔
280
    def charlen(self):
1✔
281
        return self._typespec[6]
×
282

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

293
    @property
1✔
294
    def deferred_cl(self):
1✔
295
        if len(self._typespec) == 8:
×
296
            return self._typespec[7] == "DEFERRED_CL"
×
297

298
        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