forked from Orchid/orchid
Updated macro system to process and return mactree and then lower it separately to gexpr
This commit is contained in:
@@ -16,7 +16,7 @@ use task_local::task_local;
|
||||
|
||||
use crate::gen_expr::GExpr;
|
||||
use crate::tree::{GenTok, GenTokTree};
|
||||
use crate::{Expr, ToExpr, api, request, sys_id};
|
||||
use crate::{ExecHandle, Expr, ToExpr, TryFromExpr, api, exec, request, sys_id};
|
||||
|
||||
/// [PTokTree] without [orchid_base::Pos] metadata
|
||||
pub type PTok = Token<Expr, Never>;
|
||||
@@ -118,7 +118,7 @@ impl<'a> ParsCtx<'a> {
|
||||
pub fn module(&self) -> Sym { self.module.clone() }
|
||||
}
|
||||
|
||||
type BoxConstCallback = Box<dyn FnOnce(ConstCtx) -> LocalBoxFuture<'static, GExpr>>;
|
||||
type BoxConstCallback = Box<dyn for<'a> FnOnce(ConstCtx<'a>) -> LocalBoxFuture<'a, GExpr>>;
|
||||
|
||||
task_local! {
|
||||
static CONST_TBL: RefCell<HashMap<NonZero<u64>, BoxConstCallback>>;
|
||||
@@ -143,14 +143,15 @@ impl ParsedLine {
|
||||
/// Define a constant. The callback is only called later if the constant is
|
||||
/// referenced, and it can call [crate::refl] to base its value on the module
|
||||
/// tree or use its argument for context-specific queries
|
||||
pub fn cnst<'a, R: ToExpr + 'static, F: AsyncFnOnce(ConstCtx) -> R + 'static>(
|
||||
pub fn cnst<'a, R: ToExpr + 'static, F: for<'b> AsyncFnOnce(ConstCtx<'b>) -> R + 'static>(
|
||||
sr: &SrcRange,
|
||||
comments: impl IntoIterator<Item = &'a Comment>,
|
||||
exported: bool,
|
||||
name: IStr,
|
||||
f: F,
|
||||
) -> Self {
|
||||
let cb = Box::new(|ctx| async move { f(ctx).await.to_gen().await }.boxed_local());
|
||||
let cb: BoxConstCallback =
|
||||
Box::new(|ctx| async move { f(ctx).await.to_gen().await }.boxed_local());
|
||||
let kind = ParsedLineKind::Mem(ParsedMem { name, exported, kind: ParsedMemKind::Const(cb) });
|
||||
let comments = comments.into_iter().cloned().collect();
|
||||
ParsedLine { comments, sr: sr.clone(), kind }
|
||||
@@ -241,11 +242,11 @@ pub enum ParsedMemKind {
|
||||
}
|
||||
|
||||
/// Enable a generated constant to query about its environment
|
||||
#[derive(Clone)]
|
||||
pub struct ConstCtx {
|
||||
pub struct ConstCtx<'a> {
|
||||
constid: api::ParsedConstId,
|
||||
exec: ExecHandle<'a>,
|
||||
}
|
||||
impl ConstCtx {
|
||||
impl<'a> ConstCtx<'a> {
|
||||
/// Resolve a set of local names into the full names they would point to if
|
||||
/// they were globally bound. Errors produced at this stage are soft, as the
|
||||
/// names may still be found to be locally bound within the expression
|
||||
@@ -272,10 +273,14 @@ impl ConstCtx {
|
||||
pub async fn names_n<const N: usize>(&self, names: [&Sym; N]) -> [OrcRes<Sym>; N] {
|
||||
self.names(names).collect::<Vec<_>>().await.try_into().expect("Lengths must match")
|
||||
}
|
||||
pub async fn exec<R: TryFromExpr>(&mut self, val: impl ToExpr) -> OrcRes<R> {
|
||||
self.exec.exec(val).await
|
||||
}
|
||||
pub fn handle(&mut self) -> &mut ExecHandle<'a> { &mut self.exec }
|
||||
}
|
||||
|
||||
pub(crate) async fn get_const(id: api::ParsedConstId) -> GExpr {
|
||||
let cb = CONST_TBL
|
||||
.with(|ent| ent.borrow_mut().remove(&id.0).expect("Bad ID or double read of parsed const"));
|
||||
cb(ConstCtx { constid: id }).await
|
||||
exec(async move |exec| cb(ConstCtx { constid: id, exec }).await).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user