temp commit

This commit is contained in:
2025-07-12 00:46:10 +02:00
parent 1868f1a506
commit fe89188c4b
60 changed files with 1536 additions and 709 deletions

View File

@@ -1,50 +1,179 @@
use futures::future::LocalBoxFuture;
use std::marker::PhantomData;
use futures::FutureExt;
use futures::future::{LocalBoxFuture, join_all};
use itertools::Itertools;
use orchid_api::ResolveNames;
use orchid_base::error::OrcRes;
use orchid_base::id_store::IdStore;
use orchid_base::interner::Tok;
use orchid_base::location::SrcRange;
use orchid_base::name::Sym;
use orchid_base::parse::{Comment, Snippet};
use orchid_base::reqnot::{ReqHandlish, Requester};
use orchid_base::tree::ttv_into_api;
use crate::api;
use crate::expr::Expr;
use crate::gen_expr::GExpr;
use crate::system::SysCtx;
use crate::system::{SysCtx, SysCtxEntry};
use crate::tree::GenTokTree;
pub type GenSnippet<'a> = Snippet<'a, Expr, GExpr>;
pub trait Parser: Send + Sync + Sized + Default + 'static {
const LINE_HEAD: &'static str;
fn parse(
ctx: SysCtx,
module: Sym,
fn parse<'a>(
ctx: ParsCtx<'a>,
exported: bool,
comments: Vec<Comment>,
line: GenSnippet<'_>,
) -> impl Future<Output = OrcRes<Vec<GenTokTree>>> + '_;
line: GenSnippet<'a>,
) -> impl Future<Output = OrcRes<Vec<ParsedLine>>> + 'a;
}
pub trait DynParser: Send + Sync + 'static {
fn line_head(&self) -> &'static str;
fn parse<'a>(
&self,
ctx: SysCtx,
module: Sym,
ctx: ParsCtx<'a>,
exported: bool,
comments: Vec<Comment>,
line: GenSnippet<'a>,
) -> LocalBoxFuture<'a, OrcRes<Vec<GenTokTree>>>;
) -> LocalBoxFuture<'a, OrcRes<Vec<ParsedLine>>>;
}
impl<T: Parser> DynParser for T {
fn line_head(&self) -> &'static str { Self::LINE_HEAD }
fn parse<'a>(
&self,
ctx: SysCtx,
module: Sym,
ctx: ParsCtx<'a>,
exported: bool,
comments: Vec<Comment>,
line: GenSnippet<'a>,
) -> LocalBoxFuture<'a, OrcRes<Vec<GenTokTree>>> {
Box::pin(async move { Self::parse(ctx, module, exported, comments, line).await })
) -> LocalBoxFuture<'a, OrcRes<Vec<ParsedLine>>> {
Box::pin(async move { Self::parse(ctx, exported, comments, line).await })
}
}
pub type ParserObj = &'static dyn DynParser;
pub struct ParsCtx<'a> {
_parse: PhantomData<&'a mut ()>,
ctx: SysCtx,
module: Sym,
}
impl ParsCtx<'_> {
pub(crate) fn new(ctx: SysCtx, module: Sym) -> Self { Self { _parse: PhantomData, ctx, module } }
pub fn ctx(&self) -> &SysCtx { &self.ctx }
pub fn module(&self) -> Sym { self.module.clone() }
}
type BoxConstCallback = Box<dyn FnOnce(ConstCtx) -> LocalBoxFuture<'static, GExpr>>;
#[derive(Default)]
struct ParsedConstCtxEntry {
consts: IdStore<BoxConstCallback>,
}
impl SysCtxEntry for ParsedConstCtxEntry {}
pub struct ParsedLine {
pub sr: SrcRange,
pub comments: Vec<Comment>,
pub kind: ParsedLineKind,
}
impl ParsedLine {
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(),
source_range: self.sr.to_api(),
kind: match self.kind {
ParsedLineKind::Mem(mem) => api::ParsedLineKind::Member(api::ParsedMember {
name: mem.name.to_api(),
exported: mem.exported,
kind: match mem.kind {
ParsedMemKind::Const(cb) => api::ParsedMemberKind::Constant(api::ParsedConstId(
ctx.get_or_default::<ParsedConstCtxEntry>().consts.add(cb).id(),
)),
ParsedMemKind::Mod(plv) =>
api::ParsedMemberKind::Module(linev_into_api(plv, ctx, hand).boxed_local().await),
},
}),
ParsedLineKind::Rec(tv) =>
api::ParsedLineKind::Recursive(ttv_into_api(tv, &mut (), &mut (ctx, hand)).await),
},
}
}
}
pub(crate) async fn linev_into_api(
v: Vec<ParsedLine>,
ctx: SysCtx,
hand: &dyn ReqHandlish,
) -> Vec<api::ParsedLine> {
join_all(v.into_iter().map(|l| l.into_api(ctx.clone(), hand))).await
}
pub enum ParsedLineKind {
Mem(ParsedMem),
Rec(Vec<GenTokTree>),
}
pub struct ParsedMem {
name: Tok<String>,
exported: bool,
kind: ParsedMemKind,
}
pub enum ParsedMemKind {
Const(BoxConstCallback),
Mod(Vec<ParsedLine>),
}
impl ParsedMemKind {
pub fn cnst<F: AsyncFnOnce(ConstCtx) -> GExpr + 'static>(f: F) -> Self {
Self::Const(Box::new(|ctx| Box::pin(f(ctx))))
}
}
/* TODO: how the macro runner uses the multi-stage loader
Since the macro runner actually has to invoke the interpreter,
it'll run at const-time and not at postparse-time anyway.
pasing stage establishes the role of every constant as a macro keyword
postparse / const load links up constants with every macro they can directly invoke
the constants representing the keywords might not actually be postparsed,
\ the connection is instead made by detecting in the macro system that the
\ resolved name is owned by a macro
the returned constant from this call is always an entrypoint call to
\ the macro system
the constants representing the keywords resolve to panic
execute relies on these links detected in the extension to dispatch relevant macros
*/
pub struct ConstCtx {
ctx: SysCtx,
constid: api::ParsedConstId,
}
impl ConstCtx {
pub async fn names<const N: usize>(&self, names: [&Sym; N]) -> [Option<Sym>; N] {
let resolve_names = ResolveNames {
constid: self.constid,
sys: self.ctx.sys_id(),
names: names.into_iter().map(|n| n.to_api()).collect_vec(),
};
let names = self.ctx.reqnot().request(resolve_names).await;
let mut results = [const { None }; N];
for (i, name) in names.into_iter().enumerate().filter_map(|(i, n)| Some((i, n?))) {
results[i] = Some(Sym::from_api(name, self.ctx.i()).await);
}
results
}
}
pub(crate) async fn get_const(id: api::ParsedConstId, ctx: SysCtx) -> GExpr {
let ent = ctx.get::<ParsedConstCtxEntry>();
let rec = ent.consts.get(id.0).expect("Bad ID or double read of parsed const");
let ctx = ConstCtx { constid: id, ctx: ctx.clone() };
rec.remove()(ctx).await
}