egglog 9.0.0__cp313-cp313-win_amd64.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.

Potentially problematic release.


This version of egglog might be problematic. Click here for more details.

egglog/builtins.py ADDED
@@ -0,0 +1,1045 @@
1
+ # mypy: disable-error-code="empty-body"
2
+ """
3
+ Builtin sorts and function to egg.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from fractions import Fraction
9
+ from functools import partial, reduce
10
+ from types import FunctionType, MethodType
11
+ from typing import TYPE_CHECKING, Generic, Protocol, TypeAlias, TypeVar, Union, cast, overload
12
+
13
+ from typing_extensions import TypeVarTuple, Unpack
14
+
15
+ from . import bindings
16
+ from .conversion import convert, converter, get_type_args
17
+ from .declarations import *
18
+ from .egraph import BaseExpr, BuiltinExpr, EGraph, expr_fact, function, get_current_ruleset, method
19
+ from .egraph_state import GLOBAL_PY_OBJECT_SORT
20
+ from .functionalize import functionalize
21
+ from .runtime import RuntimeClass, RuntimeExpr, RuntimeFunction
22
+ from .thunk import Thunk
23
+
24
+ if TYPE_CHECKING:
25
+ from collections.abc import Callable, Iterator
26
+
27
+
28
+ __all__ = [
29
+ "BigInt",
30
+ "BigIntLike",
31
+ "BigRat",
32
+ "BigRatLike",
33
+ "Bool",
34
+ "BoolLike",
35
+ "Map",
36
+ "MapLike",
37
+ "MultiSet",
38
+ "PyObject",
39
+ "Rational",
40
+ "Set",
41
+ "SetLike",
42
+ "String",
43
+ "StringLike",
44
+ "Unit",
45
+ "UnstableFn",
46
+ "Vec",
47
+ "VecLike",
48
+ "f64",
49
+ "f64Like",
50
+ "i64",
51
+ "i64Like",
52
+ "join",
53
+ "py_eval",
54
+ "py_eval_fn",
55
+ "py_exec",
56
+ ]
57
+
58
+
59
+ class Unit(BuiltinExpr, egg_sort="Unit"):
60
+ """
61
+ The unit type. This is used to reprsent if a value exists in the e-graph or not.
62
+ """
63
+
64
+ def __init__(self) -> None: ...
65
+
66
+ @method(preserve=True)
67
+ def __bool__(self) -> bool:
68
+ return bool(expr_fact(self))
69
+
70
+
71
+ class String(BuiltinExpr):
72
+ @method(preserve=True)
73
+ def eval(self) -> str:
74
+ value = _extract_lit(self)
75
+ assert isinstance(value, bindings.String)
76
+ return value.value
77
+
78
+ def __init__(self, value: str) -> None: ...
79
+
80
+ @method(egg_fn="replace")
81
+ def replace(self, old: StringLike, new: StringLike) -> String: ...
82
+
83
+
84
+ StringLike: TypeAlias = String | str
85
+
86
+
87
+ @function(egg_fn="+", builtin=True)
88
+ def join(*strings: StringLike) -> String: ...
89
+
90
+
91
+ converter(str, String, String)
92
+
93
+ BoolLike: TypeAlias = Union["Bool", bool]
94
+
95
+
96
+ class Bool(BuiltinExpr, egg_sort="bool"):
97
+ @method(preserve=True)
98
+ def eval(self) -> bool:
99
+ value = _extract_lit(self)
100
+ assert isinstance(value, bindings.Bool)
101
+ return value.value
102
+
103
+ @method(preserve=True)
104
+ def __bool__(self) -> bool:
105
+ return self.eval()
106
+
107
+ def __init__(self, value: bool) -> None: ...
108
+
109
+ @method(egg_fn="not")
110
+ def __invert__(self) -> Bool: ...
111
+
112
+ @method(egg_fn="and")
113
+ def __and__(self, other: BoolLike) -> Bool: ...
114
+
115
+ @method(egg_fn="or")
116
+ def __or__(self, other: BoolLike) -> Bool: ...
117
+
118
+ @method(egg_fn="xor")
119
+ def __xor__(self, other: BoolLike) -> Bool: ...
120
+
121
+ @method(egg_fn="=>")
122
+ def implies(self, other: BoolLike) -> Bool: ...
123
+
124
+
125
+ converter(bool, Bool, Bool)
126
+
127
+ # The types which can be convertered into an i64
128
+ i64Like: TypeAlias = Union["i64", int] # noqa: N816, PYI042
129
+
130
+
131
+ class i64(BuiltinExpr): # noqa: N801
132
+ @method(preserve=True)
133
+ def eval(self) -> int:
134
+ value = _extract_lit(self)
135
+ assert isinstance(value, bindings.Int)
136
+ return value.value
137
+
138
+ @method(preserve=True)
139
+ def __index__(self) -> int:
140
+ return self.eval()
141
+
142
+ @method(preserve=True)
143
+ def __int__(self) -> int:
144
+ return self.eval()
145
+
146
+ def __init__(self, value: int) -> None: ...
147
+
148
+ @method(egg_fn="+")
149
+ def __add__(self, other: i64Like) -> i64: ...
150
+
151
+ @method(egg_fn="-")
152
+ def __sub__(self, other: i64Like) -> i64: ...
153
+
154
+ @method(egg_fn="*")
155
+ def __mul__(self, other: i64Like) -> i64: ...
156
+
157
+ @method(egg_fn="/")
158
+ def __truediv__(self, other: i64Like) -> i64: ...
159
+
160
+ @method(egg_fn="%")
161
+ def __mod__(self, other: i64Like) -> i64: ...
162
+
163
+ @method(egg_fn="&")
164
+ def __and__(self, other: i64Like) -> i64: ...
165
+
166
+ @method(egg_fn="|")
167
+ def __or__(self, other: i64Like) -> i64: ...
168
+
169
+ @method(egg_fn="^")
170
+ def __xor__(self, other: i64Like) -> i64: ...
171
+
172
+ @method(egg_fn="<<")
173
+ def __lshift__(self, other: i64Like) -> i64: ...
174
+
175
+ @method(egg_fn=">>")
176
+ def __rshift__(self, other: i64Like) -> i64: ...
177
+
178
+ def __radd__(self, other: i64Like) -> i64: ...
179
+
180
+ def __rsub__(self, other: i64Like) -> i64: ...
181
+
182
+ def __rmul__(self, other: i64Like) -> i64: ...
183
+
184
+ def __rtruediv__(self, other: i64Like) -> i64: ...
185
+
186
+ def __rmod__(self, other: i64Like) -> i64: ...
187
+
188
+ def __rand__(self, other: i64Like) -> i64: ...
189
+
190
+ def __ror__(self, other: i64Like) -> i64: ...
191
+
192
+ def __rxor__(self, other: i64Like) -> i64: ...
193
+
194
+ def __rlshift__(self, other: i64Like) -> i64: ...
195
+
196
+ def __rrshift__(self, other: i64Like) -> i64: ...
197
+
198
+ @method(egg_fn="not-i64")
199
+ def __invert__(self) -> i64: ...
200
+
201
+ @method(egg_fn="<")
202
+ def __lt__(self, other: i64Like) -> Unit: # type: ignore[empty-body,has-type]
203
+ ...
204
+
205
+ @method(egg_fn=">")
206
+ def __gt__(self, other: i64Like) -> Unit: ...
207
+
208
+ @method(egg_fn="<=")
209
+ def __le__(self, other: i64Like) -> Unit: # type: ignore[empty-body,has-type]
210
+ ...
211
+
212
+ @method(egg_fn=">=")
213
+ def __ge__(self, other: i64Like) -> Unit: ...
214
+
215
+ @method(egg_fn="min")
216
+ def min(self, other: i64Like) -> i64: ...
217
+
218
+ @method(egg_fn="max")
219
+ def max(self, other: i64Like) -> i64: ...
220
+
221
+ @method(egg_fn="to-string")
222
+ def to_string(self) -> String: ...
223
+
224
+ @method(egg_fn="bool-<")
225
+ def bool_lt(self, other: i64Like) -> Bool: ...
226
+
227
+ @method(egg_fn="bool->")
228
+ def bool_gt(self, other: i64Like) -> Bool: ...
229
+
230
+ @method(egg_fn="bool-<=")
231
+ def bool_le(self, other: i64Like) -> Bool: ...
232
+
233
+ @method(egg_fn="bool->=")
234
+ def bool_ge(self, other: i64Like) -> Bool: ...
235
+
236
+
237
+ converter(int, i64, i64)
238
+
239
+
240
+ @function(builtin=True, egg_fn="count-matches")
241
+ def count_matches(s: StringLike, pattern: StringLike) -> i64: ...
242
+
243
+
244
+ f64Like: TypeAlias = Union["f64", float] # noqa: N816, PYI042
245
+
246
+
247
+ class f64(BuiltinExpr): # noqa: N801
248
+ @method(preserve=True)
249
+ def eval(self) -> float:
250
+ value = _extract_lit(self)
251
+ assert isinstance(value, bindings.Float)
252
+ return value.value
253
+
254
+ @method(preserve=True)
255
+ def __float__(self) -> float:
256
+ return self.eval()
257
+
258
+ @method(preserve=True)
259
+ def __int__(self) -> int:
260
+ return int(self.eval())
261
+
262
+ def __init__(self, value: float) -> None: ...
263
+
264
+ @method(egg_fn="neg")
265
+ def __neg__(self) -> f64: ...
266
+
267
+ @method(egg_fn="+")
268
+ def __add__(self, other: f64Like) -> f64: ...
269
+
270
+ @method(egg_fn="-")
271
+ def __sub__(self, other: f64Like) -> f64: ...
272
+
273
+ @method(egg_fn="*")
274
+ def __mul__(self, other: f64Like) -> f64: ...
275
+
276
+ @method(egg_fn="/")
277
+ def __truediv__(self, other: f64Like) -> f64: ...
278
+
279
+ @method(egg_fn="%")
280
+ def __mod__(self, other: f64Like) -> f64: ...
281
+
282
+ @method(egg_fn="^")
283
+ def __pow__(self, other: f64Like) -> f64: ...
284
+
285
+ def __radd__(self, other: f64Like) -> f64: ...
286
+
287
+ def __rsub__(self, other: f64Like) -> f64: ...
288
+
289
+ def __rmul__(self, other: f64Like) -> f64: ...
290
+
291
+ def __rtruediv__(self, other: f64Like) -> f64: ...
292
+
293
+ def __rmod__(self, other: f64Like) -> f64: ...
294
+
295
+ @method(egg_fn="<")
296
+ def __lt__(self, other: f64Like) -> Unit: # type: ignore[empty-body,has-type]
297
+ ...
298
+
299
+ @method(egg_fn=">")
300
+ def __gt__(self, other: f64Like) -> Unit: ...
301
+
302
+ @method(egg_fn="<=")
303
+ def __le__(self, other: f64Like) -> Unit: # type: ignore[empty-body,has-type]
304
+ ...
305
+
306
+ @method(egg_fn=">=")
307
+ def __ge__(self, other: f64Like) -> Unit: ...
308
+
309
+ @method(egg_fn="min")
310
+ def min(self, other: f64Like) -> f64: ...
311
+
312
+ @method(egg_fn="max")
313
+ def max(self, other: f64Like) -> f64: ...
314
+
315
+ @method(egg_fn="to-i64")
316
+ def to_i64(self) -> i64: ...
317
+
318
+ @method(egg_fn="to-f64")
319
+ @classmethod
320
+ def from_i64(cls, i: i64) -> f64: ...
321
+
322
+ @method(egg_fn="to-string")
323
+ def to_string(self) -> String: ...
324
+
325
+
326
+ converter(float, f64, f64)
327
+
328
+
329
+ T = TypeVar("T", bound=BaseExpr)
330
+ V = TypeVar("V", bound=BaseExpr)
331
+
332
+
333
+ class Map(BuiltinExpr, Generic[T, V]):
334
+ @method(preserve=True)
335
+ def eval(self) -> dict[T, V]:
336
+ call = _extract_call(self)
337
+ expr = cast("RuntimeExpr", self)
338
+ d = {}
339
+ while call.callable != ClassMethodRef("Map", "empty"):
340
+ assert call.callable == MethodRef("Map", "insert")
341
+ call_typed, k_typed, v_typed = call.args
342
+ assert isinstance(call_typed.expr, CallDecl)
343
+ k = cast("T", expr.__with_expr__(k_typed))
344
+ v = cast("V", expr.__with_expr__(v_typed))
345
+ d[k] = v
346
+ call = call_typed.expr
347
+ return d
348
+
349
+ @method(preserve=True)
350
+ def __iter__(self) -> Iterator[T]:
351
+ return iter(self.eval())
352
+
353
+ @method(preserve=True)
354
+ def __len__(self) -> int:
355
+ return len(self.eval())
356
+
357
+ @method(preserve=True)
358
+ def __contains__(self, key: T) -> bool:
359
+ return key in self.eval()
360
+
361
+ @method(egg_fn="map-empty")
362
+ @classmethod
363
+ def empty(cls) -> Map[T, V]: ...
364
+
365
+ @method(egg_fn="map-insert")
366
+ def insert(self, key: T, value: V) -> Map[T, V]: ...
367
+
368
+ @method(egg_fn="map-get")
369
+ def __getitem__(self, key: T) -> V: ...
370
+
371
+ @method(egg_fn="map-not-contains")
372
+ def not_contains(self, key: T) -> Unit: ...
373
+
374
+ @method(egg_fn="map-contains")
375
+ def contains(self, key: T) -> Unit: ...
376
+
377
+ @method(egg_fn="map-remove")
378
+ def remove(self, key: T) -> Map[T, V]: ...
379
+
380
+ @method(egg_fn="rebuild")
381
+ def rebuild(self) -> Map[T, V]: ...
382
+
383
+
384
+ TO = TypeVar("TO")
385
+ VO = TypeVar("VO")
386
+
387
+ converter(
388
+ dict,
389
+ Map,
390
+ lambda t: reduce(
391
+ (lambda acc, kv: acc.insert(convert(kv[0], get_type_args()[0]), convert(kv[1], get_type_args()[1]))),
392
+ t.items(),
393
+ Map[get_type_args()].empty(), # type: ignore[misc]
394
+ ),
395
+ )
396
+
397
+ MapLike: TypeAlias = Map[T, V] | dict[TO, VO]
398
+
399
+
400
+ class Set(BuiltinExpr, Generic[T]):
401
+ @method(preserve=True)
402
+ def eval(self) -> set[T]:
403
+ call = _extract_call(self)
404
+ assert call.callable == InitRef("Set")
405
+ return {cast("T", cast("RuntimeExpr", self).__with_expr__(x)) for x in call.args}
406
+
407
+ @method(preserve=True)
408
+ def __iter__(self) -> Iterator[T]:
409
+ return iter(self.eval())
410
+
411
+ @method(preserve=True)
412
+ def __len__(self) -> int:
413
+ return len(self.eval())
414
+
415
+ @method(preserve=True)
416
+ def __contains__(self, key: T) -> bool:
417
+ return key in self.eval()
418
+
419
+ @method(egg_fn="set-of")
420
+ def __init__(self, *args: T) -> None: ...
421
+
422
+ @method(egg_fn="set-empty")
423
+ @classmethod
424
+ def empty(cls) -> Set[T]: ...
425
+
426
+ @method(egg_fn="set-insert")
427
+ def insert(self, value: T) -> Set[T]: ...
428
+
429
+ @method(egg_fn="set-not-contains")
430
+ def not_contains(self, value: T) -> Unit: ...
431
+
432
+ @method(egg_fn="set-contains")
433
+ def contains(self, value: T) -> Unit: ...
434
+
435
+ @method(egg_fn="set-remove")
436
+ def remove(self, value: T) -> Set[T]: ...
437
+
438
+ @method(egg_fn="set-union")
439
+ def __or__(self, other: Set[T]) -> Set[T]: ...
440
+
441
+ @method(egg_fn="set-diff")
442
+ def __sub__(self, other: Set[T]) -> Set[T]: ...
443
+
444
+ @method(egg_fn="set-intersect")
445
+ def __and__(self, other: Set[T]) -> Set[T]: ...
446
+
447
+ @method(egg_fn="rebuild")
448
+ def rebuild(self) -> Set[T]: ...
449
+
450
+
451
+ converter(
452
+ set,
453
+ Set,
454
+ lambda t: Set[get_type_args()[0]]( # type: ignore[misc,operator]
455
+ *(convert(x, get_type_args()[0]) for x in t)
456
+ ),
457
+ )
458
+
459
+ SetLike: TypeAlias = Set[T] | set[TO]
460
+
461
+
462
+ class MultiSet(BuiltinExpr, Generic[T]):
463
+ @method(preserve=True)
464
+ def eval(self) -> list[T]:
465
+ call = _extract_call(self)
466
+ assert call.callable == InitRef("MultiSet")
467
+ return [cast("T", cast("RuntimeExpr", self).__with_expr__(x)) for x in call.args]
468
+
469
+ @method(preserve=True)
470
+ def __iter__(self) -> Iterator[T]:
471
+ return iter(self.eval())
472
+
473
+ @method(preserve=True)
474
+ def __len__(self) -> int:
475
+ return len(self.eval())
476
+
477
+ @method(preserve=True)
478
+ def __contains__(self, key: T) -> bool:
479
+ return key in self.eval()
480
+
481
+ @method(egg_fn="multiset-of")
482
+ def __init__(self, *args: T) -> None: ...
483
+
484
+ @method(egg_fn="multiset-insert")
485
+ def insert(self, value: T) -> MultiSet[T]: ...
486
+
487
+ @method(egg_fn="multiset-not-contains")
488
+ def not_contains(self, value: T) -> Unit: ...
489
+
490
+ @method(egg_fn="multiset-contains")
491
+ def contains(self, value: T) -> Unit: ...
492
+
493
+ @method(egg_fn="multiset-remove")
494
+ def remove(self, value: T) -> MultiSet[T]: ...
495
+
496
+ @method(egg_fn="multiset-length")
497
+ def length(self) -> i64: ...
498
+
499
+ @method(egg_fn="multiset-pick")
500
+ def pick(self) -> T: ...
501
+
502
+ @method(egg_fn="multiset-sum")
503
+ def __add__(self, other: MultiSet[T]) -> MultiSet[T]: ...
504
+
505
+ @method(egg_fn="unstable-multiset-map", reverse_args=True)
506
+ def map(self, f: Callable[[T], T]) -> MultiSet[T]: ...
507
+
508
+
509
+ class Rational(BuiltinExpr):
510
+ @method(preserve=True)
511
+ def eval(self) -> Fraction:
512
+ call = _extract_call(self)
513
+ assert call.callable == InitRef("Rational")
514
+
515
+ def _to_int(e: TypedExprDecl) -> int:
516
+ expr = e.expr
517
+ assert isinstance(expr, LitDecl)
518
+ assert isinstance(expr.value, int)
519
+ return expr.value
520
+
521
+ num, den = call.args
522
+ return Fraction(_to_int(num), _to_int(den))
523
+
524
+ @method(preserve=True)
525
+ def __float__(self) -> float:
526
+ return float(self.eval())
527
+
528
+ @method(preserve=True)
529
+ def __int__(self) -> int:
530
+ return int(self.eval())
531
+
532
+ @method(egg_fn="rational")
533
+ def __init__(self, num: i64Like, den: i64Like) -> None: ...
534
+
535
+ @method(egg_fn="to-f64")
536
+ def to_f64(self) -> f64: ...
537
+
538
+ @method(egg_fn="+")
539
+ def __add__(self, other: Rational) -> Rational: ...
540
+
541
+ @method(egg_fn="-")
542
+ def __sub__(self, other: Rational) -> Rational: ...
543
+
544
+ @method(egg_fn="*")
545
+ def __mul__(self, other: Rational) -> Rational: ...
546
+
547
+ @method(egg_fn="/")
548
+ def __truediv__(self, other: Rational) -> Rational: ...
549
+
550
+ @method(egg_fn="min")
551
+ def min(self, other: Rational) -> Rational: ...
552
+
553
+ @method(egg_fn="max")
554
+ def max(self, other: Rational) -> Rational: ...
555
+
556
+ @method(egg_fn="neg")
557
+ def __neg__(self) -> Rational: ...
558
+
559
+ @method(egg_fn="abs")
560
+ def __abs__(self) -> Rational: ...
561
+
562
+ @method(egg_fn="floor")
563
+ def floor(self) -> Rational: ...
564
+
565
+ @method(egg_fn="ceil")
566
+ def ceil(self) -> Rational: ...
567
+
568
+ @method(egg_fn="round")
569
+ def round(self) -> Rational: ...
570
+
571
+ @method(egg_fn="pow")
572
+ def __pow__(self, other: Rational) -> Rational: ...
573
+
574
+ @method(egg_fn="log")
575
+ def log(self) -> Rational: ...
576
+
577
+ @method(egg_fn="sqrt")
578
+ def sqrt(self) -> Rational: ...
579
+
580
+ @method(egg_fn="cbrt")
581
+ def cbrt(self) -> Rational: ...
582
+
583
+ @method(egg_fn="numer") # type: ignore[misc]
584
+ @property
585
+ def numer(self) -> i64: ...
586
+
587
+ @method(egg_fn="denom") # type: ignore[misc]
588
+ @property
589
+ def denom(self) -> i64: ...
590
+
591
+
592
+ class BigInt(BuiltinExpr):
593
+ @method(preserve=True)
594
+ def eval(self) -> int:
595
+ call = _extract_call(self)
596
+ assert call.callable == ClassMethodRef("BigInt", "from_string")
597
+ (s,) = call.args
598
+ assert isinstance(s.expr, LitDecl)
599
+ assert isinstance(s.expr.value, str)
600
+ return int(s.expr.value)
601
+
602
+ @method(preserve=True)
603
+ def __index__(self) -> int:
604
+ return self.eval()
605
+
606
+ @method(preserve=True)
607
+ def __int__(self) -> int:
608
+ return self.eval()
609
+
610
+ @method(egg_fn="from-string")
611
+ @classmethod
612
+ def from_string(cls, s: StringLike) -> BigInt: ...
613
+
614
+ @method(egg_fn="bigint")
615
+ def __init__(self, value: i64Like) -> None: ...
616
+
617
+ @method(egg_fn="+")
618
+ def __add__(self, other: BigIntLike) -> BigInt: ...
619
+
620
+ @method(egg_fn="-")
621
+ def __sub__(self, other: BigIntLike) -> BigInt: ...
622
+
623
+ @method(egg_fn="*")
624
+ def __mul__(self, other: BigIntLike) -> BigInt: ...
625
+
626
+ @method(egg_fn="/")
627
+ def __truediv__(self, other: BigIntLike) -> BigInt: ...
628
+
629
+ @method(egg_fn="%")
630
+ def __mod__(self, other: BigIntLike) -> BigInt: ...
631
+
632
+ @method(egg_fn="&")
633
+ def __and__(self, other: BigIntLike) -> BigInt: ...
634
+
635
+ @method(egg_fn="|")
636
+ def __or__(self, other: BigIntLike) -> BigInt: ...
637
+
638
+ @method(egg_fn="^")
639
+ def __xor__(self, other: BigIntLike) -> BigInt: ...
640
+
641
+ @method(egg_fn="<<")
642
+ def __lshift__(self, other: i64Like) -> BigInt: ...
643
+
644
+ @method(egg_fn=">>")
645
+ def __rshift__(self, other: i64Like) -> BigInt: ...
646
+
647
+ def __radd__(self, other: BigIntLike) -> BigInt: ...
648
+
649
+ def __rsub__(self, other: BigIntLike) -> BigInt: ...
650
+
651
+ def __rmul__(self, other: BigIntLike) -> BigInt: ...
652
+
653
+ def __rtruediv__(self, other: BigIntLike) -> BigInt: ...
654
+
655
+ def __rmod__(self, other: BigIntLike) -> BigInt: ...
656
+
657
+ def __rand__(self, other: BigIntLike) -> BigInt: ...
658
+
659
+ def __ror__(self, other: BigIntLike) -> BigInt: ...
660
+
661
+ def __rxor__(self, other: BigIntLike) -> BigInt: ...
662
+
663
+ @method(egg_fn="not-Z")
664
+ def __invert__(self) -> BigInt: ...
665
+
666
+ @method(egg_fn="bits")
667
+ def bits(self) -> BigInt: ...
668
+
669
+ @method(egg_fn="<")
670
+ def __lt__(self, other: BigIntLike) -> Unit: # type: ignore[empty-body,has-type]
671
+ ...
672
+
673
+ @method(egg_fn=">")
674
+ def __gt__(self, other: BigIntLike) -> Unit: ...
675
+
676
+ @method(egg_fn="<=")
677
+ def __le__(self, other: BigIntLike) -> Unit: # type: ignore[empty-body,has-type]
678
+ ...
679
+
680
+ @method(egg_fn=">=")
681
+ def __ge__(self, other: BigIntLike) -> Unit: ...
682
+
683
+ @method(egg_fn="min")
684
+ def min(self, other: BigIntLike) -> BigInt: ...
685
+
686
+ @method(egg_fn="max")
687
+ def max(self, other: BigIntLike) -> BigInt: ...
688
+
689
+ @method(egg_fn="to-string")
690
+ def to_string(self) -> String: ...
691
+
692
+ @method(egg_fn="bool-=")
693
+ def bool_eq(self, other: BigIntLike) -> Bool: ...
694
+
695
+ @method(egg_fn="bool-<")
696
+ def bool_lt(self, other: BigIntLike) -> Bool: ...
697
+
698
+ @method(egg_fn="bool->")
699
+ def bool_gt(self, other: BigIntLike) -> Bool: ...
700
+
701
+ @method(egg_fn="bool-<=")
702
+ def bool_le(self, other: BigIntLike) -> Bool: ...
703
+
704
+ @method(egg_fn="bool->=")
705
+ def bool_ge(self, other: BigIntLike) -> Bool: ...
706
+
707
+
708
+ converter(i64, BigInt, lambda i: BigInt(i))
709
+
710
+ BigIntLike: TypeAlias = BigInt | i64Like
711
+
712
+
713
+ class BigRat(BuiltinExpr):
714
+ @method(preserve=True)
715
+ def eval(self) -> Fraction:
716
+ call = _extract_call(self)
717
+ assert call.callable == InitRef("BigRat")
718
+
719
+ def _to_fraction(e: TypedExprDecl) -> Fraction:
720
+ expr = e.expr
721
+ assert isinstance(expr, CallDecl)
722
+ assert expr.callable == ClassMethodRef("BigInt", "from_string")
723
+ (s,) = expr.args
724
+ assert isinstance(s.expr, LitDecl)
725
+ assert isinstance(s.expr.value, str)
726
+ return Fraction(s.expr.value)
727
+
728
+ num, den = call.args
729
+ return Fraction(_to_fraction(num), _to_fraction(den))
730
+
731
+ @method(preserve=True)
732
+ def __float__(self) -> float:
733
+ return float(self.eval())
734
+
735
+ @method(preserve=True)
736
+ def __int__(self) -> int:
737
+ return int(self.eval())
738
+
739
+ @method(egg_fn="bigrat")
740
+ def __init__(self, num: BigIntLike, den: BigIntLike) -> None: ...
741
+
742
+ @method(egg_fn="to-f64")
743
+ def to_f64(self) -> f64: ...
744
+
745
+ @method(egg_fn="+")
746
+ def __add__(self, other: BigRatLike) -> BigRat: ...
747
+
748
+ @method(egg_fn="-")
749
+ def __sub__(self, other: BigRatLike) -> BigRat: ...
750
+
751
+ @method(egg_fn="*")
752
+ def __mul__(self, other: BigRatLike) -> BigRat: ...
753
+
754
+ @method(egg_fn="/")
755
+ def __truediv__(self, other: BigRatLike) -> BigRat: ...
756
+
757
+ @method(egg_fn="min")
758
+ def min(self, other: BigRatLike) -> BigRat: ...
759
+
760
+ @method(egg_fn="max")
761
+ def max(self, other: BigRatLike) -> BigRat: ...
762
+
763
+ @method(egg_fn="neg")
764
+ def __neg__(self) -> BigRat: ...
765
+
766
+ @method(egg_fn="abs")
767
+ def __abs__(self) -> BigRat: ...
768
+
769
+ @method(egg_fn="floor")
770
+ def floor(self) -> BigRat: ...
771
+
772
+ @method(egg_fn="ceil")
773
+ def ceil(self) -> BigRat: ...
774
+
775
+ @method(egg_fn="round")
776
+ def round(self) -> BigRat: ...
777
+
778
+ @method(egg_fn="pow")
779
+ def __pow__(self, other: BigRatLike) -> BigRat: ...
780
+
781
+ @method(egg_fn="log")
782
+ def log(self) -> BigRat: ...
783
+
784
+ @method(egg_fn="sqrt")
785
+ def sqrt(self) -> BigRat: ...
786
+
787
+ @method(egg_fn="cbrt")
788
+ def cbrt(self) -> BigRat: ...
789
+
790
+ @method(egg_fn="numer") # type: ignore[misc]
791
+ @property
792
+ def numer(self) -> BigInt: ...
793
+
794
+ @method(egg_fn="denom") # type: ignore[misc]
795
+ @property
796
+ def denom(self) -> BigInt: ...
797
+
798
+ @method(egg_fn="<")
799
+ def __lt__(self, other: BigRatLike) -> Unit: ... # type: ignore[has-type]
800
+
801
+ @method(egg_fn=">")
802
+ def __gt__(self, other: BigRatLike) -> Unit: ...
803
+
804
+ @method(egg_fn=">=")
805
+ def __ge__(self, other: BigRatLike) -> Unit: ... # type: ignore[has-type]
806
+
807
+ @method(egg_fn="<=")
808
+ def __le__(self, other: BigRatLike) -> Unit: ...
809
+
810
+
811
+ converter(Fraction, BigRat, lambda f: BigRat(f.numerator, f.denominator))
812
+ BigRatLike: TypeAlias = BigRat | Fraction
813
+
814
+
815
+ class Vec(BuiltinExpr, Generic[T]):
816
+ @method(preserve=True)
817
+ def eval(self) -> tuple[T, ...]:
818
+ call = _extract_call(self)
819
+ if call.callable == ClassMethodRef("Vec", "empty"):
820
+ return ()
821
+ assert call.callable == InitRef("Vec")
822
+ return tuple(cast("T", cast("RuntimeExpr", self).__with_expr__(x)) for x in call.args)
823
+
824
+ @method(preserve=True)
825
+ def __iter__(self) -> Iterator[T]:
826
+ return iter(self.eval())
827
+
828
+ @method(preserve=True)
829
+ def __len__(self) -> int:
830
+ return len(self.eval())
831
+
832
+ @method(preserve=True)
833
+ def __contains__(self, key: T) -> bool:
834
+ return key in self.eval()
835
+
836
+ @method(egg_fn="vec-of")
837
+ def __init__(self, *args: T) -> None: ...
838
+
839
+ @method(egg_fn="vec-empty")
840
+ @classmethod
841
+ def empty(cls) -> Vec[T]: ...
842
+
843
+ @method(egg_fn="vec-append")
844
+ def append(self, *others: Vec[T]) -> Vec[T]: ...
845
+
846
+ @method(egg_fn="vec-push")
847
+ def push(self, value: T) -> Vec[T]: ...
848
+
849
+ @method(egg_fn="vec-pop")
850
+ def pop(self) -> Vec[T]: ...
851
+
852
+ @method(egg_fn="vec-not-contains")
853
+ def not_contains(self, value: T) -> Unit: ...
854
+
855
+ @method(egg_fn="vec-contains")
856
+ def contains(self, value: T) -> Unit: ...
857
+
858
+ @method(egg_fn="vec-length")
859
+ def length(self) -> i64: ...
860
+
861
+ @method(egg_fn="vec-get")
862
+ def __getitem__(self, index: i64Like) -> T: ...
863
+
864
+ @method(egg_fn="rebuild")
865
+ def rebuild(self) -> Vec[T]: ...
866
+
867
+ @method(egg_fn="vec-remove")
868
+ def remove(self, index: i64Like) -> Vec[T]: ...
869
+
870
+ @method(egg_fn="vec-set")
871
+ def set(self, index: i64Like, value: T) -> Vec[T]: ...
872
+
873
+
874
+ for sequence_type in (list, tuple):
875
+ converter(
876
+ sequence_type,
877
+ Vec,
878
+ lambda t: Vec[get_type_args()[0]]( # type: ignore[misc,operator]
879
+ *(convert(x, get_type_args()[0]) for x in t)
880
+ ),
881
+ )
882
+
883
+ VecLike: TypeAlias = Vec[T] | tuple[TO, ...] | list[TO]
884
+
885
+
886
+ class PyObject(BuiltinExpr):
887
+ @method(preserve=True)
888
+ def eval(self) -> object:
889
+ report = (EGraph.current or EGraph())._run_extract(cast("RuntimeExpr", self), 0)
890
+ assert isinstance(report, bindings.Best)
891
+ expr = report.termdag.term_to_expr(report.term, bindings.PanicSpan())
892
+ return GLOBAL_PY_OBJECT_SORT.load(expr)
893
+
894
+ def __init__(self, value: object) -> None: ...
895
+
896
+ @method(egg_fn="py-from-string")
897
+ @classmethod
898
+ def from_string(cls, s: StringLike) -> PyObject: ...
899
+
900
+ @method(egg_fn="py-to-string")
901
+ def to_string(self) -> String: ...
902
+
903
+ @method(egg_fn="py-to-bool")
904
+ def to_bool(self) -> Bool: ...
905
+
906
+ @method(egg_fn="py-dict-update")
907
+ def dict_update(self, *keys_and_values: object) -> PyObject: ...
908
+
909
+ @method(egg_fn="py-from-int")
910
+ @classmethod
911
+ def from_int(cls, i: i64Like) -> PyObject: ...
912
+
913
+ @method(egg_fn="py-dict")
914
+ @classmethod
915
+ def dict(cls, *keys_and_values: object) -> PyObject: ...
916
+
917
+
918
+ converter(object, PyObject, PyObject)
919
+
920
+
921
+ @function(builtin=True, egg_fn="py-eval")
922
+ def py_eval(code: StringLike, globals: object = PyObject.dict(), locals: object = PyObject.dict()) -> PyObject: ...
923
+
924
+
925
+ class PyObjectFunction(Protocol):
926
+ def __call__(self, *__args: PyObject) -> PyObject: ...
927
+
928
+
929
+ def py_eval_fn(fn: Callable) -> PyObjectFunction:
930
+ """
931
+ Takes a python callable and maps it to a callable which takes and returns PyObjects.
932
+
933
+ It translates it to a call which uses `py_eval` to call the function, passing in the
934
+ args as locals, and using the globals from function.
935
+ """
936
+
937
+ def inner(*__args: PyObject, __fn: Callable = fn) -> PyObject:
938
+ new_kvs: list[object] = []
939
+ eval_str = "__fn("
940
+ for i, arg in enumerate(__args):
941
+ new_kvs.extend((f"__arg_{i}", arg))
942
+ eval_str += f"__arg_{i}, "
943
+ eval_str += ")"
944
+ return py_eval(eval_str, PyObject({"__fn": __fn}).dict_update(*new_kvs), __fn.__globals__)
945
+
946
+ return inner
947
+
948
+
949
+ @function(builtin=True, egg_fn="py-exec")
950
+ def py_exec(code: StringLike, globals: object = PyObject.dict(), locals: object = PyObject.dict()) -> PyObject:
951
+ """
952
+ Copies the locals, execs the Python code, and returns the locals with any updates.
953
+ """
954
+
955
+
956
+ TS = TypeVarTuple("TS")
957
+
958
+ T1 = TypeVar("T1")
959
+ T2 = TypeVar("T2")
960
+ T3 = TypeVar("T3")
961
+
962
+
963
+ class UnstableFn(BuiltinExpr, Generic[T, Unpack[TS]]):
964
+ @overload
965
+ def __init__(self, f: Callable[[Unpack[TS]], T]) -> None: ...
966
+
967
+ @overload
968
+ def __init__(self, f: Callable[[T1, Unpack[TS]], T], _a: T1, /) -> None: ...
969
+
970
+ @overload
971
+ def __init__(self, f: Callable[[T1, T2, Unpack[TS]], T], _a: T1, _b: T2, /) -> None: ...
972
+
973
+ # Removing due to bug in MyPy
974
+ # https://github.com/python/mypy/issues/17212
975
+ # @overload
976
+ # def __init__(self, f: Callable[[T1, T2, T3, Unpack[TS]], T], _a: T1, _b: T2, _c: T3, /) -> None: ...
977
+
978
+ # etc, for partial application
979
+
980
+ @method(egg_fn="unstable-fn")
981
+ def __init__(self, f, *partial) -> None: ...
982
+
983
+ @method(egg_fn="unstable-app")
984
+ def __call__(self, *args: Unpack[TS]) -> T: ...
985
+
986
+
987
+ # Method Type is for builtins like __getitem__
988
+ converter(MethodType, UnstableFn, lambda m: UnstableFn(m.__func__, m.__self__))
989
+ converter(RuntimeFunction, UnstableFn, UnstableFn)
990
+ converter(partial, UnstableFn, lambda p: UnstableFn(p.func, *p.args))
991
+
992
+
993
+ def _convert_function(a: FunctionType) -> UnstableFn:
994
+ """
995
+ Converts a function type to an unstable function
996
+
997
+ Would just be UnstableFn(function(a)) but we have to look for any nonlocals and globals
998
+ which are runtime expressions with `var`s in them and add them as args to the function
999
+ """
1000
+ # Update annotations of a to be the type we are trying to convert to
1001
+ return_tp, *arg_tps = get_type_args()
1002
+ a.__annotations__ = {
1003
+ "return": return_tp,
1004
+ # The first varnames should always be the arg names
1005
+ **dict(zip(a.__code__.co_varnames, arg_tps, strict=False)),
1006
+ }
1007
+ # Modify name to make it unique
1008
+ # a.__name__ = f"{a.__name__} {hash(a.__code__)}"
1009
+ transformed_fn = functionalize(a, value_to_annotation)
1010
+ assert isinstance(transformed_fn, partial)
1011
+ return UnstableFn(
1012
+ function(ruleset=get_current_ruleset(), use_body_as_name=True, subsume=True)(transformed_fn.func),
1013
+ *transformed_fn.args,
1014
+ )
1015
+
1016
+
1017
+ def value_to_annotation(a: object) -> type | None:
1018
+ # only lift runtime expressions (which could contain vars) not any other nonlocals/globals we use in the function
1019
+ if not isinstance(a, RuntimeExpr):
1020
+ return None
1021
+ return cast("type", RuntimeClass(Thunk.value(a.__egg_decls__), a.__egg_typed_expr__.tp.to_var()))
1022
+
1023
+
1024
+ converter(FunctionType, UnstableFn, _convert_function)
1025
+
1026
+
1027
+ def _extract_lit(e: BaseExpr) -> bindings._Literal:
1028
+ """
1029
+ Special case extracting literals to make this faster by using termdag directly.
1030
+ """
1031
+ report = (EGraph.current or EGraph())._run_extract(cast("RuntimeExpr", e), 0)
1032
+ assert isinstance(report, bindings.Best)
1033
+ term = report.term
1034
+ assert isinstance(term, bindings.TermLit)
1035
+ return term.value
1036
+
1037
+
1038
+ def _extract_call(e: BaseExpr) -> CallDecl:
1039
+ """
1040
+ Extracts the call form of an expression
1041
+ """
1042
+ extracted = cast("RuntimeExpr", (EGraph.current or EGraph()).extract(e))
1043
+ expr = extracted.__egg_typed_expr__.expr
1044
+ assert isinstance(expr, CallDecl)
1045
+ return expr