-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.py
228 lines (204 loc) · 5.21 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
from functools import *
def FT(key, function = lambda x: x):
print(function(key))
return key
def cando(function):
try:
function()
return True
except:
return False
def safechain(functions):
error = None
for function in functions:
try:
return function()
except TypeError as e:
error = e
except:
raise
raise error
def cast(args):
if isinstance(args, (list, tuple, set)):
try:
return type(args)(map(cast, args))
except:
try:
return map(cast, args)
except:
return f(args)
return f(args)
id = 0
fkey = []
keys = []
fval = []
vals = []
def getval(function, index):
return vals[fval.index(function)][index]
def getvalarray(function):
return vals[fval.index(function)]
def getkey(function):
return keys[fkey.index(function)]
def haskey(function):
return any(key == function for key in fkey)
def call(func, *args, **kwargs):
if isinstance(func, (list, tuple, set)):
return type(func)(call(f, *args, **kwargs) for f in func)
return func(*args, **kwargs)
funcskey = []
funcsval = []
def getfunction(function, cast = True, cache = False, partial = False):
try:
return funcsval[funcskey.index(function)]
except:
func = Function(function, cast, cache, partial)
funcskey.append(function)
funcsval.append(func)
return func
class _splat:
def __init__(self, array):
self.array = array
def __iter__(self):
return iter(self.array)
def splat(obj):
if hasattr(obj, '__iter__'):
return _splat(obj)
return obj
def determine_arguments(array):
result = []
for element in array:
if isinstance(element, _splat):
result += determine_arguments(element.array)
else:
result.append(element)
return result
class Function:
def __init__(self, function, cast = True, cache = False, partial = False):
global id
self.function = function
self.cast = cast
self.cache = cache
self.partial = partial
self.id = id
id += 1
if not haskey(self.function):
fkey.append(self.function)
keys.append([])
fval.append(self.function)
vals.append([])
def __rshift__(self, other):
return Function(lambda *args, **kwargs: call(other, *((call(self.function, *args, **kwargs),) + args), **kwargs))
def __lshift__(self, other):
return Function(lambda *args, **kwargs: call(self.function, *(args + (call(other, *args, **kwargs),)), **kwargs))
def __and__(self, other):
return Function(lambda *args, **kwargs: self.function(*(args + (other,)), **kwargs), self.cast, self.cache and other.cache)
def __rand__(self, other):
return Function(lambda *args, **kwargs: self.function(other, *args, **kwargs), self.cast, self.cache and other.cache)
def __rtruediv__(self, other):
return reduce(self, other)
def __call__(self, *args, **kwargs):
if self.cast: args = cast(args)
args = determine_arguments(args)
if self.cache and (args, kwargs) in getkey(self.function):
return getval(self.function, getkey(self.function).index((args, kwargs)))
else:
if isinstance(args, map): args = list(args)
result = self.function(*args, **kwargs)
if self.cache:
getkey(self.function).append((args, kwargs))
getvalarray(self.function).append(result)
return result
def __add__(self, other):
other = f(other)
def inner(*args, **kwargs):
return other(self(*args, **kwargs))
return Function(inner)
def __rmul__(self, times):
return self * times
def __mul__(self, times):
times = f(times)
if isinstance(times, Function):
def inner(*args, **kwargs):
value = self(*args, **kwargs)
while not times(value):
value = self(value, *(args[1:]), **kwargs)
return value
return inner
if times == 0: return lambda *args, **kwargs: args[0] if len(args) == 1 else args
if times == 1: return self
if times == 2: return self + self
return self + self * (times - 1)
def setCaching(self, cache):
self.cache = cache
return self
def wipeCache(self):
keys[fkey.index(self.function)] = []
vals[fkey.index(self.function)] = []
return self
def setPartial(self, partial):
self.partial = partial
IDENT = None
EVALP = None
def setident(ident):
global IDENT
IDENT = ident
def setevalp(evalp):
global EVALP
EVALP = evalp
def g(x):
if isinstance(x, (type(type), type(print), type(lambda: 0))):
return Function(x)
else:
return x
def f(x):
if isinstance(x, IDENT):
return g(x())
elif hasattr(x, '__iter__') and not isinstance(x, str):
try:
return type(x)(map(f, x))
except:
return g(x)
else:
return g(x)
def h(x):
if not isinstance(x, str): return x
result = ''
index = 0
while index < len(x):
if x[index] == '\\':
result += eval('"\\' + x[index + 1] + '"')
index += 1
elif x[index] == '#':
if x[index + 1] == '{':
string = ''
index += 2
while x[index] != '}':
if x[index] == '\\':
string += x[index + 1]
index += 1
else:
string += x[index]
index += 1
result += str(EVALP(string))
else:
result += '#'
else:
result += x[index]
index += 1
return result
def make_type(dict):
funcs = {}
other = {}
for key in dict:
value = dict[key]
if isinstance(value, Function):
funcs[key] = value
else:
other[key] = value
class InnerType:
def __init__(self):
for key in other:
self.__setattr__(key, other[key])
for key in funcs:
setattr(InnerType, key, dict[key])
return InnerType()