forked from Orchid/orchid
New macro system and stdlib additions
This commit is contained in:
@@ -9,7 +9,7 @@ use orchid_base::name::{NameLike, VPath};
|
||||
use orchid_base::reqnot::Requester;
|
||||
|
||||
use crate::api;
|
||||
use crate::system::{SysCtx, SysCtxEntry, WeakSysCtx};
|
||||
use crate::context::{SysCtxEntry, ctx, i};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReflMemData {
|
||||
@@ -33,37 +33,33 @@ pub enum ReflMemKind {
|
||||
pub struct ReflModData {
|
||||
inferred: Mutex<bool>,
|
||||
path: VPath,
|
||||
ctx: WeakSysCtx,
|
||||
members: MemoMap<Tok<String>, ReflMem>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ReflMod(Rc<ReflModData>);
|
||||
impl ReflMod {
|
||||
fn ctx(&self) -> SysCtx {
|
||||
self.0.ctx.upgrade().expect("ReflectedModule accessed after context drop")
|
||||
}
|
||||
pub fn path(&self) -> &[Tok<String>] { &self.0.path[..] }
|
||||
pub fn is_root(&self) -> bool { self.0.path.is_empty() }
|
||||
async fn try_populate(&self) -> Result<(), api::LsModuleError> {
|
||||
let ctx = self.ctx();
|
||||
let path_tok = ctx.i().i(&self.0.path[..]).await;
|
||||
let reply = match ctx.reqnot().request(api::LsModule(ctx.sys_id(), path_tok.to_api())).await {
|
||||
let path_tok = i().i(&self.0.path[..]).await;
|
||||
let reply = match ctx().reqnot().request(api::LsModule(ctx().sys_id(), path_tok.to_api())).await
|
||||
{
|
||||
Err(api::LsModuleError::TreeUnavailable) =>
|
||||
panic!("Reflected tree accessed outside an interpreter call. This extension is faulty."),
|
||||
Err(err) => return Err(err),
|
||||
Ok(details) => details,
|
||||
};
|
||||
for (k, v) in reply.members {
|
||||
let k = ctx.i().ex(k).await;
|
||||
let k = i().ex(k).await;
|
||||
let mem = match self.0.members.get(&k) {
|
||||
Some(mem) => mem,
|
||||
None => {
|
||||
let path = self.0.path.clone().name_with_suffix(k.clone()).to_sym(ctx.i()).await;
|
||||
let path = self.0.path.clone().name_with_suffix(k.clone()).to_sym(&i()).await;
|
||||
let kind = match v.kind {
|
||||
api::MemberInfoKind::Constant => ReflMemKind::Const,
|
||||
api::MemberInfoKind::Module =>
|
||||
ReflMemKind::Mod(default_module(&ctx, VPath::new(path.segs()))),
|
||||
ReflMemKind::Mod(default_module(VPath::new(path.segs()))),
|
||||
};
|
||||
self.0.members.get_or_insert(&k, || default_member(self.is_root(), kind))
|
||||
},
|
||||
@@ -91,7 +87,6 @@ impl ReflMod {
|
||||
self.0.members.get(key).cloned()
|
||||
}
|
||||
pub async fn get_by_path(&self, path: &[Tok<String>]) -> Result<ReflMem, InvalidPathError> {
|
||||
let ctx = self.ctx();
|
||||
let (next, tail) = path.split_first().expect("Attempted to walk by empty path");
|
||||
let inferred_g = self.0.inferred.lock().await;
|
||||
if let Some(next) = self.0.members.get(next) {
|
||||
@@ -107,7 +102,7 @@ impl ReflMod {
|
||||
if !*inferred_g {
|
||||
return Err(InvalidPathError { keep_ancestry: true });
|
||||
}
|
||||
let candidate = default_module(&ctx, self.0.path.clone().suffix([next.clone()]));
|
||||
let candidate = default_module(self.0.path.clone().suffix([next.clone()]));
|
||||
if tail.is_empty() {
|
||||
return match candidate.try_populate().await {
|
||||
Ok(()) => {
|
||||
@@ -135,6 +130,7 @@ impl ReflMod {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ReflRoot(ReflMod);
|
||||
impl SysCtxEntry for ReflRoot {}
|
||||
|
||||
@@ -143,13 +139,8 @@ pub struct InvalidPathError {
|
||||
keep_ancestry: bool,
|
||||
}
|
||||
|
||||
fn default_module(ctx: &SysCtx, path: VPath) -> ReflMod {
|
||||
ReflMod(Rc::new(ReflModData {
|
||||
ctx: ctx.downgrade(),
|
||||
inferred: Mutex::new(true),
|
||||
path,
|
||||
members: MemoMap::new(),
|
||||
}))
|
||||
fn default_module(path: VPath) -> ReflMod {
|
||||
ReflMod(Rc::new(ReflModData { inferred: Mutex::new(true), path, members: MemoMap::new() }))
|
||||
}
|
||||
|
||||
fn default_member(is_root: bool, kind: ReflMemKind) -> ReflMem {
|
||||
@@ -159,8 +150,8 @@ fn default_member(is_root: bool, kind: ReflMemKind) -> ReflMem {
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_root(ctx: &SysCtx) -> &ReflRoot {
|
||||
ctx.get_or_insert(|| ReflRoot(default_module(ctx, VPath::new([]))))
|
||||
fn get_root() -> ReflRoot {
|
||||
ctx().get_or_insert(|| ReflRoot(default_module(VPath::new([])))).clone()
|
||||
}
|
||||
|
||||
pub fn refl(ctx: &SysCtx) -> ReflMod { get_root(ctx).0.clone() }
|
||||
pub fn refl() -> ReflMod { get_root().0.clone() }
|
||||
|
||||
Reference in New Issue
Block a user