New macro system and stdlib additions
This commit is contained in:
75
orchid-std/src/std/option.rs
Normal file
75
orchid-std/src/std/option.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use std::borrow::Cow;
|
||||
use std::pin::Pin;
|
||||
|
||||
use futures::AsyncWrite;
|
||||
use orchid_api_traits::Encode;
|
||||
use orchid_base::error::mk_errv;
|
||||
use orchid_base::sym;
|
||||
use orchid_extension::atom::{Atomic, ForeignAtom, TAtom};
|
||||
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant};
|
||||
use orchid_extension::context::i;
|
||||
use orchid_extension::conv::{ToExpr, TryFromExpr};
|
||||
use orchid_extension::expr::{Expr, ExprHandle};
|
||||
use orchid_extension::gen_expr::{call, sym_ref};
|
||||
use orchid_extension::tree::{GenMember, cnst, fun, prefix};
|
||||
|
||||
use crate::{OrcString, api};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OptAtom(Option<Expr>);
|
||||
impl Atomic for OptAtom {
|
||||
type Data = Option<api::ExprTicket>;
|
||||
type Variant = OwnedVariant;
|
||||
}
|
||||
impl OwnedAtom for OptAtom {
|
||||
type Refs = Vec<Expr>;
|
||||
async fn val(&self) -> Cow<'_, Self::Data> {
|
||||
Cow::Owned(self.0.as_ref().map(|ex| ex.handle().ticket()))
|
||||
}
|
||||
async fn deserialize(mut ctx: impl DeserializeCtx, refs: Self::Refs) -> Self {
|
||||
Self(ctx.read::<bool>().await.then(|| refs.into_iter().next().unwrap()))
|
||||
}
|
||||
async fn serialize(&self, write: Pin<&mut (impl AsyncWrite + ?Sized)>) -> Self::Refs {
|
||||
self.0.is_some().encode(write).await;
|
||||
self.0.iter().cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OrcOpt<T>(pub Option<T>);
|
||||
impl<T: TryFromExpr> TryFromExpr for OrcOpt<T> {
|
||||
async fn try_from_expr(expr: Expr) -> orchid_base::error::OrcRes<Self> {
|
||||
let atom = TAtom::<OptAtom>::try_from_expr(expr).await?;
|
||||
match atom.value {
|
||||
None => Ok(OrcOpt(None)),
|
||||
Some(tk) => Ok(OrcOpt(Some(
|
||||
T::try_from_expr(Expr::from_handle(ExprHandle::from_ticket(tk).await)).await?,
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: ToExpr + 'static> ToExpr for OrcOpt<T> {
|
||||
async fn to_gen(self) -> orchid_extension::gen_expr::GExpr {
|
||||
if let Some(val) = self.0 {
|
||||
call(sym_ref(sym!(std::option::some; i())), [val.to_gen().await])
|
||||
} else {
|
||||
sym_ref(sym!(std::option::none; i()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gen_option_lib() -> Vec<GenMember> {
|
||||
prefix("std::option", [
|
||||
cnst(true, "none", OptAtom(None)),
|
||||
fun(true, "some", async |ex: Expr| OptAtom(Some(ex))),
|
||||
fun(true, "expect", async |opt: ForeignAtom, msg: OrcString| {
|
||||
match OrcOpt::try_from_expr(opt.clone().ex()).await? {
|
||||
OrcOpt(Some(ex)) => Ok::<Expr, _>(ex),
|
||||
OrcOpt(None) => Err(mk_errv(
|
||||
i().i("Unwrapped std::option::none").await,
|
||||
msg.get_string().await.as_str(),
|
||||
[opt.pos()],
|
||||
)),
|
||||
}
|
||||
}),
|
||||
])
|
||||
}
|
||||
Reference in New Issue
Block a user