egglog 10.0.2__cp310-cp310-win_amd64.whl → 11.0.0__cp310-cp310-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/__init__.py +3 -1
- egglog/bindings.cp310-win_amd64.pyd +0 -0
- egglog/bindings.pyi +26 -34
- egglog/builtins.py +221 -173
- egglog/conversion.py +61 -43
- egglog/declarations.py +103 -17
- egglog/deconstruct.py +173 -0
- egglog/egraph.py +77 -129
- egglog/egraph_state.py +17 -14
- egglog/examples/bignum.py +1 -1
- egglog/examples/multiset.py +2 -2
- egglog/exp/array_api.py +37 -3
- egglog/exp/array_api_jit.py +11 -5
- egglog/exp/array_api_program_gen.py +1 -1
- egglog/pretty.py +11 -25
- egglog/runtime.py +197 -147
- egglog/version_compat.py +2 -2
- {egglog-10.0.2.dist-info → egglog-11.0.0.dist-info}/METADATA +1 -1
- {egglog-10.0.2.dist-info → egglog-11.0.0.dist-info}/RECORD +21 -21
- {egglog-10.0.2.dist-info → egglog-11.0.0.dist-info}/WHEEL +1 -1
- egglog/functionalize.py +0 -91
- {egglog-10.0.2.dist-info → egglog-11.0.0.dist-info}/licenses/LICENSE +0 -0
egglog/builtins.py
CHANGED
|
@@ -6,18 +6,20 @@ Builtin sorts and function to egg.
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
from collections.abc import Callable
|
|
9
|
+
from dataclasses import dataclass
|
|
9
10
|
from fractions import Fraction
|
|
10
11
|
from functools import partial, reduce
|
|
12
|
+
from inspect import signature
|
|
11
13
|
from types import FunctionType, MethodType
|
|
12
14
|
from typing import TYPE_CHECKING, Generic, Protocol, TypeAlias, TypeVar, cast, overload
|
|
13
15
|
|
|
14
|
-
from typing_extensions import TypeVarTuple, Unpack
|
|
16
|
+
from typing_extensions import TypeVarTuple, Unpack, deprecated
|
|
15
17
|
|
|
16
|
-
from .conversion import convert, converter, get_type_args
|
|
18
|
+
from .conversion import convert, converter, get_type_args, resolve_literal
|
|
17
19
|
from .declarations import *
|
|
18
|
-
from .
|
|
19
|
-
from .
|
|
20
|
-
from .runtime import
|
|
20
|
+
from .deconstruct import get_callable_args, get_literal_value
|
|
21
|
+
from .egraph import BaseExpr, BuiltinExpr, _add_default_rewrite_inner, expr_fact, function, get_current_ruleset, method
|
|
22
|
+
from .runtime import RuntimeExpr, RuntimeFunction, resolve_type_annotation_mutate
|
|
21
23
|
from .thunk import Thunk
|
|
22
24
|
|
|
23
25
|
if TYPE_CHECKING:
|
|
@@ -31,7 +33,7 @@ __all__ = [
|
|
|
31
33
|
"BigRatLike",
|
|
32
34
|
"Bool",
|
|
33
35
|
"BoolLike",
|
|
34
|
-
"
|
|
36
|
+
"ExprValueError",
|
|
35
37
|
"Map",
|
|
36
38
|
"MapLike",
|
|
37
39
|
"MultiSet",
|
|
@@ -56,15 +58,17 @@ __all__ = [
|
|
|
56
58
|
]
|
|
57
59
|
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
@dataclass
|
|
62
|
+
class ExprValueError(AttributeError):
|
|
60
63
|
"""
|
|
61
|
-
Raised when an
|
|
62
|
-
|
|
63
|
-
Try extracting this expression first.
|
|
64
|
+
Raised when an expression cannot be converted to a Python value because the value is not a constructor.
|
|
64
65
|
"""
|
|
65
66
|
|
|
67
|
+
expr: BaseExpr
|
|
68
|
+
allowed: str
|
|
69
|
+
|
|
66
70
|
def __str__(self) -> str:
|
|
67
|
-
return f"Cannot
|
|
71
|
+
return f"Cannot get Python value of {self.expr}, must be of form {self.allowed}. Try calling `extract` on it to get the underlying value."
|
|
68
72
|
|
|
69
73
|
|
|
70
74
|
class Unit(BuiltinExpr, egg_sort="Unit"):
|
|
@@ -80,13 +84,21 @@ class Unit(BuiltinExpr, egg_sort="Unit"):
|
|
|
80
84
|
|
|
81
85
|
|
|
82
86
|
class String(BuiltinExpr):
|
|
87
|
+
def __init__(self, value: str) -> None: ...
|
|
88
|
+
|
|
83
89
|
@method(preserve=True)
|
|
90
|
+
@deprecated("use .value")
|
|
84
91
|
def eval(self) -> str:
|
|
85
|
-
|
|
86
|
-
assert isinstance(value, str)
|
|
87
|
-
return value
|
|
92
|
+
return self.value
|
|
88
93
|
|
|
89
|
-
|
|
94
|
+
@method(preserve=True) # type: ignore[misc]
|
|
95
|
+
@property
|
|
96
|
+
def value(self) -> str:
|
|
97
|
+
if (value := get_literal_value(self)) is not None:
|
|
98
|
+
return value
|
|
99
|
+
raise ExprValueError(self, "String")
|
|
100
|
+
|
|
101
|
+
__match_args__ = ("value",)
|
|
90
102
|
|
|
91
103
|
@method(egg_fn="replace")
|
|
92
104
|
def replace(self, old: StringLike, new: StringLike) -> String: ...
|
|
@@ -103,17 +115,25 @@ converter(str, String, String)
|
|
|
103
115
|
|
|
104
116
|
|
|
105
117
|
class Bool(BuiltinExpr, egg_sort="bool"):
|
|
118
|
+
def __init__(self, value: bool) -> None: ...
|
|
119
|
+
|
|
106
120
|
@method(preserve=True)
|
|
121
|
+
@deprecated("use .value")
|
|
107
122
|
def eval(self) -> bool:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
123
|
+
return self.value
|
|
124
|
+
|
|
125
|
+
@method(preserve=True) # type: ignore[misc]
|
|
126
|
+
@property
|
|
127
|
+
def value(self) -> bool:
|
|
128
|
+
if (value := get_literal_value(self)) is not None:
|
|
129
|
+
return value
|
|
130
|
+
raise ExprValueError(self, "Bool")
|
|
131
|
+
|
|
132
|
+
__match_args__ = ("value",)
|
|
111
133
|
|
|
112
134
|
@method(preserve=True)
|
|
113
135
|
def __bool__(self) -> bool:
|
|
114
|
-
return self.
|
|
115
|
-
|
|
116
|
-
def __init__(self, value: bool) -> None: ...
|
|
136
|
+
return self.value
|
|
117
137
|
|
|
118
138
|
@method(egg_fn="not")
|
|
119
139
|
def __invert__(self) -> Bool: ...
|
|
@@ -138,21 +158,29 @@ converter(bool, Bool, Bool)
|
|
|
138
158
|
|
|
139
159
|
|
|
140
160
|
class i64(BuiltinExpr): # noqa: N801
|
|
161
|
+
def __init__(self, value: int) -> None: ...
|
|
162
|
+
|
|
141
163
|
@method(preserve=True)
|
|
164
|
+
@deprecated("use .value")
|
|
142
165
|
def eval(self) -> int:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
166
|
+
return self.value
|
|
167
|
+
|
|
168
|
+
@method(preserve=True) # type: ignore[misc]
|
|
169
|
+
@property
|
|
170
|
+
def value(self) -> int:
|
|
171
|
+
if (value := get_literal_value(self)) is not None:
|
|
172
|
+
return value
|
|
173
|
+
raise ExprValueError(self, "i64")
|
|
174
|
+
|
|
175
|
+
__match_args__ = ("value",)
|
|
146
176
|
|
|
147
177
|
@method(preserve=True)
|
|
148
178
|
def __index__(self) -> int:
|
|
149
|
-
return self.
|
|
179
|
+
return self.value
|
|
150
180
|
|
|
151
181
|
@method(preserve=True)
|
|
152
182
|
def __int__(self) -> int:
|
|
153
|
-
return self.
|
|
154
|
-
|
|
155
|
-
def __init__(self, value: int) -> None: ...
|
|
183
|
+
return self.value
|
|
156
184
|
|
|
157
185
|
@method(egg_fn="+")
|
|
158
186
|
def __add__(self, other: i64Like) -> i64: ...
|
|
@@ -257,21 +285,29 @@ def count_matches(s: StringLike, pattern: StringLike) -> i64: ...
|
|
|
257
285
|
|
|
258
286
|
|
|
259
287
|
class f64(BuiltinExpr): # noqa: N801
|
|
288
|
+
def __init__(self, value: float) -> None: ...
|
|
289
|
+
|
|
260
290
|
@method(preserve=True)
|
|
291
|
+
@deprecated("use .value")
|
|
261
292
|
def eval(self) -> float:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
293
|
+
return self.value
|
|
294
|
+
|
|
295
|
+
@method(preserve=True) # type: ignore[misc]
|
|
296
|
+
@property
|
|
297
|
+
def value(self) -> float:
|
|
298
|
+
if (value := get_literal_value(self)) is not None:
|
|
299
|
+
return value
|
|
300
|
+
raise ExprValueError(self, "f64")
|
|
301
|
+
|
|
302
|
+
__match_args__ = ("value",)
|
|
265
303
|
|
|
266
304
|
@method(preserve=True)
|
|
267
305
|
def __float__(self) -> float:
|
|
268
|
-
return self.
|
|
306
|
+
return self.value
|
|
269
307
|
|
|
270
308
|
@method(preserve=True)
|
|
271
309
|
def __int__(self) -> int:
|
|
272
|
-
return int(self.
|
|
273
|
-
|
|
274
|
-
def __init__(self, value: float) -> None: ...
|
|
310
|
+
return int(self.value)
|
|
275
311
|
|
|
276
312
|
@method(egg_fn="neg")
|
|
277
313
|
def __neg__(self) -> f64: ...
|
|
@@ -347,34 +383,34 @@ V = TypeVar("V", bound=BaseExpr)
|
|
|
347
383
|
|
|
348
384
|
class Map(BuiltinExpr, Generic[T, V]):
|
|
349
385
|
@method(preserve=True)
|
|
386
|
+
@deprecated("use .value")
|
|
350
387
|
def eval(self) -> dict[T, V]:
|
|
351
|
-
|
|
352
|
-
|
|
388
|
+
return self.value
|
|
389
|
+
|
|
390
|
+
@method(preserve=True) # type: ignore[misc]
|
|
391
|
+
@property
|
|
392
|
+
def value(self) -> dict[T, V]:
|
|
353
393
|
d = {}
|
|
354
|
-
while
|
|
355
|
-
|
|
356
|
-
if call.callable != MethodRef("Map", "insert"):
|
|
357
|
-
raise BuiltinEvalError(msg)
|
|
358
|
-
call_typed, k_typed, v_typed = call.args
|
|
359
|
-
if not isinstance(call_typed.expr, CallDecl):
|
|
360
|
-
raise BuiltinEvalError(msg)
|
|
361
|
-
k = cast("T", expr.__with_expr__(k_typed))
|
|
362
|
-
v = cast("V", expr.__with_expr__(v_typed))
|
|
394
|
+
while args := get_callable_args(self, Map[T, V].insert):
|
|
395
|
+
self, k, v = args # noqa: PLW0642
|
|
363
396
|
d[k] = v
|
|
364
|
-
|
|
397
|
+
if get_callable_args(self, Map.empty) is None:
|
|
398
|
+
raise ExprValueError(self, "Map.empty or Map.insert")
|
|
365
399
|
return d
|
|
366
400
|
|
|
401
|
+
__match_args__ = ("value",)
|
|
402
|
+
|
|
367
403
|
@method(preserve=True)
|
|
368
404
|
def __iter__(self) -> Iterator[T]:
|
|
369
|
-
return iter(self.
|
|
405
|
+
return iter(self.value)
|
|
370
406
|
|
|
371
407
|
@method(preserve=True)
|
|
372
408
|
def __len__(self) -> int:
|
|
373
|
-
return len(self.
|
|
409
|
+
return len(self.value)
|
|
374
410
|
|
|
375
411
|
@method(preserve=True)
|
|
376
412
|
def __contains__(self, key: T) -> bool:
|
|
377
|
-
return key in self.
|
|
413
|
+
return key in self.value
|
|
378
414
|
|
|
379
415
|
@method(egg_fn="map-empty")
|
|
380
416
|
@classmethod
|
|
@@ -417,24 +453,30 @@ MapLike: TypeAlias = Map[T, V] | dict[TO, VO]
|
|
|
417
453
|
|
|
418
454
|
class Set(BuiltinExpr, Generic[T]):
|
|
419
455
|
@method(preserve=True)
|
|
456
|
+
@deprecated("use .value")
|
|
420
457
|
def eval(self) -> set[T]:
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
458
|
+
return self.value
|
|
459
|
+
|
|
460
|
+
@method(preserve=True) # type: ignore[misc]
|
|
461
|
+
@property
|
|
462
|
+
def value(self) -> set[T]:
|
|
463
|
+
if (args := get_callable_args(self, Set[T])) is not None:
|
|
464
|
+
return set(args)
|
|
465
|
+
raise ExprValueError(self, "Set(*xs)")
|
|
466
|
+
|
|
467
|
+
__match_args__ = ("value",)
|
|
426
468
|
|
|
427
469
|
@method(preserve=True)
|
|
428
470
|
def __iter__(self) -> Iterator[T]:
|
|
429
|
-
return iter(self.
|
|
471
|
+
return iter(self.value)
|
|
430
472
|
|
|
431
473
|
@method(preserve=True)
|
|
432
474
|
def __len__(self) -> int:
|
|
433
|
-
return len(self.
|
|
475
|
+
return len(self.value)
|
|
434
476
|
|
|
435
477
|
@method(preserve=True)
|
|
436
478
|
def __contains__(self, key: T) -> bool:
|
|
437
|
-
return key in self.
|
|
479
|
+
return key in self.value
|
|
438
480
|
|
|
439
481
|
@method(egg_fn="set-of")
|
|
440
482
|
def __init__(self, *args: T) -> None: ...
|
|
@@ -481,24 +523,30 @@ SetLike: TypeAlias = Set[T] | set[TO]
|
|
|
481
523
|
|
|
482
524
|
class MultiSet(BuiltinExpr, Generic[T]):
|
|
483
525
|
@method(preserve=True)
|
|
526
|
+
@deprecated("use .value")
|
|
484
527
|
def eval(self) -> list[T]:
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
528
|
+
return self.value
|
|
529
|
+
|
|
530
|
+
@method(preserve=True) # type: ignore[misc]
|
|
531
|
+
@property
|
|
532
|
+
def value(self) -> list[T]:
|
|
533
|
+
if (args := get_callable_args(self, MultiSet[T])) is not None:
|
|
534
|
+
return list(args)
|
|
535
|
+
raise ExprValueError(self, "MultiSet")
|
|
536
|
+
|
|
537
|
+
__match_args__ = ("value",)
|
|
490
538
|
|
|
491
539
|
@method(preserve=True)
|
|
492
540
|
def __iter__(self) -> Iterator[T]:
|
|
493
|
-
return iter(self.
|
|
541
|
+
return iter(self.value)
|
|
494
542
|
|
|
495
543
|
@method(preserve=True)
|
|
496
544
|
def __len__(self) -> int:
|
|
497
|
-
return len(self.
|
|
545
|
+
return len(self.value)
|
|
498
546
|
|
|
499
547
|
@method(preserve=True)
|
|
500
548
|
def __contains__(self, key: T) -> bool:
|
|
501
|
-
return key in self.
|
|
549
|
+
return key in self.value
|
|
502
550
|
|
|
503
551
|
@method(egg_fn="multiset-of")
|
|
504
552
|
def __init__(self, *args: T) -> None: ...
|
|
@@ -530,30 +578,27 @@ class MultiSet(BuiltinExpr, Generic[T]):
|
|
|
530
578
|
|
|
531
579
|
class Rational(BuiltinExpr):
|
|
532
580
|
@method(preserve=True)
|
|
581
|
+
@deprecated("use .value")
|
|
533
582
|
def eval(self) -> Fraction:
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
return expr.value
|
|
546
|
-
|
|
547
|
-
num, den = call.args
|
|
548
|
-
return Fraction(_to_int(num), _to_int(den))
|
|
583
|
+
return self.value
|
|
584
|
+
|
|
585
|
+
@method(preserve=True) # type: ignore[misc]
|
|
586
|
+
@property
|
|
587
|
+
def value(self) -> Fraction:
|
|
588
|
+
match get_callable_args(self, Rational):
|
|
589
|
+
case (i64(num), i64(den)):
|
|
590
|
+
return Fraction(num, den)
|
|
591
|
+
raise ExprValueError(self, "Rational(i64(num), i64(den))")
|
|
592
|
+
|
|
593
|
+
__match_args__ = ("value",)
|
|
549
594
|
|
|
550
595
|
@method(preserve=True)
|
|
551
596
|
def __float__(self) -> float:
|
|
552
|
-
return float(self.
|
|
597
|
+
return float(self.value)
|
|
553
598
|
|
|
554
599
|
@method(preserve=True)
|
|
555
600
|
def __int__(self) -> int:
|
|
556
|
-
return int(self.
|
|
601
|
+
return int(self.value)
|
|
557
602
|
|
|
558
603
|
@method(egg_fn="rational")
|
|
559
604
|
def __init__(self, num: i64Like, den: i64Like) -> None: ...
|
|
@@ -617,25 +662,27 @@ class Rational(BuiltinExpr):
|
|
|
617
662
|
|
|
618
663
|
class BigInt(BuiltinExpr):
|
|
619
664
|
@method(preserve=True)
|
|
665
|
+
@deprecated("use .value")
|
|
620
666
|
def eval(self) -> int:
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
667
|
+
return self.value
|
|
668
|
+
|
|
669
|
+
@method(preserve=True) # type: ignore[misc]
|
|
670
|
+
@property
|
|
671
|
+
def value(self) -> int:
|
|
672
|
+
match get_callable_args(self, BigInt.from_string):
|
|
673
|
+
case (String(s),):
|
|
674
|
+
return int(s)
|
|
675
|
+
raise ExprValueError(self, "BigInt.from_string(String(s))")
|
|
676
|
+
|
|
677
|
+
__match_args__ = ("value",)
|
|
631
678
|
|
|
632
679
|
@method(preserve=True)
|
|
633
680
|
def __index__(self) -> int:
|
|
634
|
-
return self.
|
|
681
|
+
return self.value
|
|
635
682
|
|
|
636
683
|
@method(preserve=True)
|
|
637
684
|
def __int__(self) -> int:
|
|
638
|
-
return self.
|
|
685
|
+
return self.value
|
|
639
686
|
|
|
640
687
|
@method(egg_fn="from-string")
|
|
641
688
|
@classmethod
|
|
@@ -742,34 +789,27 @@ BigIntLike: TypeAlias = BigInt | i64Like
|
|
|
742
789
|
|
|
743
790
|
class BigRat(BuiltinExpr):
|
|
744
791
|
@method(preserve=True)
|
|
792
|
+
@deprecated("use .value")
|
|
745
793
|
def eval(self) -> Fraction:
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
if not isinstance(s.expr, LitDecl):
|
|
758
|
-
msg = "BigInt can only be initialized with literals"
|
|
759
|
-
raise BuiltinEvalError(msg)
|
|
760
|
-
assert isinstance(s.expr.value, str)
|
|
761
|
-
return Fraction(s.expr.value)
|
|
762
|
-
|
|
763
|
-
num, den = call.args
|
|
764
|
-
return Fraction(_to_fraction(num), _to_fraction(den))
|
|
794
|
+
return self.value
|
|
795
|
+
|
|
796
|
+
@method(preserve=True) # type: ignore[misc]
|
|
797
|
+
@property
|
|
798
|
+
def value(self) -> Fraction:
|
|
799
|
+
match get_callable_args(self, BigRat):
|
|
800
|
+
case (BigInt(num), BigInt(den)):
|
|
801
|
+
return Fraction(num, den)
|
|
802
|
+
raise ExprValueError(self, "BigRat(BigInt(num), BigInt(den))")
|
|
803
|
+
|
|
804
|
+
__match_args__ = ("value",)
|
|
765
805
|
|
|
766
806
|
@method(preserve=True)
|
|
767
807
|
def __float__(self) -> float:
|
|
768
|
-
return float(self.
|
|
808
|
+
return float(self.value)
|
|
769
809
|
|
|
770
810
|
@method(preserve=True)
|
|
771
811
|
def __int__(self) -> int:
|
|
772
|
-
return int(self.
|
|
812
|
+
return int(self.value)
|
|
773
813
|
|
|
774
814
|
@method(egg_fn="bigrat")
|
|
775
815
|
def __init__(self, num: BigIntLike, den: BigIntLike) -> None: ...
|
|
@@ -849,27 +889,32 @@ BigRatLike: TypeAlias = BigRat | Fraction
|
|
|
849
889
|
|
|
850
890
|
class Vec(BuiltinExpr, Generic[T]):
|
|
851
891
|
@method(preserve=True)
|
|
892
|
+
@deprecated("use .value")
|
|
852
893
|
def eval(self) -> tuple[T, ...]:
|
|
853
|
-
|
|
854
|
-
|
|
894
|
+
return self.value
|
|
895
|
+
|
|
896
|
+
@method(preserve=True) # type: ignore[misc]
|
|
897
|
+
@property
|
|
898
|
+
def value(self) -> tuple[T, ...]:
|
|
899
|
+
if get_callable_args(self, Vec.empty) is not None:
|
|
855
900
|
return ()
|
|
901
|
+
if (args := get_callable_args(self, Vec[T])) is not None:
|
|
902
|
+
return args
|
|
903
|
+
raise ExprValueError(self, "Vec(*xs) or Vec.empty()")
|
|
856
904
|
|
|
857
|
-
|
|
858
|
-
msg = "Vec can only be initialized with the Vec constructor."
|
|
859
|
-
raise BuiltinEvalError(msg)
|
|
860
|
-
return tuple(cast("T", cast("RuntimeExpr", self).__with_expr__(x)) for x in call.args)
|
|
905
|
+
__match_args__ = ("value",)
|
|
861
906
|
|
|
862
907
|
@method(preserve=True)
|
|
863
908
|
def __iter__(self) -> Iterator[T]:
|
|
864
|
-
return iter(self.
|
|
909
|
+
return iter(self.value)
|
|
865
910
|
|
|
866
911
|
@method(preserve=True)
|
|
867
912
|
def __len__(self) -> int:
|
|
868
|
-
return len(self.
|
|
913
|
+
return len(self.value)
|
|
869
914
|
|
|
870
915
|
@method(preserve=True)
|
|
871
916
|
def __contains__(self, key: T) -> bool:
|
|
872
|
-
return key in self.
|
|
917
|
+
return key in self.value
|
|
873
918
|
|
|
874
919
|
@method(egg_fn="vec-of")
|
|
875
920
|
def __init__(self, *args: T) -> None: ...
|
|
@@ -923,13 +968,20 @@ VecLike: TypeAlias = Vec[T] | tuple[TO, ...] | list[TO]
|
|
|
923
968
|
|
|
924
969
|
class PyObject(BuiltinExpr):
|
|
925
970
|
@method(preserve=True)
|
|
971
|
+
@deprecated("use .value")
|
|
926
972
|
def eval(self) -> object:
|
|
973
|
+
return self.value
|
|
974
|
+
|
|
975
|
+
@method(preserve=True) # type: ignore[misc]
|
|
976
|
+
@property
|
|
977
|
+
def value(self) -> object:
|
|
927
978
|
expr = cast("RuntimeExpr", self).__egg_typed_expr__.expr
|
|
928
979
|
if not isinstance(expr, PyObjectDecl):
|
|
929
|
-
|
|
930
|
-
raise BuiltinEvalError(msg)
|
|
980
|
+
raise ExprValueError(self, "PyObject(x)")
|
|
931
981
|
return expr.value
|
|
932
982
|
|
|
983
|
+
__match_args__ = ("value",)
|
|
984
|
+
|
|
933
985
|
def __init__(self, value: object) -> None: ...
|
|
934
986
|
|
|
935
987
|
@method(egg_fn="py-from-string")
|
|
@@ -1019,6 +1071,23 @@ class UnstableFn(BuiltinExpr, Generic[T, Unpack[TS]]):
|
|
|
1019
1071
|
@method(egg_fn="unstable-fn")
|
|
1020
1072
|
def __init__(self, f, *partial) -> None: ...
|
|
1021
1073
|
|
|
1074
|
+
@method(preserve=True)
|
|
1075
|
+
@deprecated("use .value")
|
|
1076
|
+
def eval(self) -> Callable[[Unpack[TS]], T]:
|
|
1077
|
+
return self.value
|
|
1078
|
+
|
|
1079
|
+
@method(preserve=True) # type: ignore[prop-decorator]
|
|
1080
|
+
@property
|
|
1081
|
+
def value(self) -> Callable[[Unpack[TS]], T]:
|
|
1082
|
+
"""
|
|
1083
|
+
If this is a constructor, returns either the callable directly or a `functools.partial` function if args are provided.
|
|
1084
|
+
"""
|
|
1085
|
+
if (fn := get_literal_value(self)) is not None:
|
|
1086
|
+
return fn
|
|
1087
|
+
raise ExprValueError(self, "UnstableFn(f, *args)")
|
|
1088
|
+
|
|
1089
|
+
__match_args__ = ("value",)
|
|
1090
|
+
|
|
1022
1091
|
@method(egg_fn="unstable-app")
|
|
1023
1092
|
def __call__(self, *args: Unpack[TS]) -> T: ...
|
|
1024
1093
|
|
|
@@ -1029,57 +1098,36 @@ converter(RuntimeFunction, UnstableFn, UnstableFn)
|
|
|
1029
1098
|
converter(partial, UnstableFn, lambda p: UnstableFn(p.func, *p.args))
|
|
1030
1099
|
|
|
1031
1100
|
|
|
1032
|
-
def _convert_function(
|
|
1101
|
+
def _convert_function(fn: FunctionType) -> UnstableFn:
|
|
1033
1102
|
"""
|
|
1034
|
-
Converts a function type to an unstable function
|
|
1103
|
+
Converts a function type to an unstable function. This function will be an anon function in egglog.
|
|
1035
1104
|
|
|
1036
|
-
Would just be UnstableFn(function(a)) but we have to
|
|
1037
|
-
|
|
1105
|
+
Would just be UnstableFn(function(a)) but we have to account for unbound vars within the body.
|
|
1106
|
+
|
|
1107
|
+
This means that we have to turn all of those unbound vars into args to the function, and then
|
|
1108
|
+
partially apply them, alongside creating a default rewrite for the function.
|
|
1038
1109
|
"""
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
# a.__name__ = f"{a.__name__} {hash(a.__code__)}"
|
|
1048
|
-
transformed_fn = functionalize(a, value_to_annotation)
|
|
1049
|
-
assert isinstance(transformed_fn, partial)
|
|
1050
|
-
return UnstableFn(
|
|
1051
|
-
function(ruleset=get_current_ruleset(), use_body_as_name=True, subsume=True)(transformed_fn.func),
|
|
1052
|
-
*transformed_fn.args,
|
|
1110
|
+
decls = Declarations()
|
|
1111
|
+
return_type, *arg_types = [resolve_type_annotation_mutate(decls, tp) for tp in get_type_args()]
|
|
1112
|
+
arg_names = [p.name for p in signature(fn).parameters.values()]
|
|
1113
|
+
arg_decls = [
|
|
1114
|
+
TypedExprDecl(tp.to_just(), UnboundVarDecl(name)) for name, tp in zip(arg_names, arg_types, strict=True)
|
|
1115
|
+
]
|
|
1116
|
+
res = resolve_literal(
|
|
1117
|
+
return_type, fn(*(RuntimeExpr.__from_values__(decls, a) for a in arg_decls)), Thunk.value(decls)
|
|
1053
1118
|
)
|
|
1119
|
+
res_expr = res.__egg_typed_expr__
|
|
1120
|
+
decls |= res
|
|
1121
|
+
# these are all the args that appear in the body that are not bound by the args of the function
|
|
1122
|
+
unbound_vars = list(collect_unbound_vars(res_expr) - set(arg_decls))
|
|
1123
|
+
# prefix the args with them
|
|
1124
|
+
fn_ref = UnnamedFunctionRef(tuple(unbound_vars + arg_decls), res_expr)
|
|
1125
|
+
rewrite_decl = DefaultRewriteDecl(fn_ref, res_expr.expr, subsume=True)
|
|
1126
|
+
ruleset_decls = _add_default_rewrite_inner(decls, rewrite_decl, get_current_ruleset())
|
|
1127
|
+
ruleset_decls |= res
|
|
1054
1128
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
# only lift runtime expressions (which could contain vars) not any other nonlocals/globals we use in the function
|
|
1058
|
-
if not isinstance(a, RuntimeExpr):
|
|
1059
|
-
return None
|
|
1060
|
-
return cast("type", RuntimeClass(Thunk.value(a.__egg_decls__), a.__egg_typed_expr__.tp.to_var()))
|
|
1129
|
+
fn = RuntimeFunction(Thunk.value(decls), Thunk.value(fn_ref))
|
|
1130
|
+
return UnstableFn(fn, *(RuntimeExpr.__from_values__(decls, v) for v in unbound_vars))
|
|
1061
1131
|
|
|
1062
1132
|
|
|
1063
1133
|
converter(FunctionType, UnstableFn, _convert_function)
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
def _extract_lit(e: BaseExpr) -> LitType:
|
|
1067
|
-
"""
|
|
1068
|
-
Special case extracting literals to make this faster by using termdag directly.
|
|
1069
|
-
"""
|
|
1070
|
-
expr = cast("RuntimeExpr", e).__egg_typed_expr__.expr
|
|
1071
|
-
if not isinstance(expr, LitDecl):
|
|
1072
|
-
msg = "Expected a literal"
|
|
1073
|
-
raise BuiltinEvalError(msg)
|
|
1074
|
-
return expr.value
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
def _extract_call(e: BaseExpr) -> CallDecl:
|
|
1078
|
-
"""
|
|
1079
|
-
Extracts the call form of an expression
|
|
1080
|
-
"""
|
|
1081
|
-
expr = cast("RuntimeExpr", e).__egg_typed_expr__.expr
|
|
1082
|
-
if not isinstance(expr, CallDecl):
|
|
1083
|
-
msg = "Expected a call expression"
|
|
1084
|
-
raise BuiltinEvalError(msg)
|
|
1085
|
-
return expr
|