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

feihoo87 / waveforms / 10366062234

13 Aug 2024 08:00AM UTC coverage: 18.563% (-11.3%) from 29.887%
10366062234

push

github

feihoo87
rm codes

1294 of 6971 relevant lines covered (18.56%)

1.67 hits per line

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

0.0
/waveforms/scan/expression.py
1
from __future__ import annotations
×
2

3
import operator
×
4

5
import numpy as np
×
6
from pyparsing import (CaselessKeyword, Combine, Forward, Group, Keyword,
×
7
                       Literal, Optional, ParserElement, Suppress, Word,
8
                       alphanums, alphas, delimitedList, nums, oneOf, opAssoc,
9
                       pyparsing_common, restOfLine, srange, stringEnd,
10
                       stringStart)
11

12
LPAREN, RPAREN, LBRACK, RBRACK, LBRACE, RBRACE, DOT, TILDE, BANG, PLUS, MINUS = map(
×
13
    Suppress, "()[]{}.~!+-")
14

15
INT = Combine(srange("[1-9]") +
×
16
              Optional(Word(nums))).set_parse_action(lambda t: int(t[0]))
17
OCT = Combine("0" + Word("01234567")).set_parse_action(lambda t: int(t[0], 8))
×
18
HEX = Combine("0x" + Word("0123456789abcdefABCDEF")).set_parse_action(
×
19
    lambda t: int(t[0], 16))
20
FLOAT = Combine(Word(nums) + DOT + Word(nums)) | \
×
21
        Combine(DOT + Word(nums)) | \
22
        Combine(Word(nums) + DOT) | \
23
        Combine(Word(nums) + DOT + Word(nums) + CaselessKeyword("e") + Word("+-") + Word(nums)) | \
24
        Combine(Word(nums) + DOT + CaselessKeyword("e") + Word("+-") + Word(nums)) | \
25
        Combine(DOT + Word(nums) + CaselessKeyword("e") + Word("+-") + Word(nums)) | \
26
        Combine(Word(nums) + CaselessKeyword("e") + Word("+-") + Word(nums))
27
FLOAT.set_parse_action(lambda t: float(t[0]))
×
28
SYMBOL = Word(alphas, alphanums + "_")
×
29
SYMBOL.set_parse_action(lambda t: Symbol(t[0]))
×
30

31
expr = Forward()
×
32
unary = Forward()
×
33
binary = Forward()
×
34
atom = Forward()
×
35

36
atom << (INT | OCT | HEX | FLOAT | SYMBOL | (LPAREN + expr + RPAREN) |
×
37
         (LBRACK + expr + RBRACK) | (LBRACE + expr + RBRACE) | (MINUS + atom) |
38
         (PLUS + atom) | (TILDE + atom) | (BANG + atom) | (nums + DOT + nums))
39

40
unary << (atom | (MINUS + unary) | (PLUS + unary) | (TILDE + unary) |
×
41
          (BANG + unary))
42

43
ConstType = (int, float, complex)
×
44
_empty = object()
×
45

46

47
class Ref():
×
48
    __slots__ = ['name']
×
49

50
    def __init__(self, name):
×
51
        self.name = name
×
52

53
    def __repr__(self) -> str:
×
54
        return f"Ref({self.name!r})"
×
55

56

57
class Env():
×
58

59
    def __init__(self):
×
60
        self.consts = {}
×
61
        self.variables = {}
×
62
        self.refs = {}
×
63

64
    def __contains__(self, key):
×
65
        return key in self.consts or key in self.variables or key in self.refs
×
66

67
    def __getitem__(self, key):
×
68
        if key in self.consts:
×
69
            return self.consts[key]
×
70
        if key in self.variables:
×
71
            return self.variables[key]
×
72
        if key in self.refs:
×
73
            return self[self.refs[key]]
×
74
        raise KeyError(f"Key {key} not found")
×
75

76
    def __setitem__(self, key, value):
×
77
        if key in self.consts:
×
78
            raise KeyError(f"Key {key:r} is const")
×
79
        elif isinstance(value, Ref):
×
80
            self.create_ref(key, value.name)
×
81
        elif key in self.refs:
×
82
            self[self.refs[key]] = value
×
83
        else:
84
            self.variables[key] = value
×
85

86
    def __delitem__(self, key):
×
87
        if key in self.consts:
×
88
            raise KeyError(f"Key {key:r} is const")
×
89
        elif key in self.refs:
×
90
            del self[self.refs[key]]
×
91
        else:
