Various progress, doesnt compile
Added prelude, made lambdas a single-token prefix like NS, made progress on implementations, removed const line type
This commit is contained in:
94
orchid-std/src/macros/instantiate_tpl.rs
Normal file
94
orchid-std/src/macros/instantiate_tpl.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
use std::borrow::Cow;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
use futures::AsyncWrite;
|
||||
use itertools::Itertools;
|
||||
use never::Never;
|
||||
use orchid_extension::atom::{Atomic, TypAtom};
|
||||
use orchid_extension::atom_owned::{DeserializeCtx, OwnedAtom, OwnedVariant, get_own_instance};
|
||||
use orchid_extension::conv::{ToExpr, TryFromExpr};
|
||||
use orchid_extension::expr::Expr;
|
||||
use orchid_extension::gen_expr::GExpr;
|
||||
use orchid_extension::system::SysCtx;
|
||||
|
||||
use crate::macros::mactree::{MacTok, MacTree};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InstantiateTplCall {
|
||||
pub(crate) tpl: MacTree,
|
||||
pub(crate) argc: usize,
|
||||
pub(crate) argv: Vec<MacTree>,
|
||||
}
|
||||
impl Atomic for InstantiateTplCall {
|
||||
type Variant = OwnedVariant;
|
||||
type Data = ();
|
||||
}
|
||||
impl OwnedAtom for InstantiateTplCall {
|
||||
async fn val(&self) -> Cow<'_, Self::Data> { Cow::Owned(()) }
|
||||
/// TODO: get serialization done for mactree
|
||||
type Refs = Vec<Expr>;
|
||||
async fn serialize(
|
||||
&self,
|
||||
ctx: SysCtx,
|
||||
write: Pin<&mut (impl AsyncWrite + ?Sized)>,
|
||||
) -> Self::Refs {
|
||||
todo!()
|
||||
}
|
||||
async fn deserialize(ctx: impl DeserializeCtx, refs: Self::Refs) -> Self { todo!() }
|
||||
// Technically must be supported but shouldn't actually ever be called
|
||||
async fn call_ref(&self, arg: Expr) -> GExpr {
|
||||
eprintln!(
|
||||
"Copying partially applied instantiate_tpl call. This is an internal value.\
|
||||
\nIt should be fully consumed within generated code."
|
||||
);
|
||||
self.clone().call(arg).await
|
||||
}
|
||||
async fn call(mut self, arg: Expr) -> GExpr {
|
||||
let arg = match TypAtom::try_from_expr(arg).await {
|
||||
Err(e) => return Err::<Never, _>(e).to_expr(),
|
||||
Ok(t) => get_own_instance(t).await,
|
||||
};
|
||||
self.argv.push(arg);
|
||||
if self.argv.len() < self.argc {
|
||||
return self.to_expr();
|
||||
}
|
||||
instantiate_tpl(&self.tpl, &mut self.argv.into_iter(), &mut false).to_expr()
|
||||
}
|
||||
}
|
||||
fn instantiate_tpl(
|
||||
tpl: &MacTree,
|
||||
argv: &mut impl Iterator<Item = MacTree>,
|
||||
changed: &mut bool,
|
||||
) -> MacTree {
|
||||
let tok = match &*tpl.tok {
|
||||
MacTok::Slot => {
|
||||
*changed = true;
|
||||
return argv.next().expect("Not enough arguments to fill all slots!");
|
||||
},
|
||||
MacTok::Lambda(arg, body) => MacTok::Lambda(
|
||||
ro(changed, |changed| instantiate_tpl(arg, argv, changed)),
|
||||
instantiate_tpl_v(body, argv, changed),
|
||||
),
|
||||
MacTok::Name(_) | MacTok::Value(_) => return tpl.clone(),
|
||||
MacTok::Ph(_) => panic!("instantiate_tpl received a placeholder"),
|
||||
MacTok::S(p, body) => MacTok::S(*p, instantiate_tpl_v(body, argv, changed)),
|
||||
};
|
||||
if *changed { MacTree { pos: tpl.pos.clone(), tok: Rc::new(tok) } } else { tpl.clone() }
|
||||
}
|
||||
fn instantiate_tpl_v(
|
||||
tpl: &[MacTree],
|
||||
argv: &mut impl Iterator<Item = MacTree>,
|
||||
changed: &mut bool,
|
||||
) -> Vec<MacTree> {
|
||||
tpl.iter().map(|tree| ro(changed, |changed| instantiate_tpl(tree, argv, changed))).collect_vec()
|
||||
}
|
||||
|
||||
/// reverse "or". Inside, the flag is always false, but raising it will raise
|
||||
/// the outside flag too.
|
||||
fn ro<T>(flag: &mut bool, cb: impl FnOnce(&mut bool) -> T) -> T {
|
||||
let mut new_flag = false;
|
||||
let val = cb(&mut new_flag);
|
||||
*flag |= new_flag;
|
||||
val
|
||||
}
|
||||
Reference in New Issue
Block a user