|
@@ -74,20 +74,27 @@ class Turmit(object):
|
74
|
74
|
if self._prog is None:
|
75
|
75
|
self._prog = RpnExpr.random(self._prog_sz)
|
76
|
76
|
|
77
|
|
- self.__expr_fun = lambda *args, **kwargs: (0,)
|
|
77
|
+ self._determin_score = 5
|
|
78
|
+
|
|
79
|
+ self.__expr_fun = lambda *args, **kwargs: (0, True, None)
|
78
|
80
|
|
79
|
81
|
def __call__(self, **context):
|
80
|
82
|
''' @brief Exec the RPN expression and return the stack head
|
81
|
83
|
@param context dict : dict with variable values (see @ref rpnlib._var_list)
|
82
|
84
|
@return stack head after RPN
|
83
|
85
|
'''
|
84
|
|
- context = {k:int(context[k]) % self._max_int for k in context}
|
|
86
|
+ context = {k:IntVar(context[k]) % self._max_int for k in context}
|
85
|
87
|
|
86
|
88
|
if self.__expr_fun is None:
|
87
|
89
|
self._compile()
|
88
|
90
|
ret = self.__expr_fun(self, **context)
|
89
|
|
- if isinstance(ret, int):
|
|
91
|
+
|
|
92
|
+ determinist = ret[1]
|
|
93
|
+
|
|
94
|
+ if len(ret) == 2:
|
|
95
|
+ ret = ret[0]
|
90
|
96
|
return ret
|
|
97
|
+ #if len(ret) == 3 -> returned a continuation address in RPN expr
|
91
|
98
|
|
92
|
99
|
#self.__ip = 0
|
93
|
100
|
self.__ip = ret[0]
|
|
@@ -97,14 +104,29 @@ class Turmit(object):
|
97
|
104
|
if sym.optype == RpnSymbol.VALUE:
|
98
|
105
|
self._push(sym.value)
|
99
|
106
|
elif sym.optype == RpnSymbol.VARIABLE:
|
100
|
|
- self._push(context[sym.value.lower()])
|
|
107
|
+ self._push(IntVar(context[sym.value.lower()]))
|
101
|
108
|
elif sym.optype == RpnSymbol.OPERATION:
|
102
|
|
- getattr(self, sym.value.lower())()
|
|
109
|
+ op = getattr(self, sym.value.lower())
|
|
110
|
+ if determinist:
|
|
111
|
+ if not op():
|
|
112
|
+ determinist = False
|
|
113
|
+ else:
|
|
114
|
+ op()
|
103
|
115
|
self.__ip += 1
|
|
116
|
+
|
|
117
|
+ self._determin_score += 0 if determinist else 1
|
104
|
118
|
return self.shead
|
105
|
119
|
|
106
|
120
|
def _compile(self):
|
107
|
|
- code = 'def expr_fun(self, x, y, r, g, b):\n'
|
|
121
|
+ code = '''def expr_fun(self, x, y, r, g, b):
|
|
122
|
+
|
|
123
|
+ determinist = True'''
|
|
124
|
+
|
|
125
|
+ op2_head = '''a = self._stack[self._cur]
|
|
126
|
+ self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
127
|
+ if isinstance(a, IntVar) or isinstance(self._stack[self._cur], IntVar):
|
|
128
|
+ determinist = False
|
|
129
|
+'''
|
108
|
130
|
for ip, sym in enumerate(self._prog):
|
109
|
131
|
if sym.optype == RpnSymbol.VALUE:
|
110
|
132
|
code += '''
|
|
@@ -120,73 +142,65 @@ class Turmit(object):
|
120
|
142
|
''' % sym.value.lower()
|
121
|
143
|
elif sym.value == 'add':
|
122
|
144
|
code += '''
|
123
|
|
- a = self._stack[self._cur]
|
124
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
145
|
+ %s
|
125
|
146
|
self._stack[self._cur] += a
|
126
|
147
|
self._stack[self._cur] %= self._max_int
|
127
|
|
-'''
|
|
148
|
+''' % op2_head
|
128
|
149
|
elif sym.value == 'sub':
|
129
|
150
|
code += '''
|
130
|
|
- a = self._stack[self._cur]
|
131
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
151
|
+ %s
|
132
|
152
|
self._stack[self._cur] = self._stack[self._cur] - a
|
133
|
153
|
if self._stack[self._cur] < 0:
|
134
|
154
|
self._stack[self._cur] += self._max_int
|
135
|
|
-'''
|
|
155
|
+''' % op2_head
|
136
|
156
|
elif sym.value == 'mul':
|
137
|
157
|
code += '''
|
138
|
|
- a = self._stack[self._cur]
|
139
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
158
|
+ %s
|
140
|
159
|
self._stack[self._cur] *= a
|
141
|
160
|
self._stack[self._cur] %= self._max_int
|
142
|
|
-'''
|
|
161
|
+''' % op2_head
|
143
|
162
|
elif sym.value == 'div':
|
144
|
163
|
code += '''
|
145
|
|
- a = self._stack[self._cur]
|
146
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
164
|
+ %s
|
147
|
165
|
if a != 0:
|
148
|
166
|
self._stack[self._cur] = self._stack[self._cur] // a
|
149
|
|
-'''
|
|
167
|
+''' % op2_head
|
150
|
168
|
elif sym.value == 'mod':
|
151
|
169
|
code += '''
|
152
|
|
- a = self._stack[self._cur]
|
153
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
170
|
+ %s
|
154
|
171
|
if a != 0:
|
155
|
172
|
self._stack[self._cur] = self._stack[self._cur] % a
|
156
|
|
-'''
|
|
173
|
+''' % op2_head
|
157
|
174
|
elif sym.value == 'bin_and':
|
158
|
175
|
code += '''
|
159
|
|
- a = self._stack[self._cur]
|
160
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
176
|
+ %s
|
161
|
177
|
self._stack[self._cur] &= a
|
162
|
|
-'''
|
|
178
|
+''' % op2_head
|
163
|
179
|
elif sym.value == 'bin_or':
|
164
|
180
|
code += '''
|
165
|
|
- a = self._stack[self._cur]
|
166
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
181
|
+ %s
|
167
|
182
|
self._stack[self._cur] |= a
|
168
|
|
-'''
|
|
183
|
+''' % op2_head
|
169
|
184
|
elif sym.value == 'bin_xor':
|
170
|
185
|
code += '''
|
171
|
|
- a = self._stack[self._cur]
|
172
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
186
|
+ %s
|
173
|
187
|
self._stack[self._cur] ^= a
|
174
|
|
-'''
|
|
188
|
+''' % op2_head
|
175
|
189
|
elif sym.value == 'lshift':
|
176
|
190
|
code += '''
|
177
|
|
- a = self._stack[self._cur]
|
178
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
191
|
+ %s
|
179
|
192
|
self._stack[self._cur] = (self._stack[self._cur] << a) % self._max_int
|
180
|
|
-'''
|
|
193
|
+''' % op2_head
|
181
|
194
|
elif sym.value == 'rshift':
|
182
|
195
|
code += '''
|
183
|
|
- a = self._stack[self._cur]
|
184
|
|
- self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
|
|
196
|
+ %s
|
185
|
197
|
self._stack[self._cur] = self._stack[self._cur] >> a
|
186
|
|
-'''
|
|
198
|
+''' % op2_head
|
187
|
199
|
elif sym.value == 'dup':
|
188
|
200
|
code += '''
|
189
|
201
|
a = self._stack[self._cur]
|
|
202
|
+ if isinstance(a, IntVar):
|
|
203
|
+ determinist = False
|
190
|
204
|
self._cur += 1
|
191
|
205
|
self._cur %= len(self._stack)
|
192
|
206
|
self._stack[self._cur] = a
|
|
@@ -197,10 +211,10 @@ class Turmit(object):
|
197
|
211
|
'''
|
198
|
212
|
else:
|
199
|
213
|
code += '''
|
200
|
|
- return (%d,)
|
|
214
|
+ return (%d,determinist, None)
|
201
|
215
|
''' % ip
|
202
|
216
|
code += '''
|
203
|
|
- return self._stack[self._cur]
|
|
217
|
+ return (self._stack[self._cur], determinist)
|
204
|
218
|
'''
|
205
|
219
|
g = {}
|
206
|
220
|
l = {}
|
|
@@ -245,12 +259,13 @@ class Turmit(object):
|
245
|
259
|
@param val int : integer to transform
|
246
|
260
|
@return integer
|
247
|
261
|
'''
|
|
262
|
+ intvar = isinstance(val, IntVar)
|
248
|
263
|
val = int(val)
|
249
|
264
|
if self._max_int is not None:
|
250
|
265
|
val %= self._max_int
|
251
|
266
|
if not self._signed_int and val < 0:
|
252
|
267
|
val = self._max_int - val
|
253
|
|
- return val
|
|
268
|
+ return IntVar(val) if intvar else val
|
254
|
269
|
|
255
|
270
|
@RpnOp
|
256
|
271
|
def mem_sz(self, new_sz):
|
|
@@ -295,7 +310,7 @@ class Turmit(object):
|
295
|
310
|
'''
|
296
|
311
|
return a & b
|
297
|
312
|
|
298
|
|
- @RpnOp
|
|
313
|
+ @RpnOpNoMod
|
299
|
314
|
def dup(self, a):
|
300
|
315
|
''' @brief Duplicates stack head
|
301
|
316
|
@param a int : value
|
|
@@ -359,14 +374,14 @@ class Turmit(object):
|
359
|
374
|
'''
|
360
|
375
|
return a ^ b
|
361
|
376
|
|
362
|
|
- @RpnOp
|
|
377
|
+ @RpnOpNoMod
|
363
|
378
|
def pop(self, a):
|
364
|
379
|
''' @brief Pops a, head of the stack
|
365
|
380
|
@param a int : value
|
366
|
381
|
'''
|
367
|
382
|
pass
|
368
|
383
|
|
369
|
|
- @RpnOp
|
|
384
|
+ @RpnOpNoMod
|
370
|
385
|
def swp(self, a, b):
|
371
|
386
|
''' @brief Swap the two values on top of the stack
|
372
|
387
|
@param a int : v1
|