Macro system done in theory
too afraid to begin debugging, resting for a moment
This commit is contained in:
@@ -2,29 +2,48 @@ use std::marker::PhantomData;
|
||||
|
||||
use async_stream::stream;
|
||||
use futures::future::{LocalBoxFuture, join_all};
|
||||
use futures::{FutureExt, Stream, StreamExt, pin_mut};
|
||||
use futures::{FutureExt, Stream, StreamExt};
|
||||
use itertools::Itertools;
|
||||
use never::Never;
|
||||
use orchid_api::ResolveNames;
|
||||
use orchid_base::error::{OrcRes, Reporter};
|
||||
use orchid_base::error::{OrcErrv, OrcRes, Reporter};
|
||||
use orchid_base::id_store::IdStore;
|
||||
use orchid_base::interner::{Interner, Tok};
|
||||
use orchid_base::location::SrcRange;
|
||||
use orchid_base::match_mapping;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::parse::{Comment, ParseCtx, Snippet};
|
||||
use orchid_base::reqnot::{ReqHandlish, Requester};
|
||||
use orchid_base::tree::{TokTree, Token, ttv_into_api};
|
||||
|
||||
use crate::api;
|
||||
use crate::conv::ToExpr;
|
||||
use crate::expr::Expr;
|
||||
use crate::gen_expr::GExpr;
|
||||
use crate::system::{SysCtx, SysCtxEntry};
|
||||
use crate::tree::GenTokTree;
|
||||
use crate::tree::{GenTok, GenTokTree};
|
||||
|
||||
pub type PTok = Token<Expr, Never>;
|
||||
pub type PTokTree = TokTree<Expr, Never>;
|
||||
pub type PSnippet<'a> = Snippet<'a, Expr, Never>;
|
||||
|
||||
pub fn p_tok2gen(tok: PTok) -> GenTok {
|
||||
match_mapping!(tok, PTok => GenTok {
|
||||
Comment(s), Name(n), BR, Handle(ex), Bottom(err),
|
||||
LambdaHead(arg => Box::new(p_tree2gen(*arg))),
|
||||
NS(n, arg => Box::new(p_tree2gen(*arg))),
|
||||
S(p, body () p_v2gen),
|
||||
} {
|
||||
PTok::NewExpr(never) => match never {}
|
||||
})
|
||||
}
|
||||
pub fn p_tree2gen(tree: PTokTree) -> GenTokTree {
|
||||
TokTree { tok: p_tok2gen(tree.tok), sr: tree.sr }
|
||||
}
|
||||
pub fn p_v2gen(v: impl IntoIterator<Item = PTokTree>) -> Vec<GenTokTree> {
|
||||
v.into_iter().map(p_tree2gen).collect_vec()
|
||||
}
|
||||
|
||||
pub trait Parser: Send + Sync + Sized + Default + 'static {
|
||||
const LINE_HEAD: &'static str;
|
||||
fn parse<'a>(
|
||||
@@ -93,6 +112,31 @@ pub struct ParsedLine {
|
||||
pub kind: ParsedLineKind,
|
||||
}
|
||||
impl ParsedLine {
|
||||
pub fn cnst<'a, R: ToExpr + 'static, F: AsyncFnOnce(ConstCtx) -> R + 'static>(
|
||||
sr: &SrcRange,
|
||||
comments: impl IntoIterator<Item = &'a Comment>,
|
||||
exported: bool,
|
||||
name: Tok<String>,
|
||||
f: F,
|
||||
) -> Self {
|
||||
let cb = Box::new(|ctx| async move { f(ctx).await.to_expr().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 }
|
||||
}
|
||||
pub fn module<'a>(
|
||||
sr: &SrcRange,
|
||||
comments: impl IntoIterator<Item = &'a Comment>,
|
||||
exported: bool,
|
||||
name: &Tok<String>,
|
||||
use_prelude: bool,
|
||||
lines: impl IntoIterator<Item = ParsedLine>,
|
||||
) -> Self {
|
||||
let mem_kind = ParsedMemKind::Mod { lines: lines.into_iter().collect(), use_prelude };
|
||||
let line_kind = ParsedLineKind::Mem(ParsedMem { name: name.clone(), exported, kind: mem_kind });
|
||||
let comments = comments.into_iter().cloned().collect();
|
||||
ParsedLine { comments, sr: sr.clone(), kind: line_kind }
|
||||
}
|
||||
pub async fn into_api(self, ctx: SysCtx, hand: &dyn ReqHandlish) -> api::ParsedLine {
|
||||
api::ParsedLine {
|
||||
comments: self.comments.into_iter().map(|c| c.to_api()).collect(),
|
||||
@@ -142,18 +186,6 @@ pub enum ParsedMemKind {
|
||||
Mod { lines: Vec<ParsedLine>, use_prelude: bool },
|
||||
}
|
||||
|
||||
impl ParsedMemKind {
|
||||
pub fn cnst<F: AsyncFnOnce(ConstCtx) -> GExpr + 'static>(f: F) -> Self {
|
||||
Self::Const(Box::new(|ctx| Box::pin(f(ctx))))
|
||||
}
|
||||
pub fn module(lines: impl IntoIterator<Item = ParsedLine>) -> Self {
|
||||
Self::Mod { lines: lines.into_iter().collect(), use_prelude: true }
|
||||
}
|
||||
pub fn clean_module(lines: impl IntoIterator<Item = ParsedLine>) -> Self {
|
||||
Self::Mod { lines: lines.into_iter().collect(), use_prelude: false }
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: how the macro runner uses the multi-stage loader
|
||||
|
||||
Since the macro runner actually has to invoke the interpreter,
|
||||
@@ -169,16 +201,18 @@ postparse / const load links up constants with every macro they can directly inv
|
||||
the constants representing the keywords resolve to panic
|
||||
execute relies on these links detected in the extension to dispatch relevant macros
|
||||
*/
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConstCtx {
|
||||
ctx: SysCtx,
|
||||
constid: api::ParsedConstId,
|
||||
}
|
||||
impl ConstCtx {
|
||||
pub fn names<'a>(
|
||||
&'a self,
|
||||
names: impl IntoIterator<Item = &'a Sym> + 'a,
|
||||
) -> impl Stream<Item = Option<Sym>> + 'a {
|
||||
pub fn ctx(&self) -> &SysCtx { &self.ctx }
|
||||
pub fn i(&self) -> &Interner { self.ctx.i() }
|
||||
pub fn names<'b>(
|
||||
&'b self,
|
||||
names: impl IntoIterator<Item = &'b Sym> + 'b,
|
||||
) -> impl Stream<Item = OrcRes<Sym>> + 'b {
|
||||
let resolve_names = ResolveNames {
|
||||
constid: self.constid,
|
||||
sys: self.ctx.sys_id(),
|
||||
@@ -187,20 +221,14 @@ impl ConstCtx {
|
||||
stream! {
|
||||
for name_opt in self.ctx.reqnot().request(resolve_names).await {
|
||||
yield match name_opt {
|
||||
None => None,
|
||||
Some(name) => Some(Sym::from_api(name, self.ctx.i()).await)
|
||||
Err(e) => Err(OrcErrv::from_api(&e, self.ctx.i()).await),
|
||||
Ok(name) => Ok(Sym::from_api(name, self.ctx.i()).await)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub async fn names_n<const N: usize>(&self, names: [&Sym; N]) -> [Option<Sym>; N] {
|
||||
let mut results = [const { None }; N];
|
||||
let names = self.names(names).enumerate().filter_map(|(i, n)| async move { Some((i, n?)) });
|
||||
pin_mut!(names);
|
||||
while let Some((i, name)) = names.next().await {
|
||||
results[i] = Some(name);
|
||||
}
|
||||
results
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user