forked from Orchid/orchid
partway towards commands
I got very confused and started mucking about with "spawn" when in fact all I needed was the "inline" extension type in orcx that allows the interpreter to expose custom constants.
This commit is contained in:
@@ -1,21 +1,15 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::ops::{Add, Range};
|
||||
|
||||
use async_fn_stream::stream;
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use futures::{FutureExt, StreamExt, stream};
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::mk_errv;
|
||||
use orchid_base::format::fmt;
|
||||
use orchid_base::interner::is;
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::logging::log;
|
||||
use orchid_base::name::{NameLike, Sym, VPath};
|
||||
use orchid_base::tree::Paren;
|
||||
use orchid_extension::atom::TAtom;
|
||||
use orchid_extension::atom_owned::own;
|
||||
use orchid_base::{NameLike, Paren, Pos, Sym, VPath, fmt, is, log, mk_errv};
|
||||
use orchid_extension::TAtom;
|
||||
use orchid_extension::conv::ToExpr;
|
||||
use orchid_extension::coroutine_exec::{ExecHandle, exec};
|
||||
use orchid_extension::gen_expr::{GExpr, arg, bot, call, lambda, new_atom, sym_ref};
|
||||
use orchid_extension::coroutine_exec::exec;
|
||||
use orchid_extension::gen_expr::{GExpr, arg, bot, call, call_v, dyn_lambda, new_atom};
|
||||
use orchid_extension::reflection::{ReflMemKind, refl};
|
||||
use subslice_offset::SubsliceOffset;
|
||||
use substack::Substack;
|
||||
@@ -37,8 +31,8 @@ pub async fn resolve(val: MacTree) -> GExpr {
|
||||
.to_sym()
|
||||
.await;
|
||||
if let Ok(ReflMemKind::Const) = root.get_by_path(&new_name).await.map(|m| m.kind()) {
|
||||
let Ok(mac) = h.exec::<TAtom<Macro>>(sym_ref(new_name)).await else { continue };
|
||||
let mac = own(&mac).await;
|
||||
let Ok(mac) = h.exec::<TAtom<Macro>>(new_name).await else { continue };
|
||||
let mac = mac.own().await;
|
||||
macros.entry(mac.0.canonical_name.clone()).or_insert(mac);
|
||||
}
|
||||
}
|
||||
@@ -63,7 +57,7 @@ pub async fn resolve(val: MacTree) -> GExpr {
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut rctx = ResolveCtx { h, exclusive, priod };
|
||||
let mut rctx = ResolveCtx { exclusive, priod };
|
||||
let gex = resolve_one(&mut rctx, Substack::Bottom, &val).await;
|
||||
writeln!(
|
||||
log("debug"),
|
||||
@@ -85,7 +79,6 @@ pub struct FilteredMacroRecord<'a> {
|
||||
}
|
||||
|
||||
struct ResolveCtx<'a> {
|
||||
pub h: ExecHandle<'a>,
|
||||
/// If these overlap, that's a compile-time error
|
||||
pub exclusive: Vec<FilteredMacroRecord<'a>>,
|
||||
/// If these overlap, the priorities decide the order. In case of a tie, the
|
||||
@@ -104,7 +97,7 @@ async fn resolve_one(
|
||||
MacTok::Value(v) => v.clone().to_gen().await,
|
||||
MacTok::Name(n) => match arg_stk.iter().position(|arg| arg == n) {
|
||||
Some(de_bruijn) => arg((arg_stk.len() - 1 - de_bruijn).try_into().unwrap()),
|
||||
None => sym_ref(n.clone()),
|
||||
None => n.clone().to_gen().await,
|
||||
},
|
||||
MacTok::Lambda(arg, body) => {
|
||||
let MacTok::Name(name) = &*arg.tok else {
|
||||
@@ -116,7 +109,7 @@ async fn resolve_one(
|
||||
};
|
||||
let arg_pos = arg_stk.len() as u64;
|
||||
let arg_stk = arg_stk.push(name.clone());
|
||||
lambda(arg_pos, [resolve_seq(ctx, arg_stk, body.clone(), value.pos()).await])
|
||||
dyn_lambda(arg_pos, resolve_seq(ctx, arg_stk, body.clone(), value.pos()).await).await
|
||||
},
|
||||
MacTok::S(Paren::Round, body) => resolve_seq(ctx, arg_stk, body.clone(), value.pos()).await,
|
||||
MacTok::S(..) => bot(mk_errv(
|
||||
@@ -243,7 +236,7 @@ async fn resolve_seq(
|
||||
// backwards so that the non-overlapping ranges remain valid
|
||||
let pos = (state.names().flat_map(|r| r.1).cloned().reduce(Pos::add))
|
||||
.expect("All macro rules must contain at least one locally defined name");
|
||||
let subex = ctx.h.register(mk_body_call(mac, rule, &state, pos.clone()).await).await;
|
||||
let subex = mk_body_call(mac, rule, &state, pos.clone()).await.to_expr().await;
|
||||
new_val.splice(range, [MacTok::Value(subex).at(pos)]);
|
||||
}
|
||||
};
|
||||
@@ -261,22 +254,23 @@ async fn resolve_seq(
|
||||
let range = pre.len()..new_val.len() - suf.len();
|
||||
let pos = (state.names().flat_map(|pair| pair.1).cloned().reduce(Pos::add))
|
||||
.expect("All macro rules must contain at least one locally defined name");
|
||||
let subex = ctx.h.register(mk_body_call(mac, rule, &state, pos.clone()).await).await;
|
||||
let subex = mk_body_call(mac, rule, &state, pos.clone()).await.to_expr().await;
|
||||
std::mem::drop(state);
|
||||
new_val.splice(range, [MacTok::Value(subex).at(pos)]);
|
||||
}
|
||||
}
|
||||
let exprs = stream(async |mut h| {
|
||||
let mut exprs = stream(async |mut h| {
|
||||
for mt in new_val {
|
||||
h.emit(resolve_one(ctx, arg_stk.clone(), &mt).await).await
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.collect::<VecDeque<_>>()
|
||||
.boxed_local()
|
||||
.await;
|
||||
exprs.into_iter().reduce(|f, x| call(f, [x])).expect(
|
||||
let first = exprs.pop_front().expect(
|
||||
"We checked first that it isn't empty, and named macros get replaced with their results",
|
||||
)
|
||||
);
|
||||
stream::iter(exprs).fold(first, async |f, x| call(f, x).await).await
|
||||
}
|
||||
|
||||
async fn mk_body_call(mac: &Macro, rule: &Rule, state: &MatchState<'_>, pos: Pos) -> GExpr {
|
||||
@@ -288,5 +282,5 @@ async fn mk_body_call(mac: &Macro, rule: &Rule, state: &MatchState<'_>, pos: Pos
|
||||
new_atom(MacTok::S(Paren::Round, MacTreeSeq::new(vec.iter().cloned())).at(Pos::None)),
|
||||
});
|
||||
}
|
||||
call(sym_ref(mac.0.module.suffix([rule.body.clone()]).await), call_args).at(pos.clone())
|
||||
call_v(mac.0.module.suffix([rule.body.clone()]).await, call_args).await.at(pos.clone())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user