use std::future::Future; use std::pin::Pin; use dyn_clone::DynClone; use never::Never; use orchid_base::error::{OrcErrv, OrcRes, mk_errv}; use orchid_base::location::Pos; use trait_set::trait_set; use crate::atom::{AtomicFeatures, ForeignAtom, TAtom, ToAtom}; use crate::context::i; use crate::expr::Expr; use crate::gen_expr::{GExpr, atom, bot}; pub trait TryFromExpr: Sized { fn try_from_expr(expr: Expr) -> impl Future>; } impl TryFromExpr for Expr { async fn try_from_expr(expr: Expr) -> OrcRes { Ok(expr) } } impl TryFromExpr for (T, U) { async fn try_from_expr(expr: Expr) -> OrcRes { Ok((T::try_from_expr(expr.clone()).await?, U::try_from_expr(expr).await?)) } } async fn err_not_atom(pos: Pos) -> OrcErrv { mk_errv(i().i("Expected an atom").await, "This expression is not an atom", [pos]) } impl TryFromExpr for ForeignAtom { async fn try_from_expr(expr: Expr) -> OrcRes { match expr.atom().await { Err(ex) => Err(err_not_atom(ex.data().await.pos.clone()).await), Ok(f) => Ok(f), } } } impl TryFromExpr for TAtom { async fn try_from_expr(expr: Expr) -> OrcRes { let f = ForeignAtom::try_from_expr(expr).await?; match f.clone().downcast::().await { Ok(a) => Ok(a), Err(e) => Err(e.mk_err().await), } } } pub trait ToExpr { fn to_gen(self) -> impl Future; fn to_expr(self) -> impl Future where Self: Sized { async { self.to_gen().await.create().await } } } pub trait ToExprDyn { fn to_gen_dyn<'a>(self: Box) -> Pin + 'a>> where Self: 'a; fn to_expr_dyn<'a>(self: Box) -> Pin + 'a>> where Self: 'a; } impl ToExprDyn for T { fn to_gen_dyn<'a>(self: Box) -> Pin + 'a>> where Self: 'a { Box::pin(self.to_gen()) } fn to_expr_dyn<'a>(self: Box) -> Pin + 'a>> where Self: 'a { Box::pin(self.to_expr()) } } trait_set! { pub trait ClonableToExprDyn = ToExprDyn + DynClone; } impl ToExpr for Box { async fn to_gen(self) -> GExpr { self.to_gen_dyn().await } async fn to_expr(self) -> Expr { self.to_expr_dyn().await } } impl ToExpr for Box { async fn to_gen(self) -> GExpr { self.to_gen_dyn().await } async fn to_expr(self) -> Expr { self.to_expr_dyn().await } } impl Clone for Box { fn clone(&self) -> Self { dyn_clone::clone_box(&**self) } } impl ToExpr for GExpr { async fn to_gen(self) -> GExpr { self } async fn to_expr(self) -> Expr { self.create().await } } impl ToExpr for Expr { async fn to_gen(self) -> GExpr { self.slot() } async fn to_expr(self) -> Expr { self } } impl ToExpr for OrcRes { async fn to_gen(self) -> GExpr { match self { Err(e) => bot(e), Ok(t) => t.to_gen().await, } } } impl ToExpr for A { async fn to_gen(self) -> GExpr { atom(self) } } impl ToExpr for Never { async fn to_gen(self) -> GExpr { match self {} } }