Macro system done in theory

too afraid to begin debugging, resting for a moment
This commit is contained in:
2025-09-03 16:05:26 +02:00
parent 051b5e666f
commit 7031f3a7d8
51 changed files with 1463 additions and 458 deletions

View File

@@ -1,17 +1,20 @@
use std::pin::pin;
use async_std::stream;
use async_stream::stream;
use futures::{FutureExt, StreamExt};
use hashbrown::HashMap;
use itertools::Itertools;
use orchid_base::error::OrcRes;
use orchid_api::Paren;
use orchid_base::error::{OrcRes, Reporter};
use orchid_base::name::Sym;
use orchid_base::parse::{
Comment, ParseCtx, Parsed, Snippet, expect_tok, token_errv, try_pop_no_fluff,
};
use orchid_extension::parser::{
PSnippet, PTok, PTokTree, ParsCtx, ParsedLine, ParsedLineKind, ParsedMem, ParsedMemKind, Parser,
};
use orchid_base::sym;
use orchid_extension::gen_expr::{atom, call, sym_ref};
use orchid_extension::parser::{ConstCtx, PSnippet, PTok, PTokTree, ParsCtx, ParsedLine, Parser};
use crate::macros::mactree::{MacTok, MacTree, map_mactree_v};
use crate::macros::mactree::{MacTok, MacTree, glossary_v, map_mactree_v};
#[derive(Default)]
pub struct LetLine;
@@ -23,6 +26,7 @@ impl Parser for LetLine {
comments: Vec<Comment>,
line: PSnippet<'a>,
) -> OrcRes<Vec<ParsedLine>> {
let sr = line.sr();
let Parsed { output: name_tok, tail } = try_pop_no_fluff(&ctx, line).await?;
let Some(name) = name_tok.as_name() else {
let err = token_errv(&ctx, name_tok, "Constant must have a name", |t| {
@@ -31,44 +35,41 @@ impl Parser for LetLine {
return Err(err.await);
};
let Parsed { tail, .. } = expect_tok(&ctx, tail, ctx.i().i("=").await).await?;
let mut names = HashMap::new();
let aliased = parse_tokv(tail, &ctx).await;
map_mactree_v(&aliased, &mut false, &mut |tpl| {
if let MacTok::Name(n) = &*tpl.tok {
names.insert(n.clone(), n.clone());
Ok(vec![ParsedLine::cnst(&line.sr(), &comments, exported, name, async move |ctx| {
let rep = Reporter::new();
let dealiased = dealias_mac_v(aliased, &ctx, &rep).await;
let macro_input = MacTok::S(Paren::Round, dealiased).at(sr.pos());
if let Some(e) = rep.errv() {
return Err(e);
}
None
});
Ok(vec![ParsedLine {
comments,
sr: line.sr(),
kind: ParsedLineKind::Mem(ParsedMem {
exported,
name,
kind: ParsedMemKind::cnst(async move |ctx| {
let keys = names.keys().cloned().collect_vec();
let names_mut = &mut names;
stream! {
for await (canonical, local) in ctx.names(&keys).zip(stream::from_iter(&keys)) {
if let Some(name) = canonical {
*names_mut.get_mut(local).expect("Queried specifically the keys of this map") = name
}
}
}
.collect::<()>()
.await;
let macro_input = map_mactree_v(&aliased, &mut false, &mut |tree| match &*tree.tok {
MacTok::Name(n) => names.get(n).map(|new_n| MacTok::Name(new_n.clone()).at(tree.pos())),
_ => None,
});
todo!("Run macros then convert this into an expr")
}),
}),
}])
Ok(call([
sym_ref(sym!(macros::lower; ctx.i()).await),
call([sym_ref(sym!(macros::resolve; ctx.i()).await), atom(macro_input)]),
]))
})])
}
}
async fn parse_tokv(line: PSnippet<'_>, ctx: &ParsCtx<'_>) -> Vec<MacTree> {
pub async fn dealias_mac_v(aliased: Vec<MacTree>, ctx: &ConstCtx, rep: &Reporter) -> Vec<MacTree> {
let keys = glossary_v(&aliased).collect_vec();
let mut names: HashMap<_, _> = HashMap::new();
let mut stream = pin!(ctx.names(&keys).zip(stream::from_iter(&keys)));
while let Some((canonical, local)) = stream.next().await {
match canonical {
Err(e) => rep.report(e),
Ok(name) => {
names.insert(local.clone(), name);
},
}
}
map_mactree_v(&aliased, &mut false, &mut |tree| match &*tree.tok {
MacTok::Name(n) => names.get(n).map(|new_n| MacTok::Name(new_n.clone()).at(tree.pos())),
_ => None,
})
}
pub async fn parse_tokv(line: PSnippet<'_>, ctx: &impl ParseCtx) -> Vec<MacTree> {
if let Some((idx, arg)) = line.iter().enumerate().find_map(|(i, x)| Some((i, x.as_lambda()?))) {
let (head, lambda) = line.split_at(idx as u32);
let (_, body) = lambda.pop_front().unwrap();
@@ -89,15 +90,15 @@ async fn parse_tokv(line: PSnippet<'_>, ctx: &ParsCtx<'_>) -> Vec<MacTree> {
}
}
async fn parse_tokv_no_lambdas(line: &[PTokTree], ctx: &ParsCtx<'_>) -> Vec<MacTree> {
async fn parse_tokv_no_lambdas(line: &[PTokTree], ctx: &impl ParseCtx) -> Vec<MacTree> {
stream::from_iter(line).filter_map(|tt| parse_tok(tt, ctx)).collect().await
}
async fn parse_tok(tree: &PTokTree, ctx: &ParsCtx<'_>) -> Option<MacTree> {
pub async fn parse_tok(tree: &PTokTree, ctx: &impl ParseCtx) -> Option<MacTree> {
let tok = match &tree.tok {
PTok::Bottom(errv) => MacTok::Bottom(errv.clone()),
PTok::BR | PTok::Comment(_) => return None,
PTok::Name(n) => MacTok::Name(ctx.module().suffix([n.clone()], ctx.i()).await),
PTok::Name(n) => MacTok::Name(Sym::new([n.clone()], ctx.i()).await.unwrap()),
PTok::NS(..) => match tree.as_multiname() {
Ok(mn) => MacTok::Name(mn.to_sym(ctx.i()).await),
Err(nested) => {