92
            del self.variables[key]
×
93

94
    def ref(self, key):
×
95
        if key in self:
×
96
            return Ref(key)
×
97
        else:
98
            raise KeyError(f"Key {key!r} not found")
×
99

100
    def create_ref(self, key, name):
×
101
        if name in self.refs:
×
102
            if key in self.refs[name]:
×
103
                raise ValueError(f"Key {key!r} already exists in ref {name!r}")
×
104
            else:
105
                self.refs[key] = [name, *self.refs[name]]
×
106
        else:
107
            self.refs[key] = [name]
×
108

109
    def is_const(self, key):
×
110
        return key in self.consts
×
111

112

113
class Expression():
×
114

115
    def __init__(self):
×
116
        self.cache = _empty
×
117

118
    def d(self, x: str | Symbol):
×
119
        if isinstance(x, Symbol):
×
120
            x = x.name
×
121
        if x in self.symbols():
×
122
            return self.derivative(x)
×
123
        else:
124
            return 0
×
125

126
    def derivative(self, x):
×
127
        raise NotImplementedError
×
128

129
    def __add__(self, other):
×
130
        return BinaryExpression(self, other, operator.add)
×
131

132
    def __radd__(self, other):
×
133
        return BinaryExpression(other, self, operator.add)
×
134

135
    def __sub__(self, other):
×
136
        return BinaryExpression(self, other, operator.sub)
×
137

138
    def __rsub__(self, other):
×
139
        return BinaryExpression(other, self, operator.sub)
×
140

141
    def __mul__(self, other):
×
142
        return BinaryExpression(self, other, operator.mul)
×
143

144
    def __rmul__(self, other):
×
145
        return BinaryExpression(other, self, operator.mul)
×
146

147
    def __truediv__(self, other):
×
148
        return BinaryExpression(self, other, operator.truediv)
×
149

150
    def __rtruediv__(self, other):
×
151
        return BinaryExpression(other, self, operator.truediv)
×
152

153
    def __pow__(self, other):
×
154
        return BinaryExpression(self, other, operator.pow)
×
155

156
    def __rpow__(self, other):
×
157
        return BinaryExpression(other, self, operator.pow)
×
158

159
    def __neg__(self):
×
160
        return UnaryExpression(self, operator.neg)
×
161

162
    def __pos__(self):
×
163
        return UnaryExpression(self, operator.pos)
×
164

165
    def __eq__(self, other):
×
166
        return BinaryExpression(self, other, operator.eq)
×
167

168
    def __ne__(self, other):
×
169
        return BinaryExpression(self, other, operator.ne)
×
170

171
    def __lt__(self, other):
×
172
        return BinaryExpression(self, other, operator.lt)
×
173

174
    def __le__(self, other):
×
175
        return BinaryExpression(self, other, operator.le)
×
176

177
    def __gt__(self, other):
×
178
        return BinaryExpression(self, other, operator.gt)
×
179

180
    def __ge__(self, other):
×
181
        return BinaryExpression(self, other, operator.ge)
×
182

183
    def __getitem__(self, other):
×
184
        return ObjectMethod(self, '__getitem__', other)
×
185

186
    def __getattr__(self, other):
×
187
        return ObjectMethod(self, '__getattr__', other)
×
188

189
    def __call__(self, *args):
×
190
        return ObjectMethod(self, '__call__', *args)
×
191
    
192
    def __round__(self, n=None):
×
193
        return self
×
194

195
    def eval(self, env):
×
196
        raise NotImplementedError
×
197

198
    def symbols(self) -> list[str]:
×
199
        raise NotImplementedError
×
200

201
    def changed(self, env) -> bool:
×
202
        return True
×
203

204
    def is_const(self, env) -> bool:
×
205
        return False
×
206

207
    def value(self, env):
×
208
        if self.changed(env):
×
209
            self.cache = self.eval(env)
×
210
        return self.cache
×
211

212

213
class UnaryExpression(Expression):
×
214

215
    def __init__(self, a, op):
×
216
        super().__init__()
×
217
        self.a = a
×
218
        self.op = op
×
219

220
    def symbols(self) -> list[str]:
×
221
        if isinstance(self.a, Expression):
×
222
            return self.a.symbols()
×
223
        else:
224
            return []
×
225

226
    def changed(self, env) -> bool:
×
227
        if isinstance(self.a, ConstType):
×
228
            return False
×
229
        return self.cache is _empty or isinstance(
×
230
            self.a, Expression) and self.a.changed(env)
231

