use orchid_base::error::{OrcErr, OrcRes, mk_err}; use orchid_base::intern; use orchid_base::location::Pos; use crate::atom::{AtomicFeatures, ToAtom, TypAtom}; use crate::expr::{Expr, atom, bot}; use crate::system::downcast_atom; pub trait TryFromExpr: Sized { fn try_from_expr(expr: Expr) -> OrcRes; } impl TryFromExpr for Expr { fn try_from_expr(expr: Expr) -> OrcRes { Ok(expr) } } impl TryFromExpr for (T, U) { fn try_from_expr(expr: Expr) -> OrcRes { Ok((T::try_from_expr(expr.clone())?, U::try_from_expr(expr)?)) } } async fn err_not_atom(pos: Pos) -> OrcErr { mk_err(intern!(str: "Expected an atom").await, "This expression is not an atom", [pos.into()]) } async fn err_type(pos: Pos) -> OrcErr { mk_err(intern!(str: "Type error").await, "The atom is a different type than expected", [ pos.into() ]) } impl TryFromExpr for TypAtom<'_, A> { async fn try_from_expr(expr: Expr) -> OrcRes { match expr.foreign_atom() { Err(ex) => Err(err_not_atom(ex.pos.clone()).await.into()), Ok(f) => match downcast_atom(f) \.map_err(|f| err_type(f.pos).into()), } } } pub trait ToExpr { fn to_expr(self) -> Expr; } impl ToExpr for Expr { fn to_expr(self) -> Expr { self } } impl ToExpr for OrcRes { fn to_expr(self) -> Expr { match self { Err(e) => bot(e), Ok(t) => t.to_expr(), } } } impl ToExpr for A { fn to_expr(self) -> Expr { atom(self) } }