Skip to content

Commit ccfa1d0

Browse files
committed
new bind implementation; instanceof
1 parent 32069fb commit ccfa1d0

File tree

8 files changed

+297
-335
lines changed

8 files changed

+297
-335
lines changed

aos/aos.py

+4-9
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,11 @@ class AOShape(NamedTuple):
7878
'*': AOop.SEQUENCE
7979
}
8080

81+
def is_dim(self):
82+
return self.dim is not None
83+
8184
def get_dim_name(self):
82-
assert self.dim is not None
85+
assert self.is_dim()
8386
return self.dim.name.strip()
8487

8588

@@ -235,14 +238,6 @@ def get_or_decl_dims(names):
235238
else: return res
236239

237240

238-
def show_dims(names):
239-
names = names.strip().split(' ')
240-
res = [str(DimSymbol.lookup(name)) for name in names]
241-
return '\n'.join(res)
242-
243-
244-
245-
246241

247242

248243

aos/bind.py

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import sys
2+
from collections import defaultdict
3+
4+
from .aos import AOShape, AOop, AOConst
5+
from .dim import DimSymbol, ContinuousDim, CategoricalDim, Dim
6+
from .dim import is_dim_or_scalar
7+
from .common import AndTuple, II, Config
8+
9+
DEBUG = Config.DEBUG
10+
11+
class BindError(str):
12+
def __str__(self):
13+
return f'<Error>: {repr(self)}'
14+
15+
class Bind:
16+
def __init__(self, name: 'variable' = None, v: 'value' = None, subst=None ):
17+
# value from object
18+
# name from shape
19+
if subst is not None:
20+
self.subst = subst
21+
elif (name is not None and v is not None):
22+
self.subst = {name: [v]}
23+
else:
24+
self.subst = defaultdict(list)
25+
26+
def keys(self):
27+
return self.subst.keys()
28+
29+
@staticmethod
30+
def disj_union(binds):
31+
subst = defaultdict(list)
32+
for b in binds:
33+
keys = list(b.keys())
34+
if DEBUG: print(keys, subst.keys())
35+
assert not any([k in subst for k in keys])
36+
subst.update(b.subst)
37+
return Bind(subst=subst)
38+
39+
40+
@staticmethod
41+
def multi_union(binds):
42+
b = binds[0]
43+
subst = defaultdict(list)
44+
45+
for b in binds[1:]:
46+
keys = list(b.keys())
47+
if len(subst) > 0:
48+
assert len(keys) == sum([k in subst for k in keys])
49+
for k in keys:
50+
subst[k].extend(b.subst[k])
51+
return Bind(subst=subst)
52+
53+
def __str__(self):
54+
res = str(self.subst)
55+
return res
56+
57+
58+
59+
class TryBind:
60+
#TODO: slot for the fields
61+
def __init__(self, o: 'obj', s: 'aos'):
62+
self.o = o #obj
63+
self.s = s #shape ! (shape)*
64+
#self.op = s.op
65+
66+
#def len_match(self):
67+
# return (len(self.o) == len(self.s.args))
68+
69+
def build_matching_pairs(self):
70+
#only ordered (non-commutative) trials
71+
o = self.o
72+
# assert o is an iterator
73+
74+
args: '(shape)*'
75+
76+
if II(self.s, list):
77+
args = self.s
78+
else: args = self.s.args
79+
80+
args_len = len(args)
81+
82+
if len(o) < args_len:
83+
return BindError(f'build_matching_pairs: {self.o}, {args}')
84+
else:
85+
rest_o_len = len(o) - args_len
86+
87+
88+
tbs = [TryBind(o_, arg) for o_, arg in zip(o[:args_len-1], args[:-1])]
89+
#last arg binds to rest o sub-objects
90+
rest_o = o[args_len-1:] if rest_o_len > 1 else o[-1]
91+
tb_last = TryBind(rest_o, args[-1])
92+
tbs.append(tb_last)
93+
return tbs
94+
95+
def __repr__(self):
96+
return f'{self.o} :-? {self.s}'
97+
def __str__(self):
98+
return f'{self.o} :-? {self.s}'
99+
100+
101+
102+
103+
def combine_binds (op, binds: '(Bind | BindError)*' ):
104+
err = list(filter(lambda x: II(x, BindError), binds))
105+
if len(err) > 0:
106+
return BindError(', '.join(err))
107+
108+
if op == AOop.OR:
109+
res = Bind.disj_union(binds)
110+
elif op == AOop.AND:
111+
res = Bind.disj_union(binds)
112+
elif op == AOop.SEQUENCE:
113+
res = Bind.multi_union(binds)
114+
else:
115+
assert False, f'combine_binds: op = {op}'
116+
117+
return res
118+
119+
def split_try_bind(op, tb, obinder):
120+
if op == AOop.OR:
121+
res = obinder.bind_or(tb)
122+
elif op == AOop.AND:
123+
res = obinder.bind_and(tb)
124+
elif op == AOop.SEQUENCE:
125+
res = obinder.bind_star(tb)
126+
else:
127+
assert False, 'cant split op = {op}'
128+
129+
res: 'list(TryBind) | BindErr'
130+
if DEBUG:
131+
print(f'> split_try_bind: {op}, {tb} \n\t {res}')
132+
return res
133+
134+
def try_bind (tb, obinder):
135+
op = tb.s.op
136+
if op is None: #terminal
137+
res: 'Bind ! BindErr' = obinder.bind_terminal(tb)
138+
else:
139+
#split tb
140+
tbs = split_try_bind(op, tb, obinder)
141+
if II(tbs, BindError):
142+
return tbs
143+
# apply
144+
res = [try_bind(tb, obinder) for tb in tbs]
145+
res: '(Bind | BindError)*'
146+
147+
# combine
148+
res = combine_binds(op, res)
149+
if DEBUG: print(f'> try_bind: {tb}, {res}')
150+
return res
151+
152+
153+
'''
154+
155+
x :(ISIN | name | r1), y : (name | r2)
156+
y[ISIN] = y [(name & n* ) | ...], x[(name & n2*) | (ISIN & i*) | ...], n == n2 -> (n, i)*
157+
158+
'''
159+
160+
161+
162+
163+
164+
165+
166+
167+
168+
169+

aos/bind_matchers.py

-183
This file was deleted.

0 commit comments

Comments
 (0)