232
    def is_const(self, env) -> bool:
×
233
        return isinstance(self.a,
×
234
                          Expression) and self.a.is_const(env) or isinstance(
235
                              self.a, ConstType)
236

237
    def eval(self, env):
×
238
        a = self.a.value(env) if isinstance(self.a, Expression) else self.a
×
239
        return self.op(a)
×
240

241
    def derivative(self, x):
×
242
        if isinstance(self.a, Expression):
×
243
            return self.op(self.a.d(x))
×
244
        else:
245
            return 0
×
246
        
247
    def __repr__(self) -> str:
×
248
        return f"{self.op.__name__}({self.a!r})"
×
249

250

251
class BinaryExpression(Expression):
×
252

253
    def __init__(self, a, b, op):
×
254
        super().__init__()
×
255
        self.a = a
×
256
        self.b = b
×
257
        self.op = op
×
258

259
    def symbols(self) -> list[str]:
×
260
        symbs = set()
×
261
        if isinstance(self.a, Expression):
×
262
            symbs.update(self.a.symbols())
×
263
        if isinstance(self.b, Expression):
×
264
            symbs.update(self.b.symbols())
×
265
        return list(symbs)
×
266

267
    def eval(self, env):
×
268
        a = self.a.value(env) if isinstance(self.a, Expression) else self.a
×
269
        b = self.b.value(env) if isinstance(self.b, Expression) else self.b
×
270
        return self.op(a, b)
×
271

272
    def derivative(self, x):
×
273
        if isinstance(self.a, Expression):
×
274
            da = self.a.d(x)
×
275
        else:
276
            da = 0
×
277
        if isinstance(self.b, Expression):
×
278
            db = self.b.d(x)
×
279
        else:
280
            db = 0
×
281

282
        if self.op is operator.add:
×
283
            return da + db
×
284
        elif self.op is operator.sub:
×
285
            return da - db
×
286
        elif self.op is operator.mul:
×
287
            return self.a * db + da * self.b
×
288
        elif self.op is operator.truediv:
×
289
            return (da * self.b - self.a * db) / self.b**2
×
290
        elif self.op is operator.pow:
×
291
            if isinstance(self.a, Expression) and isinstance(
×
292
                    self.b, Expression):
293
                return self.a**self.b * (self.b * da / self.a +
×
294
                                         ObjectMethod(np, 'log', self.a) * db)
295
            elif isinstance(self.a, Expression):
×
296
                return self.b * self.a**(self.b - 1) * da
×
297
            elif isinstance(self.b, Expression):
×
298
                return np.log(self.a) * db * self.a**self.b
×
299
            else:
300
                return 0
×
301
        else:
302
            return 0
×
303
        
304
    def __repr__(self) -> str:
×
305
        return f"({self.a!r} {self.op.__name__} {self.b!r})"
×
306

307

308
class ObjectMethod(Expression):
×
309

310
    def __init__(self, obj, method: str, *args):
×
311
        super().__init__()
×
312
        self.obj = obj
×
313
        self.method = method
×
314
        self.args = args
×
315

316
    def symbols(self) -> list[str]:
×
317
        symbs = set()
×
318
        if isinstance(self.obj, Expression):
×
319
            symbs.update(self.obj.symbols())
×
320
        for a in self.args:
×
321
            if isinstance(a, Expression):
×
322
                symbs.update(a.symbols())
×
323
        return list(symbs)
×
324

325
    def eval(self, env):
×
326
        obj = self.obj.value(env) if isinstance(self.obj,
×
327
                                                Expression) else self.obj
328
        args = [
×
329
            a.value(env) if isinstance(a, Expression) else a for a in self.args
330
        ]
331
        if isinstance(obj, Expression) or any(
×
332
                isinstance(x, Expression) for x in args):
333
            return ObjectMethod(obj, self.method, *args)
×
334
        else:
335
            return getattr(obj, self.method)(*args)
×
336

337

338
class Symbol(Expression):
×
339

340
    def __init__(self, name):
×
341
        super().__init__()
×
342
        self.name = name
×
343

344
    def symbols(self) -> list[str]:
×
345
        return [self.name]
×
346

347
    def eval(self, env):
×
348
        if self.name in env:
×
349
            return env[self.name]
×
350
        else:
351
            return self
×
352

353
    def derivative(self, x):
×
354
        if x == self.name:
×
355
            return 1
×
356
        else:
357
            return 0
×
358
    
359
    def __repr__(self) -> str:
×
360
        return self.name
×
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