lean-python 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.
- lean_python/__init__.py +6 -0
- lean_python/cli.py +50 -0
- lean_python/embed.py +131 -0
- lean_python/io.py +15 -0
- lean_python/io_externs.py +1192 -0
- lean_python/marshal.py +727 -0
- lean_python/models.py +297 -0
- lean_python/runtime.py +1400 -0
- lean_python/sync.py +265 -0
- lean_python/types.py +33 -0
- lean_python-0.1.0.dist-info/METADATA +231 -0
- lean_python-0.1.0.dist-info/RECORD +15 -0
- lean_python-0.1.0.dist-info/WHEEL +4 -0
- lean_python-0.1.0.dist-info/entry_points.txt +2 -0
- lean_python-0.1.0.dist-info/licenses/LICENSE +202 -0
lean_python/runtime.py
ADDED
|
@@ -0,0 +1,1400 @@
|
|
|
1
|
+
"""Runtime of the Python code generated by lean-python.
|
|
2
|
+
|
|
3
|
+
The functions named ``lean_*`` (and the libm names) are the C names of Lean's externs and
|
|
4
|
+
follow ``lean.h``: arguments marked borrowed there are not consumed, results are owned.
|
|
5
|
+
|
|
6
|
+
Values:
|
|
7
|
+
|
|
8
|
+
- ``Nat``, ``Int``, boxed scalars and fixed-width integers are ``int``; ``Float`` and
|
|
9
|
+
``Float32`` are ``float``; ``String`` is ``bytes`` holding UTF-8.
|
|
10
|
+
- A constructor without fields is its tag (an ``int``); other constructors are ``Ctor``.
|
|
11
|
+
- ``Array``, ``ByteArray`` and ``FloatArray`` are ``LArray``, ``LByteArray``, ``LFloatArray``.
|
|
12
|
+
- ``Ctor`` and the arrays carry a reference count ``rc``, maintained by the ``inc``/``dec``
|
|
13
|
+
instructions of the IR, so updates of uniquely referenced values happen in place as in C.
|
|
14
|
+
Closures, thunks, tasks and references do not carry one: values read out of them are
|
|
15
|
+
always counted as shared.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import importlib
|
|
19
|
+
import math
|
|
20
|
+
import struct
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
PERSISTENT = 1 << 62
|
|
24
|
+
|
|
25
|
+
sys.setrecursionlimit(1_000_000)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Ctor:
|
|
29
|
+
__slots__ = ("objs", "rc", "sc", "tag")
|
|
30
|
+
|
|
31
|
+
def __init__(self, tag, objs):
|
|
32
|
+
self.tag = tag
|
|
33
|
+
self.rc = 1
|
|
34
|
+
self.objs = objs
|
|
35
|
+
self.sc = {}
|
|
36
|
+
|
|
37
|
+
def __repr__(self):
|
|
38
|
+
return f"Ctor({self.tag}, {self.objs!r}, {self.sc!r})"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class LArray:
|
|
42
|
+
__slots__ = ("data", "rc")
|
|
43
|
+
|
|
44
|
+
def __init__(self, data):
|
|
45
|
+
self.rc = 1
|
|
46
|
+
self.data = data
|
|
47
|
+
|
|
48
|
+
def __repr__(self):
|
|
49
|
+
return f"LArray({self.data!r})"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class LByteArray:
|
|
53
|
+
__slots__ = ("data", "rc")
|
|
54
|
+
|
|
55
|
+
def __init__(self, data):
|
|
56
|
+
self.rc = 1
|
|
57
|
+
self.data = data
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class LFloatArray:
|
|
61
|
+
__slots__ = ("data", "rc")
|
|
62
|
+
|
|
63
|
+
def __init__(self, data):
|
|
64
|
+
self.rc = 1
|
|
65
|
+
self.data = data
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Closure:
|
|
69
|
+
__slots__ = ("arity", "fixed", "fn")
|
|
70
|
+
|
|
71
|
+
def __init__(self, fn, arity, fixed):
|
|
72
|
+
self.fn = fn
|
|
73
|
+
self.arity = arity
|
|
74
|
+
self.fixed = fixed
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Thunk:
|
|
78
|
+
__slots__ = ("done", "fn", "value")
|
|
79
|
+
|
|
80
|
+
def __init__(self, fn, value=None, done=False):
|
|
81
|
+
self.fn = fn
|
|
82
|
+
self.value = value
|
|
83
|
+
self.done = done
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Task:
|
|
87
|
+
__slots__ = ("value",)
|
|
88
|
+
|
|
89
|
+
def __init__(self, value):
|
|
90
|
+
self.value = value
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class Ref:
|
|
94
|
+
__slots__ = ("value",)
|
|
95
|
+
|
|
96
|
+
def __init__(self, value):
|
|
97
|
+
self.value = value
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
_RC = (Ctor, LArray, LByteArray, LFloatArray)
|
|
101
|
+
|
|
102
|
+
# Classes of external objects with a reference count, and what to do when it reaches 0.
|
|
103
|
+
_FINALIZERS = {}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def register_external(cls, finalize):
|
|
107
|
+
global _RC
|
|
108
|
+
_RC = (*_RC, cls)
|
|
109
|
+
_FINALIZERS[cls] = finalize
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# ---------------------------------------------------------------------------
|
|
113
|
+
# Reference counting
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def lean_inc(x):
|
|
117
|
+
if x.__class__ in _RC:
|
|
118
|
+
x.rc += 1
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def lean_inc_n(x, n):
|
|
122
|
+
if x.__class__ in _RC:
|
|
123
|
+
x.rc += n
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def lean_inc_ret(x):
|
|
127
|
+
if x.__class__ in _RC:
|
|
128
|
+
x.rc += 1
|
|
129
|
+
return x
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def lean_dec(x):
|
|
133
|
+
if x.__class__ in _RC:
|
|
134
|
+
x.rc -= 1
|
|
135
|
+
if x.rc == 0:
|
|
136
|
+
_free(x)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _free(x):
|
|
140
|
+
stack = [x]
|
|
141
|
+
while stack:
|
|
142
|
+
o = stack.pop()
|
|
143
|
+
if o.__class__ is Ctor:
|
|
144
|
+
children = o.objs
|
|
145
|
+
elif o.__class__ is LArray:
|
|
146
|
+
children = o.data
|
|
147
|
+
else:
|
|
148
|
+
fin = _FINALIZERS.get(o.__class__)
|
|
149
|
+
if fin is not None:
|
|
150
|
+
fin(o)
|
|
151
|
+
continue
|
|
152
|
+
for c in children:
|
|
153
|
+
if c.__class__ in _RC:
|
|
154
|
+
c.rc -= 1
|
|
155
|
+
if c.rc == 0:
|
|
156
|
+
stack.append(c)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def lean_is_exclusive(x):
|
|
160
|
+
return x.__class__ in _RC and x.rc == 1
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def lean_is_shared(x):
|
|
164
|
+
return not (x.__class__ in _RC and x.rc == 1)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def lean_mark_persistent(x):
|
|
168
|
+
stack = [x]
|
|
169
|
+
while stack:
|
|
170
|
+
o = stack.pop()
|
|
171
|
+
if o.__class__ is Ctor:
|
|
172
|
+
if o.rc != PERSISTENT:
|
|
173
|
+
o.rc = PERSISTENT
|
|
174
|
+
stack.extend(o.objs)
|
|
175
|
+
elif o.__class__ is LArray:
|
|
176
|
+
if o.rc != PERSISTENT:
|
|
177
|
+
o.rc = PERSISTENT
|
|
178
|
+
stack.extend(o.data)
|
|
179
|
+
elif o.__class__ in _RC:
|
|
180
|
+
o.rc = PERSISTENT
|
|
181
|
+
return x
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def lean_obj_tag(x):
|
|
185
|
+
if isinstance(x, int):
|
|
186
|
+
return x
|
|
187
|
+
return x.tag
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def lean_reset(y, n):
|
|
191
|
+
if y.__class__ is Ctor and y.rc == 1:
|
|
192
|
+
objs = y.objs
|
|
193
|
+
for i in range(n):
|
|
194
|
+
lean_dec(objs[i])
|
|
195
|
+
return y
|
|
196
|
+
lean_dec(y)
|
|
197
|
+
return 0
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def lean_reuse(y, tag, upd, objs):
|
|
201
|
+
if isinstance(y, int):
|
|
202
|
+
return Ctor(tag, objs)
|
|
203
|
+
y.objs = objs
|
|
204
|
+
if upd:
|
|
205
|
+
y.tag = tag
|
|
206
|
+
return y
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
# ---------------------------------------------------------------------------
|
|
210
|
+
# Panics
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _eprint(msg):
|
|
214
|
+
sys.stdout.flush()
|
|
215
|
+
sys.stderr.write(msg + "\n")
|
|
216
|
+
sys.stderr.flush()
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _panic(msg):
|
|
220
|
+
_eprint(msg)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def lean_panic_fn(default, msg):
|
|
224
|
+
_panic(_s(msg))
|
|
225
|
+
return default
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def lean_panic_fn_borrowed(default, msg):
|
|
229
|
+
lean_inc(default)
|
|
230
|
+
_panic(_s(msg))
|
|
231
|
+
return default
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def lean_internal_panic(msg):
|
|
235
|
+
_eprint(f"INTERNAL PANIC: {msg}")
|
|
236
|
+
sys.exit(1)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def lean_internal_panic_unreachable():
|
|
240
|
+
lean_internal_panic("unreachable code has been reached")
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def lean_dbg_trace(msg, fn):
|
|
244
|
+
_eprint(_s(msg))
|
|
245
|
+
return lean_apply(fn, [0])
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def lean_dbg_trace_if_shared(s, a):
|
|
249
|
+
if lean_is_shared(a):
|
|
250
|
+
_eprint(f"shared RC {_s(s)}")
|
|
251
|
+
return a
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
# ---------------------------------------------------------------------------
|
|
255
|
+
# Closures
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def lean_apply(f, args):
|
|
259
|
+
while True:
|
|
260
|
+
fixed = f.fixed
|
|
261
|
+
for a in fixed:
|
|
262
|
+
lean_inc(a)
|
|
263
|
+
need = f.arity - len(fixed)
|
|
264
|
+
n = len(args)
|
|
265
|
+
if n < need:
|
|
266
|
+
return Closure(f.fn, f.arity, fixed + args)
|
|
267
|
+
if n == need:
|
|
268
|
+
return f.fn(*fixed, *args)
|
|
269
|
+
r = f.fn(*fixed, *args[:need])
|
|
270
|
+
args = args[need:]
|
|
271
|
+
f = r
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def lean_py_extern(module, attr):
|
|
275
|
+
return getattr(importlib.import_module(module), attr)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
# ---------------------------------------------------------------------------
|
|
279
|
+
# Lists
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _list_to_py(xs):
|
|
283
|
+
out = []
|
|
284
|
+
while xs.__class__ is Ctor:
|
|
285
|
+
out.append(xs.objs[0])
|
|
286
|
+
xs = xs.objs[1]
|
|
287
|
+
return out
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _py_to_list(items):
|
|
291
|
+
r = 0
|
|
292
|
+
for x in reversed(items):
|
|
293
|
+
r = Ctor(1, [x, r])
|
|
294
|
+
return r
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
# ---------------------------------------------------------------------------
|
|
298
|
+
# Nat and Int
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def lean_nat_add(a, b):
|
|
302
|
+
return a + b
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def lean_nat_sub(a, b):
|
|
306
|
+
return a - b if a > b else 0
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def lean_nat_mul(a, b):
|
|
310
|
+
return a * b
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def lean_nat_div(a, b):
|
|
314
|
+
return a // b if b else 0
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def lean_nat_mod(a, b):
|
|
318
|
+
return a % b if b else a
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def lean_nat_pow(a, b):
|
|
322
|
+
return a**b
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def lean_nat_gcd(a, b):
|
|
326
|
+
return math.gcd(a, b)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def lean_nat_lcm(a, b):
|
|
330
|
+
return math.lcm(a, b)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def lean_nat_log2(a):
|
|
334
|
+
return a.bit_length() - 1 if a > 0 else 0
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def lean_nat_land(a, b):
|
|
338
|
+
return a & b
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def lean_nat_lor(a, b):
|
|
342
|
+
return a | b
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def lean_nat_lxor(a, b):
|
|
346
|
+
return a ^ b
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def lean_nat_shiftl(a, b):
|
|
350
|
+
return a << b
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
def lean_nat_shiftr(a, b):
|
|
354
|
+
return a >> b
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def lean_nat_dec_eq(a, b):
|
|
358
|
+
return a == b
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def lean_nat_dec_lt(a, b):
|
|
362
|
+
return a < b
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def lean_nat_dec_le(a, b):
|
|
366
|
+
return a <= b
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def lean_nat_pred(a):
|
|
370
|
+
return a - 1 if a > 0 else 0
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def lean_nat_succ(a):
|
|
374
|
+
return a + 1
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def lean_nat_to_int(a):
|
|
378
|
+
return a
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
def lean_nat_abs(a):
|
|
382
|
+
return -a if a < 0 else a
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def lean_int_neg_succ_of_nat(a):
|
|
386
|
+
return -a - 1
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def lean_int_to_nat(a):
|
|
390
|
+
return max(0, a)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def lean_int_neg(a):
|
|
394
|
+
return -a
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def lean_int_add(a, b):
|
|
398
|
+
return a + b
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def lean_int_sub(a, b):
|
|
402
|
+
return a - b
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
def lean_int_mul(a, b):
|
|
406
|
+
return a * b
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def lean_int_div(a, b):
|
|
410
|
+
if b == 0:
|
|
411
|
+
return 0
|
|
412
|
+
q = abs(a) // abs(b)
|
|
413
|
+
return q if (a < 0) == (b < 0) else -q
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def lean_int_mod(a, b):
|
|
417
|
+
if b == 0:
|
|
418
|
+
return a
|
|
419
|
+
r = abs(a) % abs(b)
|
|
420
|
+
return -r if a < 0 else r
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def lean_int_ediv(a, b):
|
|
424
|
+
if b == 0:
|
|
425
|
+
return 0
|
|
426
|
+
r = a % abs(b)
|
|
427
|
+
return (a - r) // b
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def lean_int_emod(a, b):
|
|
431
|
+
if b == 0:
|
|
432
|
+
return a
|
|
433
|
+
return a % abs(b)
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
def lean_int_dec_eq(a, b):
|
|
437
|
+
return a == b
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def lean_int_dec_lt(a, b):
|
|
441
|
+
return a < b
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
def lean_int_dec_le(a, b):
|
|
445
|
+
return a <= b
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def lean_int_dec_nonneg(a):
|
|
449
|
+
return a >= 0
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def lean_int_pow(a, b):
|
|
453
|
+
return a**b
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
def lean_int_land(a, b):
|
|
457
|
+
return a & b
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def lean_int_lor(a, b):
|
|
461
|
+
return a | b
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def lean_int_xor(a, b):
|
|
465
|
+
return a ^ b
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def lean_int_shift_right(a, b):
|
|
469
|
+
return a >> b
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def lean_cstr_to_nat(s):
|
|
473
|
+
return int(s)
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
def lean_big_usize_to_nat(a):
|
|
477
|
+
return a
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def lean_usize_to_nat(a):
|
|
481
|
+
return a
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def lean_unsigned_to_nat(a):
|
|
485
|
+
return a
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
def lean_system_platform_nbits(_unit=0):
|
|
489
|
+
return 64
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
# ---------------------------------------------------------------------------
|
|
493
|
+
# Fixed-width integers
|
|
494
|
+
|
|
495
|
+
_WIDTHS = {"uint8": 8, "uint16": 16, "uint32": 32, "uint64": 64, "usize": 64}
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
def _define_uint(name, bits):
|
|
499
|
+
mask = (1 << bits) - 1
|
|
500
|
+
g = globals()
|
|
501
|
+
g[f"lean_{name}_of_nat"] = lambda a: a & mask
|
|
502
|
+
g[f"lean_{name}_of_nat_mk"] = lambda a: a & mask
|
|
503
|
+
g[f"lean_{name}_to_nat"] = lambda a: a
|
|
504
|
+
g[f"lean_{name}_add"] = lambda a, b: (a + b) & mask
|
|
505
|
+
g[f"lean_{name}_sub"] = lambda a, b: (a - b) & mask
|
|
506
|
+
g[f"lean_{name}_mul"] = lambda a, b: (a * b) & mask
|
|
507
|
+
g[f"lean_{name}_div"] = lambda a, b: a // b if b else 0
|
|
508
|
+
g[f"lean_{name}_mod"] = lambda a, b: a % b if b else a
|
|
509
|
+
g[f"lean_{name}_land"] = lambda a, b: a & b
|
|
510
|
+
g[f"lean_{name}_lor"] = lambda a, b: a | b
|
|
511
|
+
g[f"lean_{name}_xor"] = lambda a, b: a ^ b
|
|
512
|
+
g[f"lean_{name}_shift_left"] = lambda a, b: (a << (b % bits)) & mask
|
|
513
|
+
g[f"lean_{name}_shift_right"] = lambda a, b: a >> (b % bits)
|
|
514
|
+
g[f"lean_{name}_complement"] = lambda a: a ^ mask
|
|
515
|
+
g[f"lean_{name}_neg"] = lambda a: (-a) & mask
|
|
516
|
+
g[f"lean_{name}_log2"] = lambda a: a.bit_length() - 1 if a > 0 else 0
|
|
517
|
+
g[f"lean_{name}_dec_eq"] = lambda a, b: a == b
|
|
518
|
+
g[f"lean_{name}_dec_lt"] = lambda a, b: a < b
|
|
519
|
+
g[f"lean_{name}_dec_le"] = lambda a, b: a <= b
|
|
520
|
+
g[f"lean_{name}_to_float"] = lambda a: float(a)
|
|
521
|
+
g[f"lean_{name}_to_float32"] = lambda a: _f32(float(a))
|
|
522
|
+
for other, obits in _WIDTHS.items():
|
|
523
|
+
if other != name:
|
|
524
|
+
omask = (1 << obits) - 1
|
|
525
|
+
g[f"lean_{name}_to_{other}"] = lambda a, omask=omask: a & omask
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
for _n, _b in _WIDTHS.items():
|
|
529
|
+
_define_uint(_n, _b)
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
_SWIDTHS = {"int8": 8, "int16": 16, "int32": 32, "int64": 64, "isize": 64}
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def _define_sint(name, bits):
|
|
536
|
+
mask = (1 << bits) - 1
|
|
537
|
+
half = 1 << (bits - 1)
|
|
538
|
+
|
|
539
|
+
def val(a):
|
|
540
|
+
return a - (1 << bits) if a >= half else a
|
|
541
|
+
|
|
542
|
+
g = globals()
|
|
543
|
+
g[f"lean_{name}_of_int"] = lambda a: a & mask
|
|
544
|
+
g[f"lean_{name}_of_nat"] = lambda a: a & mask
|
|
545
|
+
g[f"lean_{name}_to_int"] = val
|
|
546
|
+
g[f"lean_{name}_add"] = lambda a, b: (a + b) & mask
|
|
547
|
+
g[f"lean_{name}_sub"] = lambda a, b: (a - b) & mask
|
|
548
|
+
g[f"lean_{name}_mul"] = lambda a, b: (a * b) & mask
|
|
549
|
+
g[f"lean_{name}_div"] = lambda a, b: lean_int_div(val(a), val(b)) & mask
|
|
550
|
+
g[f"lean_{name}_mod"] = lambda a, b: lean_int_mod(val(a), val(b)) & mask
|
|
551
|
+
g[f"lean_{name}_neg"] = lambda a: (-a) & mask
|
|
552
|
+
g[f"lean_{name}_land"] = lambda a, b: a & b
|
|
553
|
+
g[f"lean_{name}_lor"] = lambda a, b: a | b
|
|
554
|
+
g[f"lean_{name}_xor"] = lambda a, b: a ^ b
|
|
555
|
+
g[f"lean_{name}_shift_left"] = lambda a, b: (a << (val(b) % bits)) & mask
|
|
556
|
+
g[f"lean_{name}_shift_right"] = lambda a, b: (val(a) >> (val(b) % bits)) & mask
|
|
557
|
+
g[f"lean_{name}_complement"] = lambda a: a ^ mask
|
|
558
|
+
g[f"lean_{name}_abs"] = lambda a: abs(val(a)) & mask
|
|
559
|
+
g[f"lean_{name}_dec_eq"] = lambda a, b: a == b
|
|
560
|
+
g[f"lean_{name}_dec_lt"] = lambda a, b: val(a) < val(b)
|
|
561
|
+
g[f"lean_{name}_dec_le"] = lambda a, b: val(a) <= val(b)
|
|
562
|
+
g[f"lean_{name}_to_float"] = lambda a: float(val(a))
|
|
563
|
+
g[f"lean_{name}_to_float32"] = lambda a: _f32(float(val(a)))
|
|
564
|
+
for other, obits in _SWIDTHS.items():
|
|
565
|
+
if other != name:
|
|
566
|
+
omask = (1 << obits) - 1
|
|
567
|
+
g[f"lean_{name}_to_{other}"] = lambda a, omask=omask: val(a) & omask
|
|
568
|
+
for other, obits in _WIDTHS.items():
|
|
569
|
+
omask = (1 << obits) - 1
|
|
570
|
+
g[f"lean_{name}_to_{other}"] = lambda a, omask=omask: val(a) & omask
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
for _n, _b in _SWIDTHS.items():
|
|
574
|
+
_define_sint(_n, _b)
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def lean_bool_to_uint64(a):
|
|
578
|
+
return 1 if a else 0
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
# ---------------------------------------------------------------------------
|
|
582
|
+
# Float and Float32
|
|
583
|
+
|
|
584
|
+
_F32 = struct.Struct("<f")
|
|
585
|
+
_F64 = struct.Struct("<d")
|
|
586
|
+
_U32 = struct.Struct("<I")
|
|
587
|
+
_U64 = struct.Struct("<Q")
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
def _f32(x):
|
|
591
|
+
try:
|
|
592
|
+
return _F32.unpack(_F32.pack(x))[0]
|
|
593
|
+
except OverflowError:
|
|
594
|
+
return math.copysign(math.inf, x)
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def _float_str(a):
|
|
598
|
+
if math.isnan(a):
|
|
599
|
+
return b"NaN"
|
|
600
|
+
if math.isinf(a):
|
|
601
|
+
return b"inf" if a > 0 else b"-inf"
|
|
602
|
+
return f"{a:.6f}".encode()
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
def lean_float_to_string(a):
|
|
606
|
+
return _float_str(a)
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
def lean_float32_to_string(a):
|
|
610
|
+
return _float_str(a)
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
def _to_uint(a, bits):
|
|
614
|
+
if math.isnan(a) or a <= 0:
|
|
615
|
+
return 0
|
|
616
|
+
m = (1 << bits) - 1
|
|
617
|
+
if a >= float(1 << bits):
|
|
618
|
+
return m
|
|
619
|
+
return int(a)
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
def _to_int(a, bits):
|
|
623
|
+
if math.isnan(a):
|
|
624
|
+
return 0
|
|
625
|
+
lo = -(1 << (bits - 1))
|
|
626
|
+
hi = (1 << (bits - 1)) - 1
|
|
627
|
+
if a <= lo:
|
|
628
|
+
v = lo
|
|
629
|
+
elif a >= float(hi):
|
|
630
|
+
v = hi
|
|
631
|
+
else:
|
|
632
|
+
v = int(a)
|
|
633
|
+
return v & ((1 << bits) - 1)
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
def _div(a, b):
|
|
637
|
+
try:
|
|
638
|
+
return a / b
|
|
639
|
+
except ZeroDivisionError:
|
|
640
|
+
if math.isnan(a) or a == 0:
|
|
641
|
+
return math.nan
|
|
642
|
+
return math.copysign(math.inf, a) * math.copysign(1.0, b)
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def _libm(f):
|
|
646
|
+
def g(*args):
|
|
647
|
+
try:
|
|
648
|
+
return f(*args)
|
|
649
|
+
except ValueError:
|
|
650
|
+
return math.nan
|
|
651
|
+
except OverflowError:
|
|
652
|
+
return math.inf
|
|
653
|
+
|
|
654
|
+
return g
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
def _libm32(f):
|
|
658
|
+
def g(*args):
|
|
659
|
+
return _f32(f(*args))
|
|
660
|
+
|
|
661
|
+
return g
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def _define_float(p, rnd):
|
|
665
|
+
g = globals()
|
|
666
|
+
g[f"lean_{p}_add"] = lambda a, b: rnd(a + b)
|
|
667
|
+
g[f"lean_{p}_sub"] = lambda a, b: rnd(a - b)
|
|
668
|
+
g[f"lean_{p}_mul"] = lambda a, b: rnd(a * b)
|
|
669
|
+
g[f"lean_{p}_div"] = lambda a, b: rnd(_div(a, b))
|
|
670
|
+
g[f"lean_{p}_negate"] = lambda a: -a
|
|
671
|
+
g[f"lean_{p}_beq"] = lambda a, b: a == b
|
|
672
|
+
g[f"lean_{p}_decLt"] = lambda a, b: a < b
|
|
673
|
+
g[f"lean_{p}_decLe"] = lambda a, b: a <= b
|
|
674
|
+
g[f"lean_{p}_isnan"] = math.isnan
|
|
675
|
+
g[f"lean_{p}_isfinite"] = lambda a: math.isfinite(a)
|
|
676
|
+
g[f"lean_{p}_isinf"] = lambda a: math.isinf(a)
|
|
677
|
+
g[f"lean_{p}_of_nat"] = lambda a: rnd(_nat_to_float(a))
|
|
678
|
+
g[f"lean_{p}_of_int"] = lambda a: rnd(_int_to_float(a))
|
|
679
|
+
for name, bits in (("uint8", 8), ("uint16", 16), ("uint32", 32), ("uint64", 64), ("usize", 64)):
|
|
680
|
+
g[f"lean_{p}_to_{name}"] = lambda a, bits=bits: _to_uint(a, bits)
|
|
681
|
+
for name, bits in (("int8", 8), ("int16", 16), ("int32", 32), ("int64", 64), ("isize", 64)):
|
|
682
|
+
g[f"lean_{p}_to_{name}"] = lambda a, bits=bits: _to_int(a, bits)
|
|
683
|
+
g[f"lean_{p}_scaleb"] = lambda a, b: rnd(_scaleb(a, b))
|
|
684
|
+
g[f"lean_{p}_frexp"] = lambda a: Ctor(0, [rnd(_frexp(a)[0]), _frexp(a)[1]])
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
def _nat_to_float(a):
|
|
688
|
+
try:
|
|
689
|
+
return float(a)
|
|
690
|
+
except OverflowError:
|
|
691
|
+
return math.inf
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
def _int_to_float(a):
|
|
695
|
+
try:
|
|
696
|
+
return float(a)
|
|
697
|
+
except OverflowError:
|
|
698
|
+
return math.copysign(math.inf, a)
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
def _scaleb(a, b):
|
|
702
|
+
try:
|
|
703
|
+
return math.ldexp(a, b)
|
|
704
|
+
except OverflowError:
|
|
705
|
+
return math.copysign(math.inf, a)
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
def _frexp(a):
|
|
709
|
+
if not math.isfinite(a):
|
|
710
|
+
return (a, 0)
|
|
711
|
+
return math.frexp(a)
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
_define_float("float", lambda x: x)
|
|
715
|
+
_define_float("float32", _f32)
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
def lean_float_of_bits(u):
|
|
719
|
+
return _F64.unpack(_U64.pack(u))[0]
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
def lean_float_to_bits(a):
|
|
723
|
+
return _U64.unpack(_F64.pack(a))[0]
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def lean_float32_of_bits(u):
|
|
727
|
+
return _F32.unpack(_U32.pack(u))[0]
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
def lean_float32_to_bits(a):
|
|
731
|
+
return _U32.unpack(_F32.pack(a))[0]
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
def lean_float_to_float32(a):
|
|
735
|
+
return _f32(a)
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
def lean_float32_to_float(a):
|
|
739
|
+
return a
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
def lean_float_of_scientific(m, sign, e):
|
|
743
|
+
try:
|
|
744
|
+
if sign:
|
|
745
|
+
return float(m) / (10**e) if e < 400 else _float_div_big(m, e)
|
|
746
|
+
return float(m * 10**e)
|
|
747
|
+
except OverflowError:
|
|
748
|
+
return math.inf
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
def _float_div_big(m, e):
|
|
752
|
+
from fractions import Fraction
|
|
753
|
+
|
|
754
|
+
return float(Fraction(m, 10**e))
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
for _name, _f in (
|
|
758
|
+
("sin", math.sin),
|
|
759
|
+
("cos", math.cos),
|
|
760
|
+
("tan", math.tan),
|
|
761
|
+
("asin", math.asin),
|
|
762
|
+
("acos", math.acos),
|
|
763
|
+
("atan", math.atan),
|
|
764
|
+
("atan2", math.atan2),
|
|
765
|
+
("sinh", math.sinh),
|
|
766
|
+
("cosh", math.cosh),
|
|
767
|
+
("tanh", math.tanh),
|
|
768
|
+
("asinh", math.asinh),
|
|
769
|
+
("acosh", math.acosh),
|
|
770
|
+
("atanh", math.atanh),
|
|
771
|
+
("exp", math.exp),
|
|
772
|
+
("exp2", lambda x: 2.0**x),
|
|
773
|
+
("log", math.log),
|
|
774
|
+
("log2", math.log2),
|
|
775
|
+
("log10", math.log10),
|
|
776
|
+
("pow", math.pow),
|
|
777
|
+
("sqrt", math.sqrt),
|
|
778
|
+
("cbrt", math.cbrt),
|
|
779
|
+
("ceil", lambda x: float(math.ceil(x)) if math.isfinite(x) else x),
|
|
780
|
+
("floor", lambda x: float(math.floor(x)) if math.isfinite(x) else x),
|
|
781
|
+
("round", lambda x: float(math.floor(abs(x) + 0.5)) * math.copysign(1.0, x) if math.isfinite(x) else x),
|
|
782
|
+
("fabs", math.fabs),
|
|
783
|
+
("fmod", math.fmod),
|
|
784
|
+
("fma", math.fma),
|
|
785
|
+
):
|
|
786
|
+
globals()[_name] = _libm(_f)
|
|
787
|
+
globals()[_name + "f"] = _libm32(_libm(_f))
|
|
788
|
+
|
|
789
|
+
# ---------------------------------------------------------------------------
|
|
790
|
+
# Strings (UTF-8 bytes)
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
def _s(b):
|
|
794
|
+
return b.decode("utf-8", "surrogatepass")
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
def _is_first(c):
|
|
798
|
+
return (c & 0x80) == 0 or (c & 0xE0) == 0xC0 or (c & 0xF0) == 0xE0 or (c & 0xF8) == 0xF0
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
def _char_size(c):
|
|
802
|
+
if c & 0x80 == 0:
|
|
803
|
+
return 1
|
|
804
|
+
if (c & 0xE0) == 0xC0:
|
|
805
|
+
return 2
|
|
806
|
+
if (c & 0xF0) == 0xE0:
|
|
807
|
+
return 3
|
|
808
|
+
if (c & 0xF8) == 0xF0:
|
|
809
|
+
return 4
|
|
810
|
+
return 1
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
def _get_core(s, i):
|
|
814
|
+
size = len(s)
|
|
815
|
+
c = s[i]
|
|
816
|
+
if c & 0x80 == 0:
|
|
817
|
+
return c
|
|
818
|
+
if (c & 0xE0) == 0xC0 and i + 1 < size:
|
|
819
|
+
r = ((c & 0x1F) << 6) | (s[i + 1] & 0x3F)
|
|
820
|
+
if r >= 0x80:
|
|
821
|
+
return r
|
|
822
|
+
if (c & 0xF0) == 0xE0 and i + 2 < size:
|
|
823
|
+
r = ((c & 0x0F) << 12) | ((s[i + 1] & 0x3F) << 6) | (s[i + 2] & 0x3F)
|
|
824
|
+
if r >= 0x800 and not (0xD800 <= r <= 0xDFFF):
|
|
825
|
+
return r
|
|
826
|
+
if (c & 0xF8) == 0xF0 and i + 3 < size:
|
|
827
|
+
r = ((c & 0x07) << 18) | ((s[i + 1] & 0x3F) << 12) | ((s[i + 2] & 0x3F) << 6) | (s[i + 3] & 0x3F)
|
|
828
|
+
if 0x10000 <= r <= 0x10FFFF:
|
|
829
|
+
return r
|
|
830
|
+
return None
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
def _enc(c):
|
|
834
|
+
return chr(c).encode("utf-8", "surrogatepass")
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
_DEFAULT_CHAR = 65
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
def lean_mk_string(s):
|
|
841
|
+
return s
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
def lean_string_mk(cs):
|
|
845
|
+
return "".join(chr(c) for c in _list_to_py(cs)).encode("utf-8", "surrogatepass")
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
def lean_string_data(s):
|
|
849
|
+
return _py_to_list([ord(c) for c in _s(s)])
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
def lean_string_length(s):
|
|
853
|
+
if s.isascii():
|
|
854
|
+
return len(s)
|
|
855
|
+
return len(_s(s))
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
def lean_string_utf8_byte_size(s):
|
|
859
|
+
return len(s)
|
|
860
|
+
|
|
861
|
+
|
|
862
|
+
def lean_string_push(s, c):
|
|
863
|
+
return s + _enc(c)
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
def lean_string_append(a, b):
|
|
867
|
+
return a + b
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
def lean_string_utf8_get(s, i):
|
|
871
|
+
if i >= len(s):
|
|
872
|
+
return _DEFAULT_CHAR
|
|
873
|
+
r = _get_core(s, i)
|
|
874
|
+
return _DEFAULT_CHAR if r is None else r
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
def lean_string_utf8_get_fast(s, i):
|
|
878
|
+
c = s[i]
|
|
879
|
+
if c & 0x80 == 0:
|
|
880
|
+
return c
|
|
881
|
+
r = _get_core(s, i)
|
|
882
|
+
return _DEFAULT_CHAR if r is None else r
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
def lean_string_utf8_get_opt(s, i):
|
|
886
|
+
if i >= len(s):
|
|
887
|
+
return 0
|
|
888
|
+
r = _get_core(s, i)
|
|
889
|
+
return 0 if r is None else Ctor(1, [r])
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
def lean_string_utf8_get_bang(s, i):
|
|
893
|
+
if i >= len(s):
|
|
894
|
+
_panic("PANIC at String.get! Init.Data.String.Basic:0:0: index out of bounds")
|
|
895
|
+
return _DEFAULT_CHAR
|
|
896
|
+
r = _get_core(s, i)
|
|
897
|
+
return _DEFAULT_CHAR if r is None else r
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
def lean_string_utf8_next(s, i):
|
|
901
|
+
if i >= len(s):
|
|
902
|
+
return i + 1
|
|
903
|
+
return i + _char_size(s[i])
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
def lean_string_utf8_next_fast(s, i):
|
|
907
|
+
return i + _char_size(s[i])
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
def lean_string_utf8_prev(s, i):
|
|
911
|
+
if i == 0:
|
|
912
|
+
return 0
|
|
913
|
+
if i > len(s):
|
|
914
|
+
return i - 1
|
|
915
|
+
i -= 1
|
|
916
|
+
while not _is_first(s[i]):
|
|
917
|
+
i -= 1
|
|
918
|
+
return i
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
def lean_string_utf8_at_end(s, i):
|
|
922
|
+
return i >= len(s)
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
def lean_string_is_valid_pos(s, i):
|
|
926
|
+
if i > len(s):
|
|
927
|
+
return False
|
|
928
|
+
if i == len(s):
|
|
929
|
+
return True
|
|
930
|
+
return _is_first(s[i])
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
def lean_string_utf8_extract(s, b, e):
|
|
934
|
+
sz = len(s)
|
|
935
|
+
if b >= e or b >= sz:
|
|
936
|
+
return b""
|
|
937
|
+
if not _is_first(s[b]):
|
|
938
|
+
return b""
|
|
939
|
+
e = min(e, sz)
|
|
940
|
+
if e < sz and not _is_first(s[e]):
|
|
941
|
+
e = sz
|
|
942
|
+
return s[b:e]
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
def lean_string_utf8_extract_fast(s, b, e):
|
|
946
|
+
return s[b:e]
|
|
947
|
+
|
|
948
|
+
|
|
949
|
+
def lean_string_utf8_set(s, i, c):
|
|
950
|
+
sz = len(s)
|
|
951
|
+
if i >= sz:
|
|
952
|
+
return s
|
|
953
|
+
old = s[i]
|
|
954
|
+
if not _is_first(old):
|
|
955
|
+
return s
|
|
956
|
+
n = min(_char_size(old), sz - i)
|
|
957
|
+
return s[:i] + _enc(c) + s[i + n :]
|
|
958
|
+
|
|
959
|
+
|
|
960
|
+
def lean_string_get_byte_fast(s, i):
|
|
961
|
+
return s[i]
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
def lean_string_dec_eq(a, b):
|
|
965
|
+
return a == b
|
|
966
|
+
|
|
967
|
+
|
|
968
|
+
def lean_string_dec_lt(a, b):
|
|
969
|
+
return a < b
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
def lean_string_lt(a, b):
|
|
973
|
+
return a < b
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
def lean_string_memcmp(s1, s2, lstart, rstart, length):
|
|
977
|
+
return s1[lstart : lstart + length] == s2[rstart : rstart + length]
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
def lean_string_of_usize(n):
|
|
981
|
+
return str(n).encode()
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
def lean_string_to_utf8(s):
|
|
985
|
+
return LByteArray(bytearray(s))
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
def lean_string_from_utf8_unchecked(a):
|
|
989
|
+
return bytes(a.data)
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
def lean_string_validate_utf8(a):
|
|
993
|
+
try:
|
|
994
|
+
bytes(a.data).decode("utf-8")
|
|
995
|
+
return True
|
|
996
|
+
except UnicodeDecodeError:
|
|
997
|
+
return False
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
_M64 = (1 << 64) - 1
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
def _murmur64a(data, seed):
|
|
1004
|
+
m = 0xC6A4A7935BD1E995
|
|
1005
|
+
r = 47
|
|
1006
|
+
n = len(data)
|
|
1007
|
+
h = (seed ^ (n * m)) & _M64
|
|
1008
|
+
nblocks = n // 8
|
|
1009
|
+
for i in range(nblocks):
|
|
1010
|
+
k = int.from_bytes(data[8 * i : 8 * i + 8], "little")
|
|
1011
|
+
k = (k * m) & _M64
|
|
1012
|
+
k ^= k >> r
|
|
1013
|
+
k = (k * m) & _M64
|
|
1014
|
+
h ^= k
|
|
1015
|
+
h = (h * m) & _M64
|
|
1016
|
+
tail = data[8 * nblocks :]
|
|
1017
|
+
if tail:
|
|
1018
|
+
for i in range(len(tail) - 1, -1, -1):
|
|
1019
|
+
h ^= tail[i] << (8 * i)
|
|
1020
|
+
h = (h * m) & _M64
|
|
1021
|
+
h ^= h >> r
|
|
1022
|
+
h = (h * m) & _M64
|
|
1023
|
+
h ^= h >> r
|
|
1024
|
+
return h
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
def lean_string_hash(s):
|
|
1028
|
+
return _murmur64a(s, 11)
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
def lean_uint64_mix_hash(a, b):
|
|
1032
|
+
m = 0xC6A4A7935BD1E995
|
|
1033
|
+
r = 47
|
|
1034
|
+
b = (b * m) & _M64
|
|
1035
|
+
b ^= b >> r
|
|
1036
|
+
b = (b * m) & _M64
|
|
1037
|
+
a ^= b
|
|
1038
|
+
a = (a * m) & _M64
|
|
1039
|
+
return a
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
# ---------------------------------------------------------------------------
|
|
1043
|
+
# Arrays
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
def _array_exclusive(a):
|
|
1047
|
+
if a.rc == 1:
|
|
1048
|
+
return a
|
|
1049
|
+
data = a.data
|
|
1050
|
+
for x in data:
|
|
1051
|
+
lean_inc(x)
|
|
1052
|
+
lean_dec(a)
|
|
1053
|
+
return LArray(list(data))
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
def lean_array_mk(xs):
|
|
1057
|
+
items = _list_to_py(xs)
|
|
1058
|
+
for x in items:
|
|
1059
|
+
lean_inc(x)
|
|
1060
|
+
lean_dec(xs)
|
|
1061
|
+
return LArray(items)
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
def lean_array_to_list(a):
|
|
1065
|
+
for x in a.data:
|
|
1066
|
+
lean_inc(x)
|
|
1067
|
+
return _py_to_list(a.data)
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
def lean_mk_empty_array_with_capacity(cap):
|
|
1071
|
+
return LArray([])
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
def lean_mk_array(n, v):
|
|
1075
|
+
if n == 0:
|
|
1076
|
+
lean_dec(v)
|
|
1077
|
+
return LArray([])
|
|
1078
|
+
lean_inc_n(v, n - 1)
|
|
1079
|
+
return LArray([v] * n)
|
|
1080
|
+
|
|
1081
|
+
|
|
1082
|
+
def lean_array_get_size(a):
|
|
1083
|
+
return len(a.data)
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
def lean_array_size(a):
|
|
1087
|
+
return len(a.data)
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
def lean_array_fget(a, i):
|
|
1091
|
+
x = a.data[i]
|
|
1092
|
+
lean_inc(x)
|
|
1093
|
+
return x
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
def lean_array_fget_borrowed(a, i):
|
|
1097
|
+
return a.data[i]
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
def lean_array_uget(a, i):
|
|
1101
|
+
x = a.data[i]
|
|
1102
|
+
lean_inc(x)
|
|
1103
|
+
return x
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
def lean_array_uget_borrowed(a, i):
|
|
1107
|
+
return a.data[i]
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
def lean_array_get(default, a, i):
|
|
1111
|
+
if i < len(a.data):
|
|
1112
|
+
lean_dec(default)
|
|
1113
|
+
x = a.data[i]
|
|
1114
|
+
lean_inc(x)
|
|
1115
|
+
return x
|
|
1116
|
+
_panic_oob()
|
|
1117
|
+
return default
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
def lean_array_get_borrowed(default, a, i):
|
|
1121
|
+
if i < len(a.data):
|
|
1122
|
+
return a.data[i]
|
|
1123
|
+
_panic_oob()
|
|
1124
|
+
return default
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
def _panic_oob():
|
|
1128
|
+
_eprint("Error: index out of bounds")
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
def lean_array_push(a, v):
|
|
1132
|
+
a = _array_exclusive(a)
|
|
1133
|
+
a.data.append(v)
|
|
1134
|
+
return a
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
def lean_array_fset(a, i, v):
|
|
1138
|
+
a = _array_exclusive(a)
|
|
1139
|
+
old = a.data[i]
|
|
1140
|
+
a.data[i] = v
|
|
1141
|
+
lean_dec(old)
|
|
1142
|
+
return a
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
def lean_array_uset(a, i, v):
|
|
1146
|
+
return lean_array_fset(a, i, v)
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
def lean_array_set(a, i, v):
|
|
1150
|
+
if i >= len(a.data):
|
|
1151
|
+
lean_dec(v)
|
|
1152
|
+
_panic_oob()
|
|
1153
|
+
return a
|
|
1154
|
+
return lean_array_fset(a, i, v)
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
def lean_array_fswap(a, i, j):
|
|
1158
|
+
a = _array_exclusive(a)
|
|
1159
|
+
d = a.data
|
|
1160
|
+
d[i], d[j] = d[j], d[i]
|
|
1161
|
+
return a
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
def lean_array_swap(a, i, j):
|
|
1165
|
+
n = len(a.data)
|
|
1166
|
+
if i >= n or j >= n:
|
|
1167
|
+
return a
|
|
1168
|
+
return lean_array_fswap(a, i, j)
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
def lean_array_pop(a):
|
|
1172
|
+
a = _array_exclusive(a)
|
|
1173
|
+
if a.data:
|
|
1174
|
+
lean_dec(a.data.pop())
|
|
1175
|
+
return a
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
def lean_array_uswap(a, i, j):
|
|
1179
|
+
return lean_array_fswap(a, i, j)
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
def lean_array_propagate_mark(a):
|
|
1183
|
+
return a
|
|
1184
|
+
|
|
1185
|
+
|
|
1186
|
+
def lean_copy_array(a):
|
|
1187
|
+
for x in a.data:
|
|
1188
|
+
lean_inc(x)
|
|
1189
|
+
return LArray(list(a.data))
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
def lean_array_extract(a, start, stop):
|
|
1193
|
+
d = a.data
|
|
1194
|
+
stop = min(stop, len(d))
|
|
1195
|
+
if start >= stop:
|
|
1196
|
+
return LArray([])
|
|
1197
|
+
items = d[start:stop]
|
|
1198
|
+
for x in items:
|
|
1199
|
+
lean_inc(x)
|
|
1200
|
+
return LArray(items)
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
# ---------------------------------------------------------------------------
|
|
1204
|
+
# ByteArray and FloatArray
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
def _sarray_exclusive(a, cls):
|
|
1208
|
+
if a.rc == 1:
|
|
1209
|
+
return a
|
|
1210
|
+
lean_dec(a)
|
|
1211
|
+
return cls(a.data.copy())
|
|
1212
|
+
|
|
1213
|
+
|
|
1214
|
+
def lean_byte_array_mk(xs):
|
|
1215
|
+
return LByteArray(bytearray(xs.data))
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
def lean_byte_array_data(a):
|
|
1219
|
+
return LArray(list(a.data))
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
def lean_mk_empty_byte_array(cap):
|
|
1223
|
+
return LByteArray(bytearray())
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
def lean_byte_array_size(a):
|
|
1227
|
+
return len(a.data)
|
|
1228
|
+
|
|
1229
|
+
|
|
1230
|
+
def lean_sarray_size(a):
|
|
1231
|
+
return len(a.data)
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
def lean_byte_array_get(a, i):
|
|
1235
|
+
return a.data[i] if i < len(a.data) else 0
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
def lean_byte_array_fget(a, i):
|
|
1239
|
+
return a.data[i]
|
|
1240
|
+
|
|
1241
|
+
|
|
1242
|
+
def lean_byte_array_uget(a, i):
|
|
1243
|
+
return a.data[i]
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
def lean_byte_array_push(a, v):
|
|
1247
|
+
a = _sarray_exclusive(a, LByteArray)
|
|
1248
|
+
a.data.append(v)
|
|
1249
|
+
return a
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
def lean_byte_array_set(a, i, v):
|
|
1253
|
+
if i >= len(a.data):
|
|
1254
|
+
return a
|
|
1255
|
+
a = _sarray_exclusive(a, LByteArray)
|
|
1256
|
+
a.data[i] = v
|
|
1257
|
+
return a
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
def lean_byte_array_fset(a, i, v):
|
|
1261
|
+
a = _sarray_exclusive(a, LByteArray)
|
|
1262
|
+
a.data[i] = v
|
|
1263
|
+
return a
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
def lean_byte_array_uset(a, i, v):
|
|
1267
|
+
return lean_byte_array_fset(a, i, v)
|
|
1268
|
+
|
|
1269
|
+
|
|
1270
|
+
def lean_byte_array_copy_slice(src, src_off, dest, dest_off, length, exact):
|
|
1271
|
+
ssz = len(src.data)
|
|
1272
|
+
dsz = len(dest.data)
|
|
1273
|
+
src_off = min(src_off, ssz)
|
|
1274
|
+
length = min(length, ssz - src_off)
|
|
1275
|
+
dest_off = min(dest_off, dsz)
|
|
1276
|
+
chunk = src.data[src_off : src_off + length]
|
|
1277
|
+
r = _sarray_exclusive(dest, LByteArray)
|
|
1278
|
+
if dest_off + length > dsz:
|
|
1279
|
+
r.data.extend(bytes(dest_off + length - dsz))
|
|
1280
|
+
r.data[dest_off : dest_off + length] = chunk
|
|
1281
|
+
return r
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
def lean_byte_array_hash(a):
|
|
1285
|
+
return _murmur64a(bytes(a.data), 11)
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
def lean_float_array_mk(xs):
|
|
1289
|
+
return LFloatArray(list(xs.data))
|
|
1290
|
+
|
|
1291
|
+
|
|
1292
|
+
def lean_float_array_data(a):
|
|
1293
|
+
return LArray(list(a.data))
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
def lean_mk_empty_float_array(cap):
|
|
1297
|
+
return LFloatArray([])
|
|
1298
|
+
|
|
1299
|
+
|
|
1300
|
+
def lean_float_array_size(a):
|
|
1301
|
+
return len(a.data)
|
|
1302
|
+
|
|
1303
|
+
|
|
1304
|
+
def lean_float_array_get(a, i):
|
|
1305
|
+
return a.data[i] if i < len(a.data) else 0.0
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
def lean_float_array_fget(a, i):
|
|
1309
|
+
return a.data[i]
|
|
1310
|
+
|
|
1311
|
+
|
|
1312
|
+
def lean_float_array_uget(a, i):
|
|
1313
|
+
return a.data[i]
|
|
1314
|
+
|
|
1315
|
+
|
|
1316
|
+
def lean_float_array_push(a, v):
|
|
1317
|
+
a = _sarray_exclusive(a, LFloatArray)
|
|
1318
|
+
a.data.append(v)
|
|
1319
|
+
return a
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
def lean_float_array_set(a, i, v):
|
|
1323
|
+
if i >= len(a.data):
|
|
1324
|
+
return a
|
|
1325
|
+
a = _sarray_exclusive(a, LFloatArray)
|
|
1326
|
+
a.data[i] = v
|
|
1327
|
+
return a
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
def lean_float_array_fset(a, i, v):
|
|
1331
|
+
a = _sarray_exclusive(a, LFloatArray)
|
|
1332
|
+
a.data[i] = v
|
|
1333
|
+
return a
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
def lean_float_array_uset(a, i, v):
|
|
1337
|
+
return lean_float_array_fset(a, i, v)
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
# ---------------------------------------------------------------------------
|
|
1341
|
+
# Thunks and tasks (run synchronously)
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
def lean_mk_thunk(c):
|
|
1345
|
+
return Thunk(c)
|
|
1346
|
+
|
|
1347
|
+
|
|
1348
|
+
def lean_thunk_pure(v):
|
|
1349
|
+
return Thunk(None, v, True)
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
def _thunk_force(t):
|
|
1353
|
+
if not t.done:
|
|
1354
|
+
t.value = lean_mark_persistent(lean_apply(t.fn, [0]))
|
|
1355
|
+
t.done = True
|
|
1356
|
+
t.fn = None
|
|
1357
|
+
return t.value
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
def lean_thunk_get_own(t):
|
|
1361
|
+
v = _thunk_force(t)
|
|
1362
|
+
lean_inc(v)
|
|
1363
|
+
return v
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
def lean_thunk_get(t):
|
|
1367
|
+
return _thunk_force(t)
|
|
1368
|
+
|
|
1369
|
+
|
|
1370
|
+
def lean_task_pure(v):
|
|
1371
|
+
return Task(lean_mark_persistent(v))
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
def lean_task_spawn(c, prio=0):
|
|
1375
|
+
return Task(lean_mark_persistent(lean_apply(c, [0])))
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
def lean_task_get_own(t):
|
|
1379
|
+
v = t.value
|
|
1380
|
+
lean_inc(v)
|
|
1381
|
+
return v
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
def lean_task_get(t):
|
|
1385
|
+
return t.value
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
def lean_task_map(f, t, prio=0, sync=0):
|
|
1389
|
+
return Task(lean_mark_persistent(lean_apply(f, [t.value])))
|
|
1390
|
+
|
|
1391
|
+
|
|
1392
|
+
def lean_task_bind(t, f, prio=0, sync=0):
|
|
1393
|
+
return lean_apply(f, [t.value])
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
def lean_io_wait(t, _w=0):
|
|
1397
|
+
return t.value
|
|
1398
|
+
|
|
1399
|
+
|
|
1400
|
+
from lean_python.io_externs import *
|