Skip to content

Commit

Permalink
Merge pull request #49 from metadsl/fix-string-gen
Browse files Browse the repository at this point in the history
Fix string generation duplication
  • Loading branch information
saulshanabrook authored Oct 4, 2023
2 parents a973bbd + b587059 commit c800b77
Show file tree
Hide file tree
Showing 23 changed files with 2,147 additions and 1,059 deletions.
180 changes: 86 additions & 94 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.18.1", features = ["extension-module"] }
egglog = { git = "https://github.com/egraphs-good/egglog", rev = "4d67f262a6f27aa5cfb62a2cfc7df968959105df" }
egglog = { git = "https://github.com/egraphs-good/egglog", rev = "45d05e727cceaab13413b4e51a60ee3be9fbf403" }
# egglog = { git = "https://github.com/oflatt/egg-smol", rev = "f6df3ff831b65405665e1751b0ef71c61b025432" }
# egglog = { git = "https://github.com/saulshanabrook/egg-smol", rev = "c01695618ed4de2fbfa8116476e208bc1ca86612" }
# egglog = { git = "https://github.com/saulshanabrook/egg-smol", rev = "38b3014b34399cc78887ede09c845b2a5d6c7d19" }

pyo3-log = "0.8.1"
log = "0.4.17"
Expand Down
16 changes: 14 additions & 2 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ _This project uses semantic versioning. Before 1.0.0, this means that every brea

## Unreleased

- Bump [egglog dep](https://github.com/egraphs-good/egglog/compare/4d67f262a6f27aa5cfb62a2cfc7df968959105df...45d05e727cceaab13413b4e51a60ee3be9fbf403)

### New Features

- Adds ability for custom user defined types in a union for proper static typing with conversions [#49](https://github.com/metadsl/egglog-python/pull/49)
- Adds `py_eval` function to `EGraph` as a helper to eval Python code. [#49](https://github.com/metadsl/egglog-python/pull/49)
- Adds on hover behavior for edges in graphviz SVG output to make them easier to trace [#49](https://github.com/metadsl/egglog-python/pull/49)
- Adds `egglog.exp.program_gen` module that will compile expressions into Python statements/functions [#49](https://github.com/metadsl/egglog-python/pull/49)
- Adds `py_exec` primitive function for executing Python code [#49](https://github.com/metadsl/egglog-python/pull/49)

### Bug fixes

- Clean up example in tutorial with demand based expression generation [#49](https://github.com/metadsl/egglog-python/pull/49)

## 0.6.0 (2023-09-20)

- Bump [egglog dep](https://github.com/egraphs-good/egglog/compare/c83fc750878755eb610a314da90f9273b3bfe25d...4d67f262a6f27aa5cfb62a2cfc7df968959105df)
Expand All @@ -19,8 +33,6 @@ _This project uses semantic versioning. Before 1.0.0, this means that every brea
- Add `Relation` and `PrintOverallStatistics` low level commands [#46](https://github.com/metadsl/egglog-python/pull/46)
- Adds `count-matches` and `replace` string commands [#46](https://github.com/metadsl/egglog-python/pull/46)

### Bug fixes

### Uncategorized

- Added initial supported for Python objects [#31](https://github.com/metadsl/egglog-python/pull/31)
Expand Down
15 changes: 0 additions & 15 deletions docs/reference/egglog-translation.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,21 +245,6 @@ As shown above, we can also use the `@classmethod` and `@property` decorators to
Note that reflected methods (i.e. `__radd__`) are handled as a special case. If defined, they won't create their own egglog functions.
Instead, whenever a reflected method is called, we will try to find the corresponding non-reflected method and call that instead.

#### Custom Type Promotion

Similar to how an `int` can be automatically upcasted to an `i64`, we also support registering conversion to your custom types. For example:

```{code-cell} python
converter(int, Math, Math)
converter(str, Math, Math.var)
Math(2) + 30 + "x"
# equal to
Math(2) + Math(i64(30)) + Math.var(String("x"))
```

Regstering a conversion from A to B will also register all transitively reachable conversions from A to B.

### Declarations

In egglog, the `(declare ...)` command is syntactic sugar for a nullary function. In Python, these can be declare either as class variables or with the toplevel `egraph.constant` function:
Expand Down
70 changes: 66 additions & 4 deletions docs/reference/python-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,13 @@ egraph.load_object(egraph.extract(PyObject.from_int(1)))
We also support evaling arbitrary Python bode, given some locals and globals. This technically allows us to implement any Python method:

```{code-cell} python
empty_dict = egraph.save_object({})
egraph.load_object(egraph.extract(py_eval("1 + 2", empty_dict, empty_dict)))
egraph.load_object(egraph.extract(py_eval("1 + 2")))
```

Execing Python code is also supported. In this case, the return value will be the updated globals dict, which will be copied first before using.

```{code-cell} python
egraph.load_object(egraph.extract(py_exec("x = 1 + 2")))
```

Alongside this, we support a function `dict_update` method, which can allow you to combine some local local egglog expressions alongside, say, the locals and globals of the Python code you are evaling.
Expand All @@ -87,11 +92,68 @@ locals_expr = egraph.save_object(locals())
globals_expr = egraph.save_object(globals())
# Need `one` to map to the expression for `1` not the Python object of the expression
amended_globals = globals_expr.dict_update(PyObject.from_string("one"), one)
evalled = py_eval("one + 2", locals_expr, amended_globals)
evalled = py_eval("my_add(one, 2)", locals_expr, amended_globals)
assert egraph.load_object(egraph.extract(evalled)) == 3
```

This is a bit subtle at the moment, and we plan on adding an easier wrapper to eval arbitrary Python code in the future.
### Simpler Eval

Instead of using the above low level primitive for evaling, there is a higher level wrapper function, `egraph.eval_fn`.

It takes in a Python function and converts it to a function of PyObjects, by using `py_eval`
under the hood.

The above code code be re-written like this:

```{code-cell} python
def my_add(a, b):
return a + b
evalled = egraph.eval_fn(lambda a: my_add(a, 2))(one)
assert egraph.load_object(egraph.extract(evalled)) == 3
```

#### Custom Type Promotion

Similar to how an `int` can be automatically upcasted to an `i64`, we also support registering conversion to your custom types. For example:

```{code-cell} python
@egraph.class_
class Math(Expr):
def __init__(self, x: i64Like) -> None: ...
@classmethod
def var(cls, name: StringLike) -> Math: ...
def __add__(self, other: Math) -> Math: ...
converter(i64, Math, Math)
converter(String, Math, Math.var)
Math(2) + i64(30) + String("x")
# equal to
Math(2) + Math(i64(30)) + Math.var(String("x"))
```

Regstering a conversion from A to B will also register all transitively reachable conversions from A to B, so you can also use:

```{code-cell} python
Math(2) + 30 + "x"
```

If you want to have this work with the static type checker, you can define your own `Union` type, which MUST include
have the Egglog class as the first item in the union. For example, in this case you could then define:

```{code-cell} python
from typing import Union
MathLike = Union[Math, i64Like, StringLike]
@egraph.function
def some_math_fn(x: MathLike) -> MathLike:
...
some_math_fn(10)
```

## "Preserved" methods

Expand Down
Loading

0 comments on commit c800b77

Please sign in to comment.