Protocols and operators mostly

This commit is contained in:
2026-01-21 22:22:58 +01:00
parent 75b05a2965
commit f38193edcc
33 changed files with 578 additions and 147 deletions

View File

@@ -1,6 +1,6 @@
use std::any::{Any, TypeId, type_name};
use std::collections::HashMap;
use std::fmt;
use std::fmt::{self, Debug};
use std::future::Future;
use std::num::NonZeroU32;
use std::ops::Deref;
@@ -144,6 +144,15 @@ impl NotTypAtom {
)
}
}
impl Debug for NotTypAtom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NotTypAtom")
.field("pos", &self.pos)
.field("expr", &self.expr)
.field("typ.name", &self.typ.name())
.finish_non_exhaustive()
}
}
pub trait AtomMethod: Request + Coding {
const NAME: &str;

View File

@@ -136,6 +136,7 @@ impl Expr {
_ => Err(self),
}
}
pub async fn pos(&self) -> Pos { self.data().await.pos.clone() }
pub fn handle(&self) -> Rc<ExprHandle> { self.handle.clone() }
pub fn slot(&self) -> GExpr {

View File

@@ -31,6 +31,19 @@ trait_set! {
trait FunCB = Fn(Vec<Expr>) -> LocalBoxFuture<'static, OrcRes<GExpr>> + 'static;
}
task_local! {
static ARGV: Vec<Expr>;
}
pub fn get_arg(idx: usize) -> Expr {
ARGV
.try_with(|argv| {
(argv.get(idx).cloned())
.unwrap_or_else(|| panic!("Cannot read argument ##{idx}, only have {}", argv.len()))
})
.expect("get_arg called outside ExprFunc")
}
pub trait ExprFunc<I, O>: Clone + 'static {
fn argtyps() -> &'static [TypeId];
fn apply<'a>(&self, hand: ExecHandle<'a>, v: Vec<Expr>) -> impl Future<Output = OrcRes<GExpr>>;

View File

@@ -184,12 +184,12 @@ impl ConstCtx {
&'b self,
names: impl IntoIterator<Item = &'b Sym> + 'b,
) -> impl Stream<Item = OrcRes<Sym>> + 'b {
let resolve_names = api::ResolveNames {
constid: self.constid,
sys: sys_id(),
names: names.into_iter().map(|n| n.to_api()).collect_vec(),
};
let names = names.into_iter().map(|n| n.to_api()).collect_vec();
stream(async |mut cx| {
if names.is_empty() {
return;
}
let resolve_names = api::ResolveNames { constid: self.constid, sys: sys_id(), names };
for name_opt in request(resolve_names).await {
cx.emit(match name_opt {
Err(e) => Err(OrcErrv::from_api(&e).await),

View File

@@ -47,8 +47,9 @@ impl ReflMod {
async fn try_populate(&self) -> Result<(), api::LsModuleError> {
let path_tok = iv(&self.0.path[..]).await;
let reply = match request(api::LsModule(sys_id(), path_tok.to_api())).await {
Err(api::LsModuleError::TreeUnavailable) =>
panic!("Reflected tree accessed outside an interpreter call. This extension is faulty."),
Err(api::LsModuleError::TreeUnavailable) => {
panic!("Reflected tree accessed outside an interpreter call. This extension is faulty.")
},
Err(err) => return Err(err),
Ok(details) => details,
};
@@ -79,10 +80,12 @@ impl ReflMod {
return None;
}
match self.try_populate().await {
Err(api::LsModuleError::InvalidPath) =>
panic!("Path became invalid since module was created"),
Err(api::LsModuleError::IsConstant) =>
panic!("Path previously contained a module but now contains a constant"),
Err(api::LsModuleError::InvalidPath) => {
panic!("Path became invalid since module was created")
},
Err(api::LsModuleError::IsConstant) => {
panic!("Path previously contained a module but now contains a constant")
},
Err(api::LsModuleError::TreeUnavailable) => unreachable!(),
Ok(()) => (),
}

View File

@@ -71,8 +71,7 @@ pub fn module(
vec![GenMember { name, kind, public, comments: vec![] }]
}
pub fn root_mod(name: &str, mems: impl IntoIterator<Item = Vec<GenMember>>) -> (String, MemKind) {
let kind = MemKind::Mod { members: mems.into_iter().flatten().collect() };
(name.to_string(), kind)
(name.to_string(), MemKind::module(mems))
}
pub fn fun<I, O>(public: bool, name: &str, xf: impl ExprFunc<I, O>) -> Vec<GenMember> {
let fac =
@@ -113,12 +112,12 @@ pub fn merge_trivial(trees: impl IntoIterator<Item = Vec<GenMember>>) -> Vec<Gen
let prev = all_members.insert(mem.name.clone(), (unit, mem.comments.into_iter().collect()));
assert!(prev.is_none(), "Conflict in trivial tree merge on {}", mem.name);
},
MemKind::Mod { members } => match all_members.entry(mem.name.clone()) {
MemKind::Mod(members) => match all_members.entry(mem.name.clone()) {
hashbrown::hash_map::Entry::Vacant(slot) => {
slot.insert((MemKind::Mod { members }, mem.comments.into_iter().collect()));
slot.insert((MemKind::Mod(members), mem.comments.into_iter().collect()));
},
hashbrown::hash_map::Entry::Occupied(mut old) => match old.get_mut() {
(MemKind::Mod { members: old_items, .. }, old_cmts) => {
(MemKind::Mod(old_items), old_cmts) => {
let mut swap = vec![];
std::mem::swap(&mut swap, old_items);
*old_items = merge_trivial([swap, members]);
@@ -167,15 +166,19 @@ impl GenMember {
pub enum MemKind {
Const(GExpr),
Mod { members: Vec<GenMember> },
Mod(Vec<GenMember>),
Lazy(LazyMemberFactory),
}
impl MemKind {
pub async fn cnst(val: impl ToExpr) -> Self { Self::Const(val.to_gen().await) }
pub fn module(mems: impl IntoIterator<Item = Vec<GenMember>>) -> Self {
Self::Mod(mems.into_iter().flatten().collect())
}
pub(crate) async fn into_api(self, ctx: &mut impl TreeIntoApiCtx) -> api::MemberKind {
match self {
Self::Lazy(lazy) => api::MemberKind::Lazy(add_lazy(ctx, lazy)),
Self::Const(c) => api::MemberKind::Const(c.serialize().await),
Self::Mod { members } => api::MemberKind::Module(api::Module {
Self::Mod(members) => api::MemberKind::Module(api::Module {
members: stream(async |mut cx| {
for m in members {
cx.emit(m.into_api(ctx).await).await