Skip to content

Commit cf22521

Browse files
Add simpler error handling
1 parent bd4a1f5 commit cf22521

File tree

4 files changed

+62
-28
lines changed

4 files changed

+62
-28
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ egg-smol = { git = "https://github.com/mwillsey/egg-smol", rev = "94c173b9d6152c
1414

1515
[package.metadata.maturin]
1616
name = "egg_smol.bindings"
17+
18+
# Patch egg-smol to use local version
19+
[patch.crates-io]
20+
egg-smol = { path = "../egg-smol" }

src/error.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use pyo3::prelude::*;
2+
3+
// Create exceptions with class instead of create_exception! macro
4+
// https://github.com/PyO3/pyo3/issues/295#issuecomment-852358088
5+
#[pyclass(extends=pyo3::exceptions::PyException)]
6+
pub struct EggSmolError {
7+
#[pyo3(get)]
8+
context: String,
9+
}
10+
11+
#[pymethods]
12+
impl EggSmolError {
13+
#[new]
14+
fn new(context: String) -> Self {
15+
EggSmolError { context }
16+
}
17+
}
18+
19+
// Wrap the egg_smol::Error so we can automatically convert from it to the PyErr
20+
// and so return it from each function automatically
21+
// https://pyo3.rs/latest/function/error_handling.html#foreign-rust-error-types
22+
pub struct WrappedError(egg_smol::Error);
23+
24+
// Convert from the WrappedError to the PyErr by creating a new Python error
25+
impl From<WrappedError> for PyErr {
26+
fn from(error: WrappedError) -> Self {
27+
PyErr::new::<EggSmolError, _>(error.0.to_string())
28+
}
29+
}
30+
31+
// Convert from an egg_smol::Error to a WrappedError
32+
impl From<egg_smol::Error> for WrappedError {
33+
fn from(other: egg_smol::Error) -> Self {
34+
Self(other)
35+
}
36+
}
37+
38+
// Use similar to PyResult, wraps a result type and can be converted to PyResult
39+
pub type EggResult<T> = Result<T, WrappedError>;

src/lib.rs

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
mod error;
2+
use error::*;
13
use pyo3::prelude::*;
24

35
/// EGraph()
@@ -9,22 +11,6 @@ struct EGraph {
911
egraph: egg_smol::EGraph,
1012
}
1113

12-
// Create exceptions with class instead of create_exception! macro
13-
// https://github.com/PyO3/pyo3/issues/295#issuecomment-852358088
14-
#[pyclass(extends=pyo3::exceptions::PyException)]
15-
pub struct EggSmolError {
16-
#[pyo3(get)]
17-
context: String,
18-
}
19-
20-
#[pymethods]
21-
impl EggSmolError {
22-
#[new]
23-
fn new(context: String) -> Self {
24-
EggSmolError { context }
25-
}
26-
}
27-
2814
// Convert a Python Variant object into a rust variable, by getting the attributes
2915
fn get_variant(obj: &PyAny) -> PyResult<egg_smol::ast::Variant> {
3016
// TODO: Is there a way to do this more automatically?
@@ -56,22 +42,24 @@ impl EGraph {
5642
/// --
5743
///
5844
/// Declare a new sort with the given name.
59-
fn declare_sort(&mut self, name: &str) -> PyResult<()> {
45+
fn declare_sort(&mut self, name: &str) -> EggResult<()> {
6046
// TODO: Should the name be a symbol? If so, how should we expose that
6147
// to Python?
62-
self.egraph
63-
.declare_sort(name)
64-
.map_err(|e| PyErr::new::<EggSmolError, _>(e.to_string()))
48+
self.egraph.declare_sort(name)?;
49+
Ok({})
6550
}
6651

52+
/// declare_constructor($self, variant, sort)
53+
/// --
54+
///
55+
/// Declare a new datatype constructor.
6756
fn declare_constructor(
6857
&mut self,
6958
#[pyo3(from_py_with = "get_variant")] variant: egg_smol::ast::Variant,
7059
sort: &str,
71-
) -> PyResult<()> {
72-
self.egraph
73-
.declare_constructor(variant, sort)
74-
.map_err(|e| PyErr::new::<EggSmolError, _>(e.to_string()))
60+
) -> EggResult<()> {
61+
self.egraph.declare_constructor(variant, sort)?;
62+
Ok({})
7563
}
7664

7765
/// parse_and_run_program($self, input)
@@ -80,10 +68,9 @@ impl EGraph {
8068
/// Parse the input string as a program and run it on the EGraph.
8169
/// Returns a list of strings representing the output.
8270
/// An EggSmolError is raised if there is problem parsing or executing.
83-
fn parse_and_run_program(&mut self, input: &str) -> PyResult<Vec<String>> {
84-
self.egraph
85-
.parse_and_run_program(input)
86-
.map_err(|e| PyErr::new::<EggSmolError, _>(e.to_string()))
71+
fn parse_and_run_program(&mut self, input: &str) -> EggResult<Vec<String>> {
72+
let res = self.egraph.parse_and_run_program(input)?;
73+
Ok(res)
8774
}
8875
}
8976

0 commit comments

Comments
 (0)