forked from Orchid/orchid
exec working up to halt
clean shutdown doesn't for some reason
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use std::fmt;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
use async_lock::OnceCell;
|
||||
use derive_destructure::destructure;
|
||||
use orchid_base::format::{FmtCtx, FmtUnit, Format, take_first_fmt};
|
||||
use orchid_base::location::Pos;
|
||||
@@ -9,7 +10,7 @@ use orchid_base::tree::AtomRepr;
|
||||
|
||||
use crate::api;
|
||||
use crate::ctx::Ctx;
|
||||
use crate::expr::Expr;
|
||||
use crate::expr::{Expr, ExprParseCtx, PathSetBuilder};
|
||||
use crate::extension::Extension;
|
||||
use crate::system::System;
|
||||
|
||||
@@ -18,11 +19,12 @@ pub struct AtomData {
|
||||
owner: System,
|
||||
drop: Option<api::AtomId>,
|
||||
data: Vec<u8>,
|
||||
pub(crate) display: OnceCell<FmtUnit>,
|
||||
}
|
||||
impl AtomData {
|
||||
#[must_use]
|
||||
fn api(self) -> api::Atom {
|
||||
let (owner, drop, data) = self.destructure();
|
||||
let (owner, drop, data, _display) = self.destructure();
|
||||
api::Atom { data, drop, owner: owner.id() }
|
||||
}
|
||||
#[must_use]
|
||||
@@ -50,35 +52,22 @@ impl fmt::Debug for AtomData {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AtomHand(Rc<AtomData>);
|
||||
impl AtomHand {
|
||||
#[must_use]
|
||||
pub(crate) async fn new(api::Atom { data, drop, owner }: api::Atom, ctx: &Ctx) -> Self {
|
||||
let create = || async {
|
||||
let owner = ctx.system_inst(owner).await.expect("Dropped system created atom");
|
||||
AtomHand(Rc::new(AtomData { data, owner, drop }))
|
||||
};
|
||||
if let Some(id) = drop {
|
||||
let mut owned_g = ctx.owned_atoms.write().await;
|
||||
if let Some(data) = owned_g.get(&id)
|
||||
&& let Some(atom) = data.upgrade()
|
||||
{
|
||||
return atom;
|
||||
}
|
||||
let new = create().await;
|
||||
owned_g.insert(id, new.downgrade());
|
||||
new
|
||||
} else {
|
||||
create().await
|
||||
}
|
||||
pub(crate) fn new(data: Vec<u8>, owner: System, drop: Option<api::AtomId>) -> Self {
|
||||
Self(Rc::new(AtomData { owner, drop, data, display: OnceCell::new() }))
|
||||
}
|
||||
#[must_use]
|
||||
pub async fn call(self, arg: Expr) -> api::Expression {
|
||||
pub async fn call(self, arg: Expr) -> Expr {
|
||||
let owner_sys = self.0.owner.clone();
|
||||
let reqnot = owner_sys.reqnot();
|
||||
owner_sys.ext().exprs().give_expr(arg.clone());
|
||||
match Rc::try_unwrap(self.0) {
|
||||
let ret = match Rc::try_unwrap(self.0) {
|
||||
Ok(data) => reqnot.request(api::FinalCall(data.api(), arg.id())).await,
|
||||
Err(hand) => reqnot.request(api::CallRef(hand.api_ref(), arg.id())).await,
|
||||
}
|
||||
};
|
||||
let mut parse_ctx = ExprParseCtx { ctx: owner_sys.ctx(), exprs: owner_sys.ext().exprs() };
|
||||
let val = Expr::from_api(&ret, PathSetBuilder::new(), &mut parse_ctx).await;
|
||||
owner_sys.ext().exprs().take_expr(arg.id());
|
||||
val
|
||||
}
|
||||
#[must_use]
|
||||
pub fn sys(&self) -> &System { &self.0.owner }
|
||||
@@ -96,13 +85,19 @@ impl AtomHand {
|
||||
}
|
||||
impl Format for AtomHand {
|
||||
async fn print<'a>(&'a self, _c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
|
||||
FmtUnit::from_api(&self.0.owner.reqnot().request(api::AtomPrint(self.0.api_ref())).await)
|
||||
(self.0.display.get_or_init(|| async {
|
||||
FmtUnit::from_api(&self.0.owner.reqnot().request(api::AtomPrint(self.0.api_ref())).await)
|
||||
}))
|
||||
.await
|
||||
.clone()
|
||||
}
|
||||
}
|
||||
impl AtomRepr for AtomHand {
|
||||
type Ctx = Ctx;
|
||||
async fn from_api(atom: &orchid_api::Atom, _: Pos, ctx: &mut Self::Ctx) -> Self {
|
||||
Self::new(atom.clone(), ctx).await
|
||||
async fn from_api(atom: &api::Atom, _: Pos, ctx: &mut Self::Ctx) -> Self {
|
||||
let api::Atom { data, drop, owner } = atom.clone();
|
||||
let sys = ctx.system_inst(owner).await.expect("Dropped system created atom");
|
||||
if let Some(id) = drop { sys.new_atom(data, id).await } else { AtomHand::new(data, sys, drop) }
|
||||
}
|
||||
async fn to_api(&self) -> orchid_api::Atom { self.api_ref() }
|
||||
}
|
||||
|
||||
@@ -5,12 +5,10 @@ use std::{fmt, ops};
|
||||
|
||||
use async_lock::RwLock;
|
||||
use hashbrown::HashMap;
|
||||
use orchid_api::SysId;
|
||||
use orchid_base::builtin::Spawner;
|
||||
use orchid_base::interner::Interner;
|
||||
|
||||
use crate::api;
|
||||
use crate::atom::WeakAtomHand;
|
||||
use crate::expr_store::ExprStore;
|
||||
use crate::system::{System, WeakSystem};
|
||||
use crate::tree::WeakRoot;
|
||||
@@ -20,7 +18,6 @@ pub struct CtxData {
|
||||
pub spawn: Spawner,
|
||||
pub systems: RwLock<HashMap<api::SysId, WeakSystem>>,
|
||||
pub system_id: RefCell<NonZeroU16>,
|
||||
pub owned_atoms: RwLock<HashMap<api::AtomId, WeakAtomHand>>,
|
||||
pub common_exprs: ExprStore,
|
||||
pub root: RwLock<WeakRoot>,
|
||||
}
|
||||
@@ -46,7 +43,6 @@ impl Ctx {
|
||||
i: Interner::default(),
|
||||
systems: RwLock::default(),
|
||||
system_id: RefCell::new(NonZero::new(1).unwrap()),
|
||||
owned_atoms: RwLock::default(),
|
||||
common_exprs: ExprStore::default(),
|
||||
root: RwLock::default(),
|
||||
}))
|
||||
@@ -59,7 +55,7 @@ impl Ctx {
|
||||
pub(crate) fn next_sys_id(&self) -> api::SysId {
|
||||
let mut g = self.system_id.borrow_mut();
|
||||
*g = g.checked_add(1).unwrap_or(NonZeroU16::new(1).unwrap());
|
||||
SysId(*g)
|
||||
api::SysId(*g)
|
||||
}
|
||||
#[must_use]
|
||||
pub fn downgrade(&self) -> WeakCtx { WeakCtx(Rc::downgrade(&self.0)) }
|
||||
|
||||
@@ -9,7 +9,7 @@ use orchid_base::location::Pos;
|
||||
use orchid_base::logging::Logger;
|
||||
|
||||
use crate::ctx::Ctx;
|
||||
use crate::expr::{Expr, ExprKind, ExprParseCtx, PathSet, PathSetBuilder, Step};
|
||||
use crate::expr::{Expr, ExprKind, PathSet, Step};
|
||||
use crate::tree::Root;
|
||||
|
||||
type ExprGuard = Bound<RwLockWriteGuard<'static, ExprKind>, Expr>;
|
||||
@@ -109,11 +109,8 @@ impl ExecCtx {
|
||||
ExprKind::Call(f, x) if !self.did_pop => (ExprKind::Call(f.clone(), x), StackOp::Push(f)),
|
||||
ExprKind::Call(f, x) => match f.try_into_owned_atom().await {
|
||||
Ok(atom) => {
|
||||
let ext = atom.sys().ext().clone();
|
||||
let x_norm = self.unpack_ident(&x).await;
|
||||
let mut parse_ctx = ExprParseCtx { ctx: &self.ctx, exprs: ext.exprs() };
|
||||
let val =
|
||||
Expr::from_api(&atom.call(x_norm).await, PathSetBuilder::new(), &mut parse_ctx).await;
|
||||
let val = atom.call(x_norm).await;
|
||||
(ExprKind::Identity(val.clone()), StackOp::Swap(val))
|
||||
},
|
||||
Err(f) => match &*f.kind().read().await {
|
||||
@@ -121,15 +118,9 @@ impl ExecCtx {
|
||||
panic!("This should not appear outside function bodies"),
|
||||
ExprKind::Missing => panic!("Should have been replaced"),
|
||||
ExprKind::Atom(a) => {
|
||||
let ext = a.sys().ext().clone();
|
||||
let x_norm = self.unpack_ident(&x).await;
|
||||
let val = Expr::from_api(
|
||||
&a.clone().call(x_norm).await,
|
||||
PathSetBuilder::new(),
|
||||
&mut ExprParseCtx { ctx: ext.ctx(), exprs: ext.exprs() },
|
||||
)
|
||||
.await;
|
||||
(ExprKind::Identity(val.clone()), StackOp::Swap(val))
|
||||
let ret = a.clone().call(x_norm).await;
|
||||
(ExprKind::Identity(ret.clone()), StackOp::Swap(ret))
|
||||
},
|
||||
ExprKind::Bottom(exprv) => (ExprKind::Bottom(exprv.clone()), StackOp::Pop),
|
||||
ExprKind::Lambda(None, body) =>
|
||||
|
||||
@@ -6,7 +6,6 @@ use std::{fmt, mem};
|
||||
|
||||
use async_lock::RwLock;
|
||||
use futures::FutureExt;
|
||||
use hashbrown::HashSet;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::OrcErrv;
|
||||
use orchid_base::format::{FmtCtx, FmtUnit, Format, Variants};
|
||||
@@ -116,19 +115,18 @@ impl Expr {
|
||||
}
|
||||
impl Format for Expr {
|
||||
async fn print<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
|
||||
return print_expr(self, c, &mut HashSet::new()).await;
|
||||
return print_expr(self, c, Substack::Bottom).await;
|
||||
}
|
||||
}
|
||||
async fn print_expr<'a>(
|
||||
expr: &'a Expr,
|
||||
c: &'a (impl FmtCtx + ?Sized + 'a),
|
||||
visited: &mut HashSet<api::ExprTicket>,
|
||||
visited: Substack<'_, api::ExprTicket>,
|
||||
) -> FmtUnit {
|
||||
if visited.contains(&expr.id()) {
|
||||
if visited.iter().any(|id| id == &expr.id()) {
|
||||
return "CYCLIC_EXPR".to_string().into();
|
||||
}
|
||||
visited.insert(expr.id());
|
||||
print_exprkind(&*expr.kind().read().await, c, visited).boxed_local().await
|
||||
print_exprkind(&*expr.kind().read().await, c, visited.push(expr.id())).boxed_local().await
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -152,13 +150,13 @@ impl ExprKind {
|
||||
}
|
||||
impl Format for ExprKind {
|
||||
async fn print<'a>(&'a self, c: &'a (impl FmtCtx + ?Sized + 'a)) -> FmtUnit {
|
||||
print_exprkind(self, c, &mut HashSet::new()).await
|
||||
print_exprkind(self, c, Substack::Bottom).await
|
||||
}
|
||||
}
|
||||
async fn print_exprkind<'a>(
|
||||
ek: &ExprKind,
|
||||
c: &'a (impl FmtCtx + ?Sized + 'a),
|
||||
visited: &mut HashSet<api::ExprTicket>,
|
||||
visited: Substack<'_, api::ExprTicket>,
|
||||
) -> FmtUnit {
|
||||
match &ek {
|
||||
ExprKind::Arg => "Arg".to_string().into(),
|
||||
|
||||
@@ -28,9 +28,15 @@ impl ExprStore {
|
||||
},
|
||||
}
|
||||
}
|
||||
pub fn take_expr(&self, ticket: api::ExprTicket) {
|
||||
(self.0.exprs.borrow_mut().entry(ticket))
|
||||
.and_replace_entry_with(|_, (rc, rt)| (1 < rc).then_some((rc - 1, rt)));
|
||||
pub fn take_expr(&self, ticket: api::ExprTicket) -> Option<Expr> {
|
||||
match self.0.exprs.borrow_mut().entry(ticket) {
|
||||
Entry::Vacant(_) => None,
|
||||
Entry::Occupied(oe) if oe.get().0 == 1 => Some(oe.remove().1),
|
||||
Entry::Occupied(mut oe) => {
|
||||
oe.get_mut().0 -= 1;
|
||||
Some(oe.get().1.clone())
|
||||
},
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub fn get_expr(&self, ticket: api::ExprTicket) -> Option<Expr> {
|
||||
|
||||
@@ -18,9 +18,11 @@ use orchid_base::builtin::ExtInit;
|
||||
use orchid_base::clone;
|
||||
use orchid_base::format::{FmtCtxImpl, Format};
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::logging::Logger;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::reqnot::{DynRequester, ReqNot, Requester as _};
|
||||
use orchid_base::tree::AtomRepr;
|
||||
|
||||
use crate::api;
|
||||
use crate::atom::AtomHand;
|
||||
@@ -100,7 +102,7 @@ impl Extension {
|
||||
}
|
||||
api::ExtHostNotif::ExprNotif(api::ExprNotif::Release(rel)) => {
|
||||
this.assert_own_sys(rel.0).await;
|
||||
this.0.exprs.take_expr(rel.1)
|
||||
this.0.exprs.take_expr(rel.1);
|
||||
}
|
||||
api::ExtHostNotif::ExprNotif(api::ExprNotif::Move(mov)) => {
|
||||
this.assert_own_sys(mov.dec).await;
|
||||
@@ -173,8 +175,8 @@ impl Extension {
|
||||
let path = i.ex(path).await;
|
||||
let root = (ctx.root.read().await.upgrade())
|
||||
.expect("LSModule called when root isn't in context");
|
||||
let root_data = &mut *root.0.write().await;
|
||||
let mut walk_ctx = (ctx.clone(), &mut root_data.consts);
|
||||
let root_data = &*root.0.read().await;
|
||||
let mut walk_ctx = (ctx.clone(), &root_data.consts);
|
||||
let module =
|
||||
match walk(&root_data.root, false, path.iter().cloned(), &mut walk_ctx)
|
||||
.await
|
||||
@@ -189,7 +191,7 @@ impl Extension {
|
||||
};
|
||||
let mut members = std::collections::HashMap::new();
|
||||
for (k, v) in &module.members {
|
||||
let kind = match v.kind(ctx.clone(), &mut root_data.consts).await {
|
||||
let kind = match v.kind(ctx.clone(), &root_data.consts).await {
|
||||
MemberKind::Const => api::MemberInfoKind::Constant,
|
||||
MemberKind::Module(_) => api::MemberInfoKind::Module,
|
||||
};
|
||||
@@ -221,7 +223,7 @@ impl Extension {
|
||||
hand.handle(rn, &responses).await
|
||||
},
|
||||
api::ExtHostReq::ExtAtomPrint(ref eap @ api::ExtAtomPrint(ref atom)) => {
|
||||
let atom = AtomHand::new(atom.clone(), &ctx).await;
|
||||
let atom = AtomHand::from_api(atom, Pos::None, &mut ctx.clone()).await;
|
||||
let unit = atom.print(&FmtCtxImpl { i: &this.ctx().i }).await;
|
||||
hand.handle(eap, &unit.to_api()).await
|
||||
},
|
||||
|
||||
@@ -8,12 +8,11 @@ use orchid_base::location::SrcRange;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::parse::{name_char, name_start, op_char, unrep_space};
|
||||
use orchid_base::tokens::PARENS;
|
||||
use orchid_base::tree::recur;
|
||||
|
||||
use crate::api;
|
||||
use crate::ctx::Ctx;
|
||||
use crate::expr::{Expr, ExprParseCtx, ExprWillPanic};
|
||||
use crate::parsed::{ParsTok, ParsTokTree};
|
||||
use crate::expr::{Expr, ExprParseCtx};
|
||||
use crate::parsed::{ParsTok, ParsTokTree, tt_to_api};
|
||||
use crate::system::System;
|
||||
|
||||
pub struct LexCtx<'a> {
|
||||
@@ -54,14 +53,7 @@ impl<'a> LexCtx<'a> {
|
||||
}
|
||||
#[must_use]
|
||||
pub async fn ser_subtree(&mut self, subtree: ParsTokTree) -> api::TokenTree {
|
||||
let mut exprs = self.ctx.common_exprs.clone();
|
||||
let without_new_expr = recur(subtree, &|tt, r| {
|
||||
if let ParsTok::NewExpr(expr) = tt.tok {
|
||||
return ParsTok::Handle(expr).at(tt.sr);
|
||||
}
|
||||
r(tt)
|
||||
});
|
||||
without_new_expr.into_api(&mut exprs, &mut ExprWillPanic).await
|
||||
tt_to_api(&mut self.ctx.common_exprs.clone(), subtree).await
|
||||
}
|
||||
#[must_use]
|
||||
pub async fn des_subtree(&mut self, tree: &api::TokenTree) -> ParsTokTree {
|
||||
|
||||
@@ -11,5 +11,6 @@ pub mod lex;
|
||||
pub mod parse;
|
||||
pub mod parsed;
|
||||
pub mod subprocess;
|
||||
mod sys_parser;
|
||||
pub mod system;
|
||||
pub mod tree;
|
||||
|
||||
@@ -33,6 +33,7 @@ impl ParseCtx for HostParseCtxImpl<'_> {
|
||||
impl HostParseCtx for HostParseCtxImpl<'_> {
|
||||
fn ctx(&self) -> &Ctx { &self.ctx }
|
||||
fn systems(&self) -> impl Iterator<Item = &System> { self.systems.iter() }
|
||||
fn src_path(&self) -> Sym { self.src.clone() }
|
||||
}
|
||||
|
||||
pub trait HostParseCtx: ParseCtx {
|
||||
@@ -40,6 +41,8 @@ pub trait HostParseCtx: ParseCtx {
|
||||
fn ctx(&self) -> &Ctx;
|
||||
#[must_use]
|
||||
fn systems(&self) -> impl Iterator<Item = &System>;
|
||||
#[must_use]
|
||||
fn src_path(&self) -> Sym;
|
||||
}
|
||||
|
||||
pub async fn parse_items(
|
||||
@@ -109,9 +112,9 @@ pub async fn parse_exportable_item<'a>(
|
||||
let kind = if discr == ctx.i().i("mod").await {
|
||||
let (name, body) = parse_module(ctx, path, tail).await?;
|
||||
ItemKind::Member(ParsedMember { name, exported, kind: ParsedMemberKind::Mod(body) })
|
||||
} else if let Some(sys) = ctx.systems().find(|s| s.can_parse(discr.clone())) {
|
||||
return sys
|
||||
.parse(path, tail.to_vec(), exported, comments, &mut async |stack, lines| {
|
||||
} else if let Some(parser) = ctx.systems().find_map(|s| s.get_parser(discr.clone())) {
|
||||
return parser
|
||||
.parse(ctx, path, tail.to_vec(), exported, comments, &mut async |stack, lines| {
|
||||
let source = Snippet::new(lines.first().unwrap(), &lines);
|
||||
parse_items(ctx, stack, source).await
|
||||
})
|
||||
|
||||
@@ -10,11 +10,12 @@ use orchid_base::interner::Tok;
|
||||
use orchid_base::location::SrcRange;
|
||||
use orchid_base::parse::{Comment, Import};
|
||||
use orchid_base::tl_cache;
|
||||
use orchid_base::tree::{TokTree, Token};
|
||||
use orchid_base::tree::{TokTree, Token, recur};
|
||||
|
||||
use crate::api;
|
||||
use crate::dealias::{ChildErrorKind, ChildResult, Tree};
|
||||
use crate::expr::Expr;
|
||||
use crate::expr::{Expr, ExprWillPanic};
|
||||
use crate::expr_store::ExprStore;
|
||||
use crate::system::System;
|
||||
|
||||
pub type ParsTokTree = TokTree<Expr, Expr>;
|
||||
@@ -54,7 +55,7 @@ impl Format for Item {
|
||||
let item_text = match &self.kind {
|
||||
ItemKind::Import(i) => format!("import {i}").into(),
|
||||
ItemKind::Member(mem) => match &mem.kind {
|
||||
ParsedMemberKind::DeferredConst(_, sys) =>
|
||||
ParsedMemberKind::Const(_, sys) =>
|
||||
tl_cache!(Rc<Variants>: Rc::new(Variants::default().bounded("const {0} via {1}")))
|
||||
.units([mem.name.rc().into(), sys.print(c).await]),
|
||||
ParsedMemberKind::Mod(module) =>
|
||||
@@ -106,7 +107,7 @@ impl fmt::Debug for ParsedExpr {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParsedMemberKind {
|
||||
DeferredConst(api::ParsedConstId, System),
|
||||
Const(api::ParsedConstId, System),
|
||||
Mod(ParsedModule),
|
||||
}
|
||||
impl From<ParsedModule> for ParsedMemberKind {
|
||||
@@ -162,7 +163,7 @@ impl Tree for ParsedModule {
|
||||
.find(|m| m.name == key)
|
||||
{
|
||||
match &member.kind {
|
||||
ParsedMemberKind::DeferredConst(..) => return ChildResult::Err(ChildErrorKind::Constant),
|
||||
ParsedMemberKind::Const(..) => return ChildResult::Err(ChildErrorKind::Constant),
|
||||
ParsedMemberKind::Mod(m) => return ChildResult::Ok(m),
|
||||
}
|
||||
}
|
||||
@@ -191,15 +192,6 @@ impl Format for ParsedModule {
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO:
|
||||
///
|
||||
/// idea, does the host need an IR here or can we figure out a way to transcribe
|
||||
/// these? Should we spin off a new stage for value parsing so that ParsTokTree
|
||||
/// doesn't appear in the interpreter's ingress?
|
||||
pub struct Const {
|
||||
pub source: Option<Vec<ParsTokTree>>,
|
||||
}
|
||||
|
||||
/// Selects a code element
|
||||
///
|
||||
/// Either the steps point to a constant and rule_loc is None, or the steps
|
||||
@@ -212,3 +204,13 @@ impl ConstPath {
|
||||
#[must_use]
|
||||
pub fn to_const(steps: Tok<Vec<Tok<String>>>) -> Self { Self { steps } }
|
||||
}
|
||||
|
||||
pub async fn tt_to_api(exprs: &mut ExprStore, subtree: ParsTokTree) -> api::TokenTree {
|
||||
let without_new_expr = recur(subtree, &|tt, r| {
|
||||
if let ParsTok::NewExpr(expr) = tt.tok {
|
||||
return ParsTok::Handle(expr).at(tt.sr);
|
||||
}
|
||||
r(tt)
|
||||
});
|
||||
without_new_expr.into_api(exprs, &mut ExprWillPanic).await
|
||||
}
|
||||
|
||||
119
orchid-host/src/sys_parser.rs
Normal file
119
orchid-host/src/sys_parser.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
use futures::FutureExt;
|
||||
use futures::future::join_all;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::{OrcErrv, OrcRes};
|
||||
use orchid_base::interner::{Interner, Tok};
|
||||
use orchid_base::location::SrcRange;
|
||||
use orchid_base::name::Sym;
|
||||
use orchid_base::parse::Comment;
|
||||
use orchid_base::reqnot::Requester;
|
||||
use orchid_base::tree::ttv_from_api;
|
||||
use substack::Substack;
|
||||
|
||||
use crate::api;
|
||||
use crate::expr::ExprParseCtx;
|
||||
use crate::expr_store::ExprStore;
|
||||
use crate::parse::HostParseCtx;
|
||||
use crate::parsed::{
|
||||
Item, ItemKind, ParsTokTree, ParsedMember, ParsedMemberKind, ParsedModule, tt_to_api,
|
||||
};
|
||||
use crate::system::System;
|
||||
|
||||
pub struct Parser {
|
||||
pub(crate) system: System,
|
||||
pub(crate) idx: u16,
|
||||
}
|
||||
type ModPath<'a> = Substack<'a, Tok<String>>;
|
||||
|
||||
impl Parser {
|
||||
pub async fn parse(
|
||||
&self,
|
||||
ctx: &impl HostParseCtx,
|
||||
path: ModPath<'_>,
|
||||
line: Vec<ParsTokTree>,
|
||||
exported: bool,
|
||||
comments: Vec<Comment>,
|
||||
callback: &mut impl AsyncFnMut(ModPath<'_>, Vec<ParsTokTree>) -> OrcRes<Vec<Item>>,
|
||||
) -> OrcRes<Vec<Item>> {
|
||||
let src_path = line.first().expect("cannot be empty").sr.path();
|
||||
let line = join_all(
|
||||
(line.into_iter())
|
||||
.map(|t| async { tt_to_api(&mut self.system.ext().exprs().clone(), t).await }),
|
||||
)
|
||||
.await;
|
||||
let mod_path = ctx.src_path().suffix(path.unreverse(), self.system.i()).await;
|
||||
let comments = comments.iter().map(Comment::to_api).collect_vec();
|
||||
let req = api::ParseLine {
|
||||
idx: self.idx,
|
||||
module: mod_path.to_api(),
|
||||
src: src_path.to_api(),
|
||||
exported,
|
||||
sys: self.system.id(),
|
||||
comments,
|
||||
line,
|
||||
};
|
||||
match self.system.reqnot().request(req).await {
|
||||
Ok(parsed_v) => {
|
||||
let mut ext_exprs = self.system.ext().exprs().clone();
|
||||
conv(parsed_v, path, callback, &mut ConvCtx {
|
||||
i: self.system.i(),
|
||||
mod_path: &mod_path,
|
||||
ext_exprs: &mut ext_exprs,
|
||||
pctx: &mut ExprParseCtx { ctx: self.system.ctx(), exprs: self.system.ext().exprs() },
|
||||
src_path: &src_path,
|
||||
sys: &self.system,
|
||||
})
|
||||
.await
|
||||
},
|
||||
Err(e) => Err(OrcErrv::from_api(&e, &self.system.ctx().i).await),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ConvCtx<'a> {
|
||||
sys: &'a System,
|
||||
mod_path: &'a Sym,
|
||||
src_path: &'a Sym,
|
||||
i: &'a Interner,
|
||||
ext_exprs: &'a mut ExprStore,
|
||||
pctx: &'a mut ExprParseCtx<'a>,
|
||||
}
|
||||
async fn conv(
|
||||
parsed_v: Vec<api::ParsedLine>,
|
||||
module: Substack<'_, Tok<String>>,
|
||||
callback: &'_ mut impl AsyncFnMut(Substack<'_, Tok<String>>, Vec<ParsTokTree>) -> OrcRes<Vec<Item>>,
|
||||
ctx: &mut ConvCtx<'_>,
|
||||
) -> OrcRes<Vec<Item>> {
|
||||
let mut items = Vec::new();
|
||||
for parsed in parsed_v {
|
||||
let (name, exported, kind) = match parsed.kind {
|
||||
api::ParsedLineKind::Member(api::ParsedMember { name, exported, kind }) =>
|
||||
(name, exported, kind),
|
||||
api::ParsedLineKind::Recursive(rec) => {
|
||||
let tokens = ttv_from_api(rec, ctx.ext_exprs, ctx.pctx, ctx.src_path, ctx.i).await;
|
||||
items.extend(callback(module.clone(), tokens).await?);
|
||||
continue;
|
||||
},
|
||||
};
|
||||
let name = ctx.i.ex(name).await;
|
||||
let mkind = match kind {
|
||||
api::ParsedMemberKind::Module { lines, use_prelude } => {
|
||||
let items = conv(lines, module.push(name.clone()), callback, ctx).boxed_local().await?;
|
||||
ParsedMemberKind::Mod(ParsedModule::new(use_prelude, items))
|
||||
},
|
||||
api::ParsedMemberKind::Constant(cid) => {
|
||||
ctx.sys.0.const_paths.insert(cid, ctx.mod_path.suffix(module.unreverse(), ctx.i).await);
|
||||
ParsedMemberKind::Const(cid, ctx.sys.clone())
|
||||
},
|
||||
};
|
||||
items.push(Item {
|
||||
comments: join_all(
|
||||
parsed.comments.iter().map(|c| Comment::from_api(c, ctx.src_path.clone(), ctx.i)),
|
||||
)
|
||||
.await,
|
||||
sr: SrcRange::from_api(&parsed.source_range, ctx.i).await,
|
||||
kind: ItemKind::Member(ParsedMember { name, exported, kind: mkind }),
|
||||
})
|
||||
}
|
||||
Ok(items)
|
||||
}
|
||||
@@ -3,38 +3,32 @@ use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
use async_lock::RwLock;
|
||||
use derive_destructure::destructure;
|
||||
use futures::FutureExt;
|
||||
use futures::future::join_all;
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use memo_map::MemoMap;
|
||||
use orchid_base::char_filter::char_filter_match;
|
||||
use orchid_base::error::{OrcErrv, OrcRes, mk_errv_floating};
|
||||
use orchid_base::error::{OrcRes, mk_errv_floating};
|
||||
use orchid_base::format::{FmtCtx, FmtUnit, Format};
|
||||
use orchid_base::interner::{Interner, Tok};
|
||||
use orchid_base::iter_utils::IteratorPrint;
|
||||
use orchid_base::location::SrcRange;
|
||||
use orchid_base::name::{NameLike, Sym, VName, VPath};
|
||||
use orchid_base::parse::Comment;
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
use orchid_base::tree::{recur, ttv_from_api};
|
||||
use ordered_float::NotNan;
|
||||
use substack::{Stackframe, Substack};
|
||||
|
||||
use crate::api;
|
||||
use crate::atom::{AtomHand, WeakAtomHand};
|
||||
use crate::ctx::Ctx;
|
||||
use crate::dealias::walk;
|
||||
use crate::expr::{ExprParseCtx, ExprWillPanic};
|
||||
use crate::expr_store::ExprStore;
|
||||
use crate::extension::{Extension, WeakExtension};
|
||||
use crate::parsed::{
|
||||
Item, ItemKind, ParsTok, ParsTokTree, ParsedMember, ParsedMemberKind, ParsedModule,
|
||||
};
|
||||
use crate::sys_parser::Parser;
|
||||
use crate::tree::Root;
|
||||
|
||||
#[derive(destructure)]
|
||||
struct SystemInstData {
|
||||
pub(crate) struct SystemInstData {
|
||||
deps: Vec<System>,
|
||||
ctx: Ctx,
|
||||
ext: Extension,
|
||||
@@ -43,6 +37,7 @@ struct SystemInstData {
|
||||
id: api::SysId,
|
||||
line_types: Vec<Tok<String>>,
|
||||
prelude: Vec<Sym>,
|
||||
owned_atoms: RwLock<HashMap<api::AtomId, WeakAtomHand>>,
|
||||
pub(crate) const_paths: MemoMap<api::ParsedConstId, Sym>,
|
||||
}
|
||||
impl Drop for SystemInstData {
|
||||
@@ -60,7 +55,7 @@ impl fmt::Debug for SystemInstData {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct System(Rc<SystemInstData>);
|
||||
pub struct System(pub(crate) Rc<SystemInstData>);
|
||||
impl System {
|
||||
#[must_use]
|
||||
pub fn id(&self) -> api::SysId { self.0.id }
|
||||
@@ -101,108 +96,32 @@ impl System {
|
||||
self.0.ext.lex_req(source, src, pos, self.id(), r).await
|
||||
}
|
||||
#[must_use]
|
||||
pub fn can_parse(&self, ltyp: Tok<String>) -> bool { self.0.line_types.contains(<yp) }
|
||||
pub fn line_types(&self) -> impl Iterator<Item = &Tok<String>> + '_ { self.0.line_types.iter() }
|
||||
pub async fn parse(
|
||||
&self,
|
||||
path: Substack<'_, Tok<String>>,
|
||||
line: Vec<ParsTokTree>,
|
||||
exported: bool,
|
||||
comments: Vec<Comment>,
|
||||
callback: &mut impl AsyncFnMut(Substack<'_, Tok<String>>, Vec<ParsTokTree>) -> OrcRes<Vec<Item>>,
|
||||
) -> OrcRes<Vec<Item>> {
|
||||
let src_path = line.first().expect("cannot be empty").sr.path();
|
||||
let line = join_all(line.into_iter().map(|t| async {
|
||||
let mut expr_store = self.0.ext.exprs().clone();
|
||||
let without_new_expr = recur(t, &|t, r| {
|
||||
if let ParsTok::NewExpr(expr) = t.tok {
|
||||
return ParsTok::Handle(expr).at(t.sr);
|
||||
}
|
||||
r(t)
|
||||
});
|
||||
without_new_expr.into_api(&mut expr_store, &mut ExprWillPanic).await
|
||||
}))
|
||||
.await;
|
||||
let comments = comments.iter().map(Comment::to_api).collect_vec();
|
||||
let req = api::ParseLine {
|
||||
module: self.i().i(&path.unreverse()).await.to_api(),
|
||||
src: src_path.to_api(),
|
||||
exported,
|
||||
sys: self.id(),
|
||||
comments,
|
||||
line,
|
||||
};
|
||||
match self.reqnot().request(req).await {
|
||||
Ok(parsed_v) => {
|
||||
let mut ext_exprs = self.ext().exprs().clone();
|
||||
struct ConvCtx<'a> {
|
||||
sys: &'a System,
|
||||
src_path: &'a Sym,
|
||||
i: &'a Interner,
|
||||
ext_exprs: &'a mut ExprStore,
|
||||
pctx: &'a mut ExprParseCtx<'a>,
|
||||
}
|
||||
async fn conv(
|
||||
parsed_v: Vec<api::ParsedLine>,
|
||||
module: Substack<'_, Tok<String>>,
|
||||
callback: &'_ mut impl AsyncFnMut(
|
||||
Substack<'_, Tok<String>>,
|
||||
Vec<ParsTokTree>,
|
||||
) -> OrcRes<Vec<Item>>,
|
||||
ctx: &mut ConvCtx<'_>,
|
||||
) -> OrcRes<Vec<Item>> {
|
||||
let mut items = Vec::new();
|
||||
for parsed in parsed_v {
|
||||
let (name, exported, kind) = match parsed.kind {
|
||||
api::ParsedLineKind::Member(api::ParsedMember { name, exported, kind }) =>
|
||||
(name, exported, kind),
|
||||
api::ParsedLineKind::Recursive(rec) => {
|
||||
let tokens = ttv_from_api(rec, ctx.ext_exprs, ctx.pctx, ctx.src_path, ctx.i).await;
|
||||
items.extend(callback(module.clone(), tokens).await?);
|
||||
continue;
|
||||
},
|
||||
};
|
||||
let name = ctx.i.ex(name).await;
|
||||
let mkind = match kind {
|
||||
api::ParsedMemberKind::Module { lines, use_prelude } => {
|
||||
let items =
|
||||
conv(lines, module.push(name.clone()), callback, ctx).boxed_local().await?;
|
||||
ParsedMemberKind::Mod(ParsedModule::new(use_prelude, items))
|
||||
},
|
||||
api::ParsedMemberKind::Constant(cid) =>
|
||||
ParsedMemberKind::DeferredConst(cid, ctx.sys.clone()),
|
||||
};
|
||||
items.push(Item {
|
||||
comments: join_all(
|
||||
parsed.comments.iter().map(|c| Comment::from_api(c, ctx.src_path.clone(), ctx.i)),
|
||||
)
|
||||
.await,
|
||||
sr: SrcRange::from_api(&parsed.source_range, ctx.i).await,
|
||||
kind: ItemKind::Member(ParsedMember { name, exported, kind: mkind }),
|
||||
})
|
||||
}
|
||||
Ok(items)
|
||||
}
|
||||
conv(parsed_v, path, callback, &mut ConvCtx {
|
||||
i: self.i(),
|
||||
ext_exprs: &mut ext_exprs,
|
||||
pctx: &mut ExprParseCtx { ctx: self.ctx(), exprs: self.ext().exprs() },
|
||||
src_path: &src_path,
|
||||
sys: self,
|
||||
})
|
||||
.await
|
||||
},
|
||||
Err(e) => Err(OrcErrv::from_api(&e, &self.ctx().i).await),
|
||||
}
|
||||
pub fn get_parser(&self, ltyp: Tok<String>) -> Option<Parser> {
|
||||
(self.0.line_types.iter().enumerate())
|
||||
.find(|(_, txt)| *txt == <yp)
|
||||
.map(|(idx, _)| Parser { idx: idx as u16, system: self.clone() })
|
||||
}
|
||||
pub fn line_types(&self) -> impl Iterator<Item = &Tok<String>> + '_ { self.0.line_types.iter() }
|
||||
|
||||
#[must_use]
|
||||
pub async fn request(&self, req: Vec<u8>) -> Vec<u8> {
|
||||
self.reqnot().request(api::SysFwded(self.id(), req)).await
|
||||
}
|
||||
pub(crate) async fn new_atom(&self, data: Vec<u8>, id: api::AtomId) -> AtomHand {
|
||||
let mut owned_g = self.0.owned_atoms.write().await;
|
||||
if let Some(data) = owned_g.get(&id)
|
||||
&& let Some(atom) = data.upgrade()
|
||||
{
|
||||
return atom;
|
||||
}
|
||||
let new = AtomHand::new(data, self.clone(), Some(id));
|
||||
owned_g.insert(id, new.downgrade());
|
||||
new
|
||||
}
|
||||
pub(crate) fn drop_atom(&self, drop: api::AtomId) {
|
||||
let this = self.0.clone();
|
||||
(self.0.ctx.spawn)(Box::pin(async move {
|
||||
this.ctx.owned_atoms.write().await.remove(&drop);
|
||||
this.owned_atoms.write().await.remove(&drop);
|
||||
}))
|
||||
}
|
||||
#[must_use]
|
||||
@@ -218,7 +137,7 @@ impl System {
|
||||
async move |rel| {
|
||||
let cwd = orig.split_last_seg().1;
|
||||
let root_data = &mut *root.0.write().await;
|
||||
let walk_ctx = &mut (ctx.clone(), &mut root_data.consts);
|
||||
let walk_ctx = &mut (ctx.clone(), &root_data.consts);
|
||||
let cmod = (walk(&root_data.root, false, cwd.iter().cloned(), walk_ctx).await)
|
||||
.expect("the parent module of a constant should exist");
|
||||
let (selector, tail) = rel.split_first().expect("Names cannot be empty");
|
||||
@@ -298,6 +217,7 @@ impl SystemCtor {
|
||||
.await,
|
||||
id,
|
||||
prelude: join_all(sys_inst.prelude.iter().map(|tok| Sym::from_api(*tok, &ext.ctx().i))).await,
|
||||
owned_atoms: RwLock::new(HashMap::new()),
|
||||
const_paths: MemoMap::new(),
|
||||
}));
|
||||
let api_module_root = api::Module {
|
||||
|
||||
@@ -10,6 +10,7 @@ use futures::{FutureExt, StreamExt, stream};
|
||||
use hashbrown::HashMap;
|
||||
use hashbrown::hash_map::Entry;
|
||||
use itertools::Itertools;
|
||||
use memo_map::MemoMap;
|
||||
use orchid_base::clone;
|
||||
use orchid_base::error::{OrcRes, Reporter, mk_errv};
|
||||
use orchid_base::interner::Tok;
|
||||
@@ -26,7 +27,7 @@ use crate::system::System;
|
||||
|
||||
pub struct RootData {
|
||||
pub root: Module,
|
||||
pub consts: HashMap<Sym, Expr>,
|
||||
pub consts: MemoMap<Sym, Expr>,
|
||||
pub ctx: Ctx,
|
||||
}
|
||||
#[derive(Clone)]
|
||||
@@ -36,23 +37,25 @@ impl Root {
|
||||
pub fn new(ctx: Ctx) -> Self {
|
||||
Root(Rc::new(RwLock::new(RootData {
|
||||
root: Module::default(),
|
||||
consts: HashMap::default(),
|
||||
consts: MemoMap::default(),
|
||||
ctx,
|
||||
})))
|
||||
}
|
||||
#[must_use]
|
||||
pub async fn from_api(api: api::Module, sys: &System) -> Self {
|
||||
let mut consts = HashMap::new();
|
||||
let mut tfac = TreeFromApiCtx { consts: &mut consts, path: sys.i().i(&[][..]).await, sys };
|
||||
let consts = MemoMap::new();
|
||||
let mut tfac = TreeFromApiCtx { consts: &consts, path: sys.i().i(&[][..]).await, sys };
|
||||
let root = Module::from_api(api, &mut tfac).await;
|
||||
Root(Rc::new(RwLock::new(RootData { root, consts, ctx: sys.ctx().clone() })))
|
||||
}
|
||||
pub async fn merge(&self, new: &Root) -> Result<Self, MergeErr> {
|
||||
let this = self.0.read().await;
|
||||
let that = new.0.read().await;
|
||||
let mut consts =
|
||||
this.consts.iter().chain(&that.consts).map(|(k, v)| (k.clone(), v.clone())).collect();
|
||||
let root = this.root.merge(&that.root, this.ctx.clone(), &mut consts).await?;
|
||||
let this = self.0.write().await;
|
||||
let that = new.0.write().await;
|
||||
let consts = MemoMap::new();
|
||||
for (k, v) in this.consts.iter().chain(that.consts.iter()) {
|
||||
consts.insert(k.clone(), v.clone());
|
||||
}
|
||||
let root = this.root.merge(&that.root, this.ctx.clone(), &consts).await?;
|
||||
Ok(Self(Rc::new(RwLock::new(RootData { root, consts, ctx: this.ctx.clone() }))))
|
||||
}
|
||||
#[must_use]
|
||||
@@ -60,11 +63,11 @@ impl Root {
|
||||
let mut ref_this = self.0.write().await;
|
||||
let this = &mut *ref_this;
|
||||
let mut deferred_consts = HashMap::new();
|
||||
let mut consts = this.consts.clone();
|
||||
let consts = this.consts.clone();
|
||||
let mut tfpctx = FromParsedCtx {
|
||||
pars_root: parsed,
|
||||
deferred_consts: &mut deferred_consts,
|
||||
consts: &mut consts,
|
||||
consts: &consts,
|
||||
pars_prefix: pars_prefix.clone(),
|
||||
root: &this.root,
|
||||
ctx: &this.ctx,
|
||||
@@ -79,7 +82,7 @@ impl Root {
|
||||
)]);
|
||||
module = Module { imports: HashMap::new(), members }
|
||||
}
|
||||
let root = (this.root.merge(&module, this.ctx.clone(), &mut consts).await)
|
||||
let root = (this.root.merge(&module, this.ctx.clone(), &consts).await)
|
||||
.expect("Merge conflict between parsed and existing module");
|
||||
let new = Root(Rc::new(RwLock::new(RootData { root, consts, ctx: this.ctx.clone() })));
|
||||
*this.ctx.root.write().await = new.downgrade();
|
||||
@@ -93,7 +96,7 @@ impl Root {
|
||||
new
|
||||
}
|
||||
pub async fn get_const_value(&self, name: Sym, pos: Pos) -> OrcRes<Expr> {
|
||||
let this = &mut *self.0.write().await;
|
||||
let this = &*self.0.read().await;
|
||||
// shortcut for previously visited
|
||||
if let Some(val) = this.consts.get(&name) {
|
||||
return Ok(val.clone());
|
||||
@@ -101,7 +104,7 @@ impl Root {
|
||||
// load the node, then check if this "walk" call added it to the map
|
||||
let ctx = this.ctx.clone();
|
||||
let module =
|
||||
walk(&this.root, false, name.iter().cloned(), &mut (ctx.clone(), &mut this.consts)).await;
|
||||
walk(&this.root, false, name.iter().cloned(), &mut (ctx.clone(), &this.consts)).await;
|
||||
if let Some(val) = this.consts.get(&name) {
|
||||
return Ok(val.clone());
|
||||
}
|
||||
@@ -140,14 +143,14 @@ impl Default for WeakRoot {
|
||||
|
||||
pub struct TreeFromApiCtx<'a> {
|
||||
pub sys: &'a System,
|
||||
pub consts: &'a mut HashMap<Sym, Expr>,
|
||||
pub consts: &'a MemoMap<Sym, Expr>,
|
||||
pub path: Tok<Vec<Tok<String>>>,
|
||||
}
|
||||
impl<'a> TreeFromApiCtx<'a> {
|
||||
#[must_use]
|
||||
pub async fn push<'c>(&'c mut self, name: Tok<String>) -> TreeFromApiCtx<'c> {
|
||||
pub async fn push<'c>(&'c self, name: Tok<String>) -> TreeFromApiCtx<'c> {
|
||||
let path = self.sys.ctx().i.i(&self.path.iter().cloned().chain([name]).collect_vec()).await;
|
||||
TreeFromApiCtx { path, consts: &mut *self.consts, sys: self.sys }
|
||||
TreeFromApiCtx { path, consts: self.consts, sys: self.sys }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +211,7 @@ impl Module {
|
||||
Ok(abs_path) => {
|
||||
let names_res = match abs_path.strip_prefix(&ctx.pars_prefix[..]) {
|
||||
None => {
|
||||
let mut tree_ctx = (ctx.ctx.clone(), &mut *ctx.consts);
|
||||
let mut tree_ctx = (ctx.ctx.clone(), ctx.consts);
|
||||
resolv_glob(&path, ctx.root, &abs_path, pos, &ctx.ctx.i, &mut tree_ctx).await
|
||||
},
|
||||
Some(sub_tgt) => {
|
||||
@@ -322,7 +325,7 @@ impl Module {
|
||||
&self,
|
||||
other: &Module,
|
||||
ctx: Ctx,
|
||||
consts: &mut HashMap<Sym, Expr>,
|
||||
consts: &MemoMap<Sym, Expr>,
|
||||
) -> Result<Module, MergeErr> {
|
||||
if !self.imports.is_empty() || !other.imports.is_empty() {
|
||||
return Err(MergeErr { path: VPath::new([]), kind: MergeErrKind::Imports });
|
||||
@@ -385,12 +388,12 @@ pub struct FromParsedCtx<'a> {
|
||||
root: &'a Module,
|
||||
rep: &'a Reporter,
|
||||
ctx: &'a Ctx,
|
||||
consts: &'a mut HashMap<Sym, Expr>,
|
||||
consts: &'a MemoMap<Sym, Expr>,
|
||||
deferred_consts: &'a mut HashMap<Sym, (api::SysId, api::ParsedConstId)>,
|
||||
}
|
||||
|
||||
impl Tree for Module {
|
||||
type Ctx<'a> = (Ctx, &'a mut HashMap<Sym, Expr>);
|
||||
type Ctx<'a> = (Ctx, &'a MemoMap<Sym, Expr>);
|
||||
async fn child(
|
||||
&self,
|
||||
key: Tok<String>,
|
||||
@@ -420,7 +423,7 @@ pub struct Member {
|
||||
}
|
||||
impl Member {
|
||||
#[must_use]
|
||||
pub async fn kind<'a>(&'a self, ctx: Ctx, consts: &mut HashMap<Sym, Expr>) -> &'a MemberKind {
|
||||
pub async fn kind<'a>(&'a self, ctx: Ctx, consts: &MemoMap<Sym, Expr>) -> &'a MemberKind {
|
||||
(self.kind.get_or_init(async {
|
||||
let handle = self.lazy.borrow_mut().take().expect("If kind is uninit, lazy must be Some");
|
||||
handle.run(ctx, consts).await
|
||||
@@ -437,7 +440,7 @@ impl MemberKind {
|
||||
#[must_use]
|
||||
async fn from_parsed(parsed: &ParsedMemberKind, path: Sym, ctx: &mut FromParsedCtx<'_>) -> Self {
|
||||
match parsed {
|
||||
ParsedMemberKind::DeferredConst(id, sys) => {
|
||||
ParsedMemberKind::Const(id, sys) => {
|
||||
ctx.deferred_consts.insert(path, (sys.id(), *id));
|
||||
MemberKind::Const
|
||||
},
|
||||
@@ -454,12 +457,13 @@ pub struct LazyMemberHandle {
|
||||
}
|
||||
impl LazyMemberHandle {
|
||||
#[must_use]
|
||||
pub async fn run(self, ctx: Ctx, consts: &mut HashMap<Sym, Expr>) -> MemberKind {
|
||||
pub async fn run(self, ctx: Ctx, consts: &MemoMap<Sym, Expr>) -> MemberKind {
|
||||
let sys = ctx.system_inst(self.sys).await.expect("Missing system for lazy member");
|
||||
match sys.get_tree(self.id).await {
|
||||
api::MemberKind::Const(c) => {
|
||||
let mut pctx = ExprParseCtx { ctx: &ctx, exprs: sys.ext().exprs() };
|
||||
consts.insert(self.path, Expr::from_api(&c, PathSetBuilder::new(), &mut pctx).await);
|
||||
let expr = Expr::from_api(&c, PathSetBuilder::new(), &mut pctx).await;
|
||||
consts.insert(self.path, expr);
|
||||
MemberKind::Const
|
||||
},
|
||||
api::MemberKind::Module(m) => MemberKind::Module(
|
||||
|
||||
Reference in New Issue
Block a user