oasm 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oasm/__init__.py +670 -0
- oasm-0.1.0.dist-info/METADATA +13 -0
- oasm-0.1.0.dist-info/RECORD +5 -0
- oasm-0.1.0.dist-info/WHEEL +5 -0
- oasm-0.1.0.dist-info/top_level.txt +1 -0
oasm/__init__.py
ADDED
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
__all__ = ['table','config','equal','expr','sym','context','flow','meta','multi','domain']
|
|
2
|
+
from pprint import pformat
|
|
3
|
+
|
|
4
|
+
class table(list):
|
|
5
|
+
def __init__(self, *args, **kwargs):
|
|
6
|
+
super().__init__(args)
|
|
7
|
+
self.__dict__.update(kwargs)
|
|
8
|
+
def __getitem__(self, key=None):
|
|
9
|
+
if type(key) is str:
|
|
10
|
+
return self.__dict__[key]
|
|
11
|
+
return super().__getitem__(key)
|
|
12
|
+
def __setitem__(self, key, val):
|
|
13
|
+
if type(key) is str:
|
|
14
|
+
self.__dict__[key] = val
|
|
15
|
+
else:
|
|
16
|
+
super().__setitem__(key, val)
|
|
17
|
+
def __delitem__(self, key):
|
|
18
|
+
if type(key) is str:
|
|
19
|
+
del self.__dict__[key]
|
|
20
|
+
else:
|
|
21
|
+
super().__delitem__(key)
|
|
22
|
+
def __call__(self, *args, **kwargs):
|
|
23
|
+
func = self.__dict__.get('__call__',None)
|
|
24
|
+
if func is not None:
|
|
25
|
+
return func(self,*args,**kwargs)
|
|
26
|
+
if len(args) == 0 and len(kwargs) == 0:
|
|
27
|
+
return self
|
|
28
|
+
super().extend(args)
|
|
29
|
+
self.__dict__.update(kwargs)
|
|
30
|
+
return self
|
|
31
|
+
def __repr__(self):
|
|
32
|
+
r = ''
|
|
33
|
+
for i in self[:]:
|
|
34
|
+
r += pformat(i) + ','
|
|
35
|
+
for k,v in self.__dict__.items():
|
|
36
|
+
r += f'{k}={pformat(v)},'
|
|
37
|
+
if len(r) > 0 and r[-1] == ',':
|
|
38
|
+
r = r[:-1]
|
|
39
|
+
return '[' + r + ']'
|
|
40
|
+
def __neg__(self):
|
|
41
|
+
return self
|
|
42
|
+
def copy(self):
|
|
43
|
+
return self.__class__(*self[:],**self.__dict__)
|
|
44
|
+
@staticmethod
|
|
45
|
+
def to_dict(x):
|
|
46
|
+
if isinstance(x, table):
|
|
47
|
+
return {f'__{x.__class__.__name__}__':table.to_dict(x[:])}|table.to_dict(x.__dict__)
|
|
48
|
+
elif isinstance(x,(tuple,list)):
|
|
49
|
+
return [table.to_dict(v) for v in x]
|
|
50
|
+
elif isinstance(x,dict):
|
|
51
|
+
return {k:table.to_dict(v) for k,v in x.items()}
|
|
52
|
+
else:
|
|
53
|
+
return x
|
|
54
|
+
@classmethod
|
|
55
|
+
def from_dict(cls,dct):
|
|
56
|
+
cls = {table,config,expr,flow._tbl}|{cls}
|
|
57
|
+
for i in cls:
|
|
58
|
+
if f'__{i.__name__}__' in dct:
|
|
59
|
+
lst = dct.pop(f'__{i.__name__}__')
|
|
60
|
+
return i(*lst,**dct)
|
|
61
|
+
return dct
|
|
62
|
+
|
|
63
|
+
class config(table):
|
|
64
|
+
root = '../json'
|
|
65
|
+
|
|
66
|
+
@classmethod
|
|
67
|
+
def load(cls, name=None):
|
|
68
|
+
import json
|
|
69
|
+
dct = {}
|
|
70
|
+
for i in cls.__bases__:
|
|
71
|
+
if i not in (table,config):
|
|
72
|
+
dct |= i.load().__dict__
|
|
73
|
+
with open(f'{config.root}/{cls.__module__}.{name or cls.__name__}.json') as f:
|
|
74
|
+
val = json.load(f)
|
|
75
|
+
if type(val) is dict:
|
|
76
|
+
dct |= val
|
|
77
|
+
return cls.from_dict(dct)
|
|
78
|
+
else:
|
|
79
|
+
val.__dict__ = dct | val.__dict__
|
|
80
|
+
return val
|
|
81
|
+
|
|
82
|
+
def save(self, *args):
|
|
83
|
+
import json
|
|
84
|
+
if len(args) == 0:
|
|
85
|
+
args = self.__class__.__mro__[::-1][4:-1] + (self,)
|
|
86
|
+
dct = self.__dict__.copy()
|
|
87
|
+
for i in args:
|
|
88
|
+
with open(f"{config.root}/{i.__module__}.{getattr(i,'__name__',i.__class__.__name__)}.json",'w') as f:
|
|
89
|
+
if type(i) is type:
|
|
90
|
+
json.dump({k:dct.pop(k) for k in i.__annotations__}|{f'__{i.__name__}__':[]},f)
|
|
91
|
+
else:
|
|
92
|
+
json.dump(dct|{f'__{i.__class__.__name__}__':[]},f)
|
|
93
|
+
|
|
94
|
+
def __call__(self,*args,**kwargs):
|
|
95
|
+
func = self.__dict__.get('__call__',None)
|
|
96
|
+
if func is not None:
|
|
97
|
+
return func(self,*args,**kwargs)
|
|
98
|
+
import copy
|
|
99
|
+
r = copy.deepcopy(self)
|
|
100
|
+
for k,v in kwargs.items():
|
|
101
|
+
setattr(r,k,v)
|
|
102
|
+
return r
|
|
103
|
+
|
|
104
|
+
import operator
|
|
105
|
+
|
|
106
|
+
def equal(x, y):
|
|
107
|
+
if type(x) != type(y):
|
|
108
|
+
return False
|
|
109
|
+
if getattr(x,'__getitem__',None) is not None:
|
|
110
|
+
x = x[:]
|
|
111
|
+
y = y[:]
|
|
112
|
+
if type(x) in (tuple,list,dict):
|
|
113
|
+
if len(x) != len(y):
|
|
114
|
+
return False
|
|
115
|
+
if type(x) is dict:
|
|
116
|
+
for k,v in x.items():
|
|
117
|
+
if not equal(v,y.get(k,None)):
|
|
118
|
+
return False
|
|
119
|
+
else:
|
|
120
|
+
for i in range(len(x)):
|
|
121
|
+
if not equal(x[i],y[i]):
|
|
122
|
+
return False
|
|
123
|
+
return True
|
|
124
|
+
return x == y
|
|
125
|
+
|
|
126
|
+
class expr(table):
|
|
127
|
+
def __getitem__(self, key):
|
|
128
|
+
if type(key) is slice and key == slice(None,None,None):
|
|
129
|
+
return super().__getitem__(key)
|
|
130
|
+
dct = self.__dict__
|
|
131
|
+
if 'self' in dct:
|
|
132
|
+
this = dct.pop('self')
|
|
133
|
+
r = self.__class__(*self,key,**dct)
|
|
134
|
+
r.__dict__['self'] = this
|
|
135
|
+
dct['self'] = this
|
|
136
|
+
return r
|
|
137
|
+
else:
|
|
138
|
+
return self.__class__(*self,key,**dct)
|
|
139
|
+
def __getattr__(self, key):
|
|
140
|
+
return None if key.startswith('_') or key in ('compute','getdoc','size','shape') else self[key]
|
|
141
|
+
def __repr__(self):
|
|
142
|
+
if len(self) == 0:
|
|
143
|
+
return 'expr()'
|
|
144
|
+
line = 'sym' if self[:][0] is None else 'expr('+pformat(self[:][0])+')'
|
|
145
|
+
for i in self[:][1:]:
|
|
146
|
+
if type(i) is str:
|
|
147
|
+
line += f'.{i}'
|
|
148
|
+
elif type(i) is table:
|
|
149
|
+
line += '(' + repr(i)[1:-1] + ')'
|
|
150
|
+
else:
|
|
151
|
+
line += f'[{i}]'
|
|
152
|
+
return line[1:] if line.startswith('.') else line
|
|
153
|
+
def __call__(self, *args, **kwargs):
|
|
154
|
+
r = self[:][0]
|
|
155
|
+
body = self[:][1:]
|
|
156
|
+
body.append(table(*args,**kwargs))
|
|
157
|
+
for i in range(len(body)):
|
|
158
|
+
key = body[i]
|
|
159
|
+
if type(key) is table:
|
|
160
|
+
t = table(*key[:],**key.__dict__)
|
|
161
|
+
for k in range(len(key)):
|
|
162
|
+
v = t[k]
|
|
163
|
+
if type(v) is self.__class__:
|
|
164
|
+
dct = self.__dict__|v.__dict__
|
|
165
|
+
if 'self' in dct:
|
|
166
|
+
this = dct.pop('self')
|
|
167
|
+
v = self.__class__(*v[:],**dct)
|
|
168
|
+
v.__dict__['self'] = this
|
|
169
|
+
t[k] = v()
|
|
170
|
+
else:
|
|
171
|
+
t[k] = self.__class__(*v[:],**dct)()
|
|
172
|
+
for k,v in key.__dict__.items():
|
|
173
|
+
if type(v) is self.__class__:
|
|
174
|
+
dct = self.__dict__|v.__dict__
|
|
175
|
+
if 'self' in dct:
|
|
176
|
+
this = dct.pop('self')
|
|
177
|
+
v = self.__class__(*v[:],**dct)
|
|
178
|
+
v.__dict__['self'] = this
|
|
179
|
+
t.__dict__[k] = v()
|
|
180
|
+
else:
|
|
181
|
+
t.__dict__[k] = self.__class__(*v[:],**dct)()
|
|
182
|
+
if type(r) is self.__class__:
|
|
183
|
+
try:
|
|
184
|
+
v = r[:][0]
|
|
185
|
+
if v is None:
|
|
186
|
+
v = self.__dict__
|
|
187
|
+
for k in r[:][1:-1]:
|
|
188
|
+
geti = getattr(v,'__getitem__',None)
|
|
189
|
+
v = getattr(v,k) if geti is None else geti(k)
|
|
190
|
+
k = r[:][-1]
|
|
191
|
+
f = getattr(v,k,None) if type(k) is str else None
|
|
192
|
+
if callable(f):
|
|
193
|
+
r = f(*t[:],**t.__dict__)
|
|
194
|
+
else:
|
|
195
|
+
if len(t) == 0 and len(t.__dict__) == 0:
|
|
196
|
+
geti = getattr(v,'__getitem__',None)
|
|
197
|
+
try:
|
|
198
|
+
r = getattr(v,k) if geti is None else geti(k)
|
|
199
|
+
except:
|
|
200
|
+
if r[:][0] is None:
|
|
201
|
+
v = None
|
|
202
|
+
r = v[k] if type(v) is self.__class__ else self.__class__(v,k)
|
|
203
|
+
else:
|
|
204
|
+
seti = getattr(v,'__setitem__',None)
|
|
205
|
+
if len(t) == 1 and len(t.__dict__) == 0:
|
|
206
|
+
t = t[0]
|
|
207
|
+
setattr(v,k,t) if seti is None else seti(k,t)
|
|
208
|
+
r = expr(r[:][0])
|
|
209
|
+
except:
|
|
210
|
+
if not (i == len(body) - 1 and len(args) == 0 and len(kwargs) == 0):
|
|
211
|
+
r = r[t] if type(r) is self.__class__ else self.__class__(r,t)
|
|
212
|
+
elif callable(r):
|
|
213
|
+
try:
|
|
214
|
+
r = r(*t[:],**t.__dict__)
|
|
215
|
+
except:
|
|
216
|
+
if not (i == len(body) - 1 and len(args) == 0 and len(kwargs) == 0):
|
|
217
|
+
r = self.__class__(r,t)
|
|
218
|
+
else:
|
|
219
|
+
if not (i == len(body) - 1 and len(args) == 0 and len(kwargs) == 0):
|
|
220
|
+
r = self.__class__(r,t)
|
|
221
|
+
else:
|
|
222
|
+
r = r[key] if type(r) is self.__class__ else self.__class__(r,key)
|
|
223
|
+
#print(self[:],args,kwargs,self.__dict__,r)
|
|
224
|
+
return r
|
|
225
|
+
def __lt__(a, b):
|
|
226
|
+
return a.__class__(operator.__lt__,table(a,b))
|
|
227
|
+
def __le__(a, b):
|
|
228
|
+
return a.__class__(operator.__le__,table(a,b))
|
|
229
|
+
def __eq__(a, b):
|
|
230
|
+
return a.__class__(operator.__eq__,table(a,b))
|
|
231
|
+
def __ne__(a, b):
|
|
232
|
+
return a.__class__(operator.__ne__,table(a,b))
|
|
233
|
+
def __ge__(a, b):
|
|
234
|
+
return a.__class__(operator.__ge__,table(a,b))
|
|
235
|
+
def __gt__(a, b):
|
|
236
|
+
return a.__class__(operator.__gt__,table(a,b))
|
|
237
|
+
def __not__(a):
|
|
238
|
+
return a.__class__(operator.__not__,table(a))
|
|
239
|
+
def __abs__(a):
|
|
240
|
+
return a.__class__(operator.__abs__,table(a))
|
|
241
|
+
def __round__(a):
|
|
242
|
+
return a.__class__(round,table(a))
|
|
243
|
+
def __add__(a, b):
|
|
244
|
+
return plus(a,b)
|
|
245
|
+
def __radd__(a, b):
|
|
246
|
+
return plus(b,a)
|
|
247
|
+
def __iadd__(a, b):
|
|
248
|
+
return plus(a,b)
|
|
249
|
+
def __and__(a, b):
|
|
250
|
+
return a.__class__(operator.__and__,table(a,b))
|
|
251
|
+
def __rand__(a, b):
|
|
252
|
+
return a.__class__(operator.__and__,table(b,a))
|
|
253
|
+
def __floordiv__(a, b):
|
|
254
|
+
return a.__class__(operator.__floordiv__,table(a,b))
|
|
255
|
+
def __rfloordiv__(a, b):
|
|
256
|
+
return a.__class__(operator.__floordiv__,table(b,a))
|
|
257
|
+
def __inv__(a):
|
|
258
|
+
return a.__class__(operator.__inv__,table(a))
|
|
259
|
+
def __invert__(a):
|
|
260
|
+
return a.__class__(operator.__invert__,table(a))
|
|
261
|
+
def __lshift__(a, b):
|
|
262
|
+
return a.__class__(operator.__lshift__,table(a,b))
|
|
263
|
+
def __rlshift__(a, b):
|
|
264
|
+
return a.__class__(operator.__lshift__,table(b,a))
|
|
265
|
+
def __mod__(a, b):
|
|
266
|
+
return a.__class__(operator.__mod__,table(a,b))
|
|
267
|
+
def __rmod__(a, b):
|
|
268
|
+
return a.__class__(operator.__mod__,table(b,a))
|
|
269
|
+
def __mul__(a, b):
|
|
270
|
+
return a.__class__(operator.__mul__,table(a,b))
|
|
271
|
+
def __rmul__(a, b):
|
|
272
|
+
return a.__class__(operator.__mul__,table(b,a))
|
|
273
|
+
def __matmul__(a, b):
|
|
274
|
+
return a.__class__(operator.__matmul__,table(a,b))
|
|
275
|
+
def __rmatmul__(a, b):
|
|
276
|
+
return a.__class__(operator.__matmul__,table(b,a))
|
|
277
|
+
def __neg__(a):
|
|
278
|
+
return uminus(a)
|
|
279
|
+
def __or__(a, b):
|
|
280
|
+
return a.__class__(operator.__or__,table(a,b))
|
|
281
|
+
def __ror__(a, b):
|
|
282
|
+
return a.__class__(operator.__or__,table(b,a))
|
|
283
|
+
def __pos__(a):
|
|
284
|
+
return uplus(a)
|
|
285
|
+
def __pow__(a, b):
|
|
286
|
+
return a.__class__(operator.__pow__,table(a,b))
|
|
287
|
+
def __rpow__(a, b):
|
|
288
|
+
return a.__class__(operator.__pow__,table(b,a))
|
|
289
|
+
def __rshift__(a, b):
|
|
290
|
+
return a.__class__(operator.__rshift__,table(a,b))
|
|
291
|
+
def __rrshift__(a, b):
|
|
292
|
+
return a.__class__(operator.__rshift__,table(b,a))
|
|
293
|
+
def __sub__(a, b):
|
|
294
|
+
return minus(a,b)
|
|
295
|
+
def __rsub__(a, b):
|
|
296
|
+
return minus(b,a)
|
|
297
|
+
def __truediv__(a, b):
|
|
298
|
+
return a.__class__(operator.__truediv__,table(a,b))
|
|
299
|
+
def __rtruediv__(a, b):
|
|
300
|
+
return a.__class__(operator.__truediv__,table(b,a))
|
|
301
|
+
def __xor__(a, b):
|
|
302
|
+
return a.__class__(operator.__xor__,table(a,b))
|
|
303
|
+
def __rxor__(a, b):
|
|
304
|
+
return a.__class__(operator.__xor__,table(b,a))
|
|
305
|
+
|
|
306
|
+
sym = expr(None)
|
|
307
|
+
|
|
308
|
+
class plus_minus:
|
|
309
|
+
def __init__(self,name):
|
|
310
|
+
self._name = name
|
|
311
|
+
def __repr__(self):
|
|
312
|
+
return self._name
|
|
313
|
+
def __call__(self,*args):
|
|
314
|
+
if len(args) == 1:
|
|
315
|
+
x = args[0]
|
|
316
|
+
if self._name == 'uplus':
|
|
317
|
+
return x
|
|
318
|
+
if type(x) is expr:
|
|
319
|
+
if len(x) > 0 and x[:][0] is uminus:
|
|
320
|
+
return x[:][1][0]
|
|
321
|
+
elif len(x) > 0 and x[:][0] is plus:
|
|
322
|
+
return expr(plus,table(uminus(x[:][1][0]),uminus(x[:][1][1])))
|
|
323
|
+
else:
|
|
324
|
+
return expr(uminus,table(x))
|
|
325
|
+
return -x
|
|
326
|
+
if type(args[0]) not in (int,float,expr) or type(args[1]) not in (int,float,expr):
|
|
327
|
+
if type(args[0]) is expr or type(args[1]) is expr:
|
|
328
|
+
return expr(plus if self._name == 'plus' else minus,table(*args))
|
|
329
|
+
return args[0]+args[1] if self._name == 'plus' else args[0]-args[1]
|
|
330
|
+
atom = []
|
|
331
|
+
term = []
|
|
332
|
+
for i in range(2):
|
|
333
|
+
x = args[i]
|
|
334
|
+
sub = i == 1 and self._name == 'minus'
|
|
335
|
+
if type(x) is expr:
|
|
336
|
+
if len(x) > 0 and x[:][0] is plus:
|
|
337
|
+
t = x[:][1]
|
|
338
|
+
(term if type(t[0]) is expr else atom).append(t[0])
|
|
339
|
+
(term if type(t[1]) is expr else atom).append(-t[1] if sub else t[1])
|
|
340
|
+
else:
|
|
341
|
+
term.append(-x if sub else x)
|
|
342
|
+
else:
|
|
343
|
+
atom.append(-x if sub else x)
|
|
344
|
+
if len(atom) == 0:
|
|
345
|
+
r = 0
|
|
346
|
+
else:
|
|
347
|
+
r = sum(atom)
|
|
348
|
+
for i in term:
|
|
349
|
+
if type(r) is not expr and r == 0:
|
|
350
|
+
r = i
|
|
351
|
+
else:
|
|
352
|
+
r = expr(plus,table(r,i))
|
|
353
|
+
return r
|
|
354
|
+
|
|
355
|
+
plus = plus_minus('plus')
|
|
356
|
+
minus = plus_minus('minus')
|
|
357
|
+
uplus = plus_minus('uplus')
|
|
358
|
+
uminus = plus_minus('uminus')
|
|
359
|
+
|
|
360
|
+
class context_switch:
|
|
361
|
+
def __init__(self, ctx, tbl):
|
|
362
|
+
self.ctx = ctx
|
|
363
|
+
self.tbl = tbl
|
|
364
|
+
def __enter__(self):
|
|
365
|
+
self.top = self.ctx <= self.tbl
|
|
366
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
367
|
+
self.ctx <= self.top
|
|
368
|
+
|
|
369
|
+
class context:
|
|
370
|
+
def __init__(self,*args,**kwargs):
|
|
371
|
+
tbl = kwargs.pop('table',table)
|
|
372
|
+
object.__setattr__(self,'_tbl',tbl)
|
|
373
|
+
object.__setattr__(self,'_new',lambda:tbl(*args,**kwargs))
|
|
374
|
+
object.__setattr__(self,'_stk',[])
|
|
375
|
+
self.__enter__()
|
|
376
|
+
def __getattr__(self, key):
|
|
377
|
+
return getattr(self._stk[-1],key)
|
|
378
|
+
def __setattr__(self, key, val):
|
|
379
|
+
setattr(self._stk[-1],key,val)
|
|
380
|
+
def __getitem__(self,key):
|
|
381
|
+
return self._stk[-1][key]
|
|
382
|
+
def __setitem__(self,key,val):
|
|
383
|
+
self._stk[-1][key] = val
|
|
384
|
+
def __delitem__(self,key):
|
|
385
|
+
del self._stk[-1][key]
|
|
386
|
+
def __len__(self):
|
|
387
|
+
return len(self._stk[-1])
|
|
388
|
+
def __repr__(self):
|
|
389
|
+
return repr(self._stk[-1])
|
|
390
|
+
def __call__(self, *args, **kwargs):
|
|
391
|
+
return self._stk[-1] if len(args) == 0 and len(kwargs) == 0 else self._stk[-1](*args,**kwargs)
|
|
392
|
+
def __le__(self,val):
|
|
393
|
+
top = self._stk[-1]
|
|
394
|
+
self._stk[-1] = val
|
|
395
|
+
return top
|
|
396
|
+
def __lt__(self, other):
|
|
397
|
+
return context_switch(self, other)
|
|
398
|
+
def __enter__(self):
|
|
399
|
+
top = self._new()
|
|
400
|
+
self._stk.append(top)
|
|
401
|
+
return top
|
|
402
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
403
|
+
self._stk.pop()
|
|
404
|
+
|
|
405
|
+
class flow(table):
|
|
406
|
+
def __getitem__(self, key):
|
|
407
|
+
if type(key) is slice:
|
|
408
|
+
return super().__getitem__(key)
|
|
409
|
+
key = str(key)
|
|
410
|
+
val = self.__dict__.get(key,None)
|
|
411
|
+
if val is None:
|
|
412
|
+
val = self.__class__()
|
|
413
|
+
self.__dict__[key] = val
|
|
414
|
+
return val
|
|
415
|
+
def __getattr__(self, key):
|
|
416
|
+
return None if key.startswith('_') or key in ('compute','getdoc','size','shape') else self[key]
|
|
417
|
+
def __call__(self, *args, **kwargs):
|
|
418
|
+
if not (len(args) == 0 and len(kwargs) == 0):
|
|
419
|
+
super().append(self.__class__(*args,**kwargs))
|
|
420
|
+
return self
|
|
421
|
+
def clear(self):
|
|
422
|
+
super().clear()
|
|
423
|
+
self.__dict__.clear()
|
|
424
|
+
|
|
425
|
+
flow = context(table=flow)
|
|
426
|
+
|
|
427
|
+
class meta:
|
|
428
|
+
def __init__(self, *args):
|
|
429
|
+
self.__meta__ = args
|
|
430
|
+
def __getattr__(self, key):
|
|
431
|
+
return None if key.startswith('_') or key in ('compute','getdoc','size','shape') else self[key]
|
|
432
|
+
def __getitem__(self, key):
|
|
433
|
+
if key is None:
|
|
434
|
+
return self
|
|
435
|
+
hashable = getattr(key,'__hash__',None)
|
|
436
|
+
val = None if hashable is None else self.__dict__.get(key,None)
|
|
437
|
+
if val is None:
|
|
438
|
+
val = self.__class__()
|
|
439
|
+
val.__dict__['__meta__'] = self.__meta__ + (key,)
|
|
440
|
+
if hashable is not None:
|
|
441
|
+
self.__dict__[key] = val
|
|
442
|
+
return val
|
|
443
|
+
def __call__(self, *args, **kwargs):
|
|
444
|
+
return self.__meta__[0](*args,*self.__meta__[1:],**kwargs)
|
|
445
|
+
|
|
446
|
+
class multi(meta):
|
|
447
|
+
def __call__(self, *args, **kwargs):
|
|
448
|
+
if len(self.__meta__) == 1:
|
|
449
|
+
val = self.__class__()
|
|
450
|
+
val.__dict__['__meta__'] = self.__meta__ + args
|
|
451
|
+
return val
|
|
452
|
+
elif len(self.__meta__) == 2:
|
|
453
|
+
nodes = getattr(self.__meta__[0],'multi',None)
|
|
454
|
+
if nodes is None:
|
|
455
|
+
return self.__meta__[1](*args,**kwargs)
|
|
456
|
+
else:
|
|
457
|
+
nodes = self.__meta__[2]
|
|
458
|
+
if type(nodes) is range:
|
|
459
|
+
nodes = list(nodes)
|
|
460
|
+
if type(nodes) not in (tuple,list):
|
|
461
|
+
nodes = [nodes]
|
|
462
|
+
if len(nodes) == 0:
|
|
463
|
+
return self.__meta__[1](*args,*self.__meta__[3:],**kwargs)
|
|
464
|
+
env = self.__meta__[0]()
|
|
465
|
+
for node in nodes:
|
|
466
|
+
tbl = getattr(env,str(node),None)
|
|
467
|
+
if tbl is None:
|
|
468
|
+
with self.__meta__[0] as tbl:
|
|
469
|
+
pass
|
|
470
|
+
env[str(node)] = tbl
|
|
471
|
+
self.__meta__[0] <= tbl
|
|
472
|
+
self.__meta__[1](*args,*self.__meta__[3:],**kwargs)
|
|
473
|
+
self.__meta__[0] <= env
|
|
474
|
+
|
|
475
|
+
import ast, inspect, copy
|
|
476
|
+
|
|
477
|
+
class FindReg(ast.NodeVisitor):
|
|
478
|
+
def __init__(self, regq):
|
|
479
|
+
self.regq = regq
|
|
480
|
+
self.found = False
|
|
481
|
+
def visit_Name(self, node):
|
|
482
|
+
if self.regq(node.id):
|
|
483
|
+
self.found = True
|
|
484
|
+
|
|
485
|
+
def RegQ(node, regq):
|
|
486
|
+
visitor = FindReg(regq)
|
|
487
|
+
visitor.visit(node)
|
|
488
|
+
return visitor.found
|
|
489
|
+
|
|
490
|
+
class WithPass(ast.NodeTransformer):
|
|
491
|
+
def __init__(self, regq, env={}):
|
|
492
|
+
self.regq = regq
|
|
493
|
+
self.env = env
|
|
494
|
+
def visit_If(self, node):
|
|
495
|
+
#print(ast.dump(node))
|
|
496
|
+
self.generic_visit(node)
|
|
497
|
+
If = self.env['If']
|
|
498
|
+
if type(If) is not str:
|
|
499
|
+
If = 'If'
|
|
500
|
+
Else = self.env['Else']
|
|
501
|
+
if type(Else) is not str:
|
|
502
|
+
Else = 'Else'
|
|
503
|
+
Elif = self.env['Elif']
|
|
504
|
+
if type(Elif) is not str:
|
|
505
|
+
Elif = 'Elif'
|
|
506
|
+
if isinstance(node.test, ast.Call) and node.test.func.id == '_':
|
|
507
|
+
node.test.func.id = If
|
|
508
|
+
elif RegQ(node.test, self.regq):
|
|
509
|
+
node.test = ast.Call(func=ast.Name(id=If, ctx=ast.Load(), lineno=node.lineno, col_offset = node.col_offset), args=[node.test], keywords=[], lineno=node.lineno, col_offset = node.col_offset)
|
|
510
|
+
if isinstance(node.test, ast.Call) and node.test.func.id == If:
|
|
511
|
+
withs = [ast.With(items=[ast.withitem(context_expr = node.test)], body=node.body, lineno=node.lineno, col_offset = node.col_offset)]
|
|
512
|
+
for i in range(len(node.orelse)):
|
|
513
|
+
orelse = node.orelse[i]
|
|
514
|
+
if isinstance(orelse, ast.With) \
|
|
515
|
+
and isinstance(orelse.items[0].context_expr, ast.Call):
|
|
516
|
+
if orelse.items[0].context_expr.func.id == If:
|
|
517
|
+
orelse.items[0].context_expr.func.id = Elif
|
|
518
|
+
withs.append(orelse)
|
|
519
|
+
else:
|
|
520
|
+
orelse = ast.With(items=[\
|
|
521
|
+
ast.withitem(context_expr = \
|
|
522
|
+
ast.Call(func=ast.Name(id=Else, ctx=ast.Load(), lineno=node.lineno, col_offset = node.col_offset),\
|
|
523
|
+
args=[], keywords=[], lineno=node.lineno, col_offset = node.col_offset),\
|
|
524
|
+
lineno=node.lineno, col_offset = node.col_offset)], \
|
|
525
|
+
body=node.orelse[i:], lineno=node.lineno, col_offset = node.col_offset)
|
|
526
|
+
withs.append(orelse)
|
|
527
|
+
break
|
|
528
|
+
return withs
|
|
529
|
+
return node
|
|
530
|
+
def visit_While(self, node):
|
|
531
|
+
#print(ast.dump(node))
|
|
532
|
+
self.generic_visit(node)
|
|
533
|
+
While = self.env['While']
|
|
534
|
+
if type(While) is not str:
|
|
535
|
+
While = 'While'
|
|
536
|
+
if isinstance(node.test, ast.Name) and node.test.id == '_':
|
|
537
|
+
node.test = ast.Call(func=ast.Name(id=While, ctx=ast.Load(), lineno=node.lineno, col_offset = node.col_offset), args=[], keywords=[], lineno=node.lineno, col_offset = node.col_offset)
|
|
538
|
+
elif isinstance(node.test, ast.Call) and node.test.func.id == '_':
|
|
539
|
+
node.test.func.id = While
|
|
540
|
+
elif RegQ(node.test, self.regq):
|
|
541
|
+
node.test = ast.Call(func=ast.Name(id=While, ctx=ast.Load(), lineno=node.lineno, col_offset = node.col_offset), args=[node.test], keywords=[], lineno=node.lineno, col_offset = node.col_offset)
|
|
542
|
+
if isinstance(node.test, ast.Call) and node.test.func.id == While:
|
|
543
|
+
return ast.With(items=[ast.withitem(context_expr = node.test)], body=node.body, lineno=node.lineno, col_offset = node.col_offset)
|
|
544
|
+
return node
|
|
545
|
+
def visit_For(self, node):
|
|
546
|
+
#print(ast.dump(node))
|
|
547
|
+
self.generic_visit(node)
|
|
548
|
+
For = self.env['For']
|
|
549
|
+
if type(For) is not str:
|
|
550
|
+
For = 'For'
|
|
551
|
+
if isinstance(node.iter, ast.Call) and node.iter.func.id == '_':
|
|
552
|
+
node.iter.func.id = For
|
|
553
|
+
elif RegQ(node.target, self.regq):
|
|
554
|
+
node.iter = ast.Call(func=ast.Name(id=For, ctx=ast.Load(), lineno=node.lineno, col_offset = node.col_offset), args=[node.iter], keywords=[], lineno=node.lineno, col_offset = node.col_offset)
|
|
555
|
+
if isinstance(node.iter, ast.Call) and node.iter.func.id == For:
|
|
556
|
+
node.target.ctx = ast.Load()
|
|
557
|
+
if len(node.iter.args) == 1 and isinstance(node.iter.args[0], ast.Call) and node.iter.args[0].func.id == 'range':
|
|
558
|
+
node.iter.args[0] = ast.Tuple(node.iter.args[0].args, ctx=ast.Load(), lineno=node.lineno, col_offset = node.col_offset)
|
|
559
|
+
node.iter.args = [node.target] + node.iter.args
|
|
560
|
+
return ast.With(items=[ast.withitem(context_expr = node.iter)], body=node.body, lineno=node.lineno, col_offset = node.col_offset)
|
|
561
|
+
return node
|
|
562
|
+
def visit_Assign(self, node):
|
|
563
|
+
#print(ast.dump(node))
|
|
564
|
+
self.generic_visit(node)
|
|
565
|
+
Set = self.env['Set']
|
|
566
|
+
if type(Set) is not str:
|
|
567
|
+
Set = 'Set'
|
|
568
|
+
if isinstance(node.targets[0], ast.Name) and isinstance(node.targets[0], ast.Name) and self.regq(node.targets[0].id):
|
|
569
|
+
node.targets[0].ctx = ast.Load()
|
|
570
|
+
return ast.Expr(value=ast.Call(func=ast.Name(id=Set, ctx=ast.Load(), lineno=node.lineno, col_offset = node.col_offset), args=[node.targets[0], node.value], keywords=[], lineno=node.lineno, col_offset = node.col_offset), lineno=node.lineno, col_offset = node.col_offset)
|
|
571
|
+
return node
|
|
572
|
+
def visit_Call(self, node):
|
|
573
|
+
#print(ast.dump(node))
|
|
574
|
+
self.generic_visit(node)
|
|
575
|
+
Call = self.env['Call']
|
|
576
|
+
if type(Call) is not str:
|
|
577
|
+
Call = 'Call'
|
|
578
|
+
func = getattr(node.func, 'id', None)
|
|
579
|
+
if func is not None and self.env.get('#'+func, None) is not None:
|
|
580
|
+
return ast.Call(func=ast.Name(id=Call,ctx=ast.Load(),lineno=node.lineno,col_offset=node.col_offset),args=[ast.Constant(value=node.func.id,lineno=node.lineno,col_offset=node.col_offset)]+node.args,keywords=[],lineno=node.lineno,col_offset=node.col_offset)
|
|
581
|
+
return node
|
|
582
|
+
def visit_Return(self, node):
|
|
583
|
+
#print(ast.dump(node))
|
|
584
|
+
self.generic_visit(node)
|
|
585
|
+
Return = self.env['Return']
|
|
586
|
+
if type(Return) is not str:
|
|
587
|
+
Return = 'Return'
|
|
588
|
+
return ast.Expr(value=ast.Call(func=ast.Name(id=Return,ctx=ast.Load(),lineno=node.lineno,col_offset=node.col_offset),args=\
|
|
589
|
+
node.value.elts if type(node.value) is ast.Tuple else ([] if node.value is None else [node.value]),keywords=[],lineno=node.lineno,col_offset=node.col_offset), lineno=node.lineno, col_offset = node.col_offset)
|
|
590
|
+
|
|
591
|
+
class SubPass(ast.NodeTransformer):
|
|
592
|
+
def __init__(self, env={}):
|
|
593
|
+
self.env = env
|
|
594
|
+
self.regs = {}
|
|
595
|
+
def visit_FunctionDef(self, node):
|
|
596
|
+
#print(ast.dump(node))
|
|
597
|
+
self.regs = {'_':[]}
|
|
598
|
+
reg = -1
|
|
599
|
+
kws = len(node.args.defaults)
|
|
600
|
+
for arg in node.args.args[:(-kws or None)]:
|
|
601
|
+
if arg.annotation is None:
|
|
602
|
+
reg += 1
|
|
603
|
+
else:
|
|
604
|
+
reg = arg.annotation.value
|
|
605
|
+
self.regs['_'].append(reg)
|
|
606
|
+
arg.annotation = None
|
|
607
|
+
self.regs[arg.arg] = ast.Subscript(value=ast.Name(id='R',ctx=ast.Load(),lineno=node.lineno,col_offset=node.col_offset), \
|
|
608
|
+
slice=ast.Index(value=ast.Constant(value=reg,lineno=node.lineno,col_offset=node.col_offset)), \
|
|
609
|
+
lineno=node.lineno,col_offset=node.col_offset)
|
|
610
|
+
self.regs['_'].append(reg)
|
|
611
|
+
node.regs = self.regs['_']
|
|
612
|
+
self.generic_visit(node)
|
|
613
|
+
self.env['#'+node.name] = self.regs['_']
|
|
614
|
+
self.regs = {}
|
|
615
|
+
Func = self.env['Func']
|
|
616
|
+
if type(Func) is not str:
|
|
617
|
+
Func = 'Func'
|
|
618
|
+
node.args.args = node.args.args[-kws:] if kws else []
|
|
619
|
+
node.body = [ast.With(items=[ast.withitem(context_expr=ast.Call(func=ast.Name(id=Func,ctx=ast.Load(),lineno=node.lineno, col_offset = node.col_offset), \
|
|
620
|
+
args=[ast.Constant(value=node.name,lineno=node.lineno,col_offset=node.col_offset)]+ \
|
|
621
|
+
[ast.Constant(value=i,lineno=node.lineno,col_offset=node.col_offset) for i in node.regs], \
|
|
622
|
+
keywords=[],lineno=node.lineno,col_offset=node.col_offset))],body=node.body, lineno=node.lineno,col_offset=node.col_offset)]
|
|
623
|
+
return node
|
|
624
|
+
def visit_Name(self, node):
|
|
625
|
+
#print(ast.dump(node))
|
|
626
|
+
if node.id != '_':
|
|
627
|
+
value = self.regs.get(node.id, None)
|
|
628
|
+
if value is not None:
|
|
629
|
+
value = copy.copy(value)
|
|
630
|
+
value.ctx = node.ctx
|
|
631
|
+
return value
|
|
632
|
+
return node
|
|
633
|
+
def visit_Assign(self, node):
|
|
634
|
+
#print(ast.dump(node))
|
|
635
|
+
self.generic_visit(node)
|
|
636
|
+
if isinstance(node.targets[0], ast.Name):
|
|
637
|
+
value = self.regs.get(node.targets[0].id, None)
|
|
638
|
+
if value is not None:
|
|
639
|
+
value = copy.copy(value)
|
|
640
|
+
value.ctx = ast.Store()
|
|
641
|
+
node.targets[0] = value
|
|
642
|
+
return node
|
|
643
|
+
|
|
644
|
+
def domain(ctx={}, regq=None, sub=None, dump=False):
|
|
645
|
+
def decorator(func):
|
|
646
|
+
src = inspect.getsourcelines(func)[0]
|
|
647
|
+
indent = len(src[0]) - len(src[0].lstrip())
|
|
648
|
+
src = ''.join([line[indent:] for line in src])
|
|
649
|
+
node = ast.parse(src)
|
|
650
|
+
node.body[0].decorator_list = []
|
|
651
|
+
if sub is True:
|
|
652
|
+
node = SubPass(ctx).visit(node)
|
|
653
|
+
elif isinstance(sub, ast.NodeTransformer):
|
|
654
|
+
node = sub(ctx).visit(node)
|
|
655
|
+
elif callable(sub):
|
|
656
|
+
node = sub(node)
|
|
657
|
+
if callable(regq):
|
|
658
|
+
node = WithPass(regq,ctx).visit(node)
|
|
659
|
+
if dump:
|
|
660
|
+
unparse = getattr(ast, 'unparse', None)
|
|
661
|
+
if unparse is not None:
|
|
662
|
+
print(unparse(node))
|
|
663
|
+
env = func.__globals__.copy()
|
|
664
|
+
env.update(ctx)
|
|
665
|
+
exec(compile(node, filename='', mode='exec'), env)
|
|
666
|
+
def wrap(*args, **kwargs):
|
|
667
|
+
env.update(ctx)
|
|
668
|
+
return eval(func.__name__, env)(*args, **kwargs)
|
|
669
|
+
return wrap
|
|
670
|
+
return decorator
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oasm
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Open ASseMbly tools
|
|
5
|
+
Author-email: nzturn <nzturn@gmail.com>
|
|
6
|
+
Keywords: asm,dsl
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# Open ASseMbly tools
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
oasm/__init__.py,sha256=2Zg2kwWBs1khFXkREzyAljGuJnnqKqpNGmcmUtH3PDk,28080
|
|
2
|
+
oasm-0.1.0.dist-info/METADATA,sha256=e0zuFe5q8CkTxAMagX7hvv5XTd2UcG_hamjpeCnO4Zs,370
|
|
3
|
+
oasm-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
4
|
+
oasm-0.1.0.dist-info/top_level.txt,sha256=EacQcwgujQK1Vg--A4w6awZ2LPUTDx7kHNRd9BsavOc,5
|
|
5
|
+
oasm-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oasm
|