forked from Orchid/orchid
Macro system done in theory
too afraid to begin debugging, resting for a moment
This commit is contained in:
@@ -58,10 +58,10 @@ impl AtomHand {
|
||||
};
|
||||
if let Some(id) = drop {
|
||||
let mut owned_g = ctx.owned_atoms.write().await;
|
||||
if let Some(data) = owned_g.get(&id) {
|
||||
if let Some(atom) = data.upgrade() {
|
||||
return atom;
|
||||
}
|
||||
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());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use hashbrown::HashSet;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::error::{OrcErr, OrcRes, Reporter, mk_err, mk_errv};
|
||||
use orchid_base::error::{OrcErrv, OrcRes, Reporter, mk_errv};
|
||||
use orchid_base::interner::{Interner, Tok};
|
||||
use orchid_base::location::Pos;
|
||||
use orchid_base::name::VName;
|
||||
@@ -16,7 +16,7 @@ pub enum AbsPathError {
|
||||
RootPath,
|
||||
}
|
||||
impl AbsPathError {
|
||||
pub async fn err_obj(self, i: &Interner, pos: Pos, path: &str) -> OrcErr {
|
||||
pub async fn err_obj(self, i: &Interner, pos: Pos, path: &str) -> OrcErrv {
|
||||
let (descr, msg) = match self {
|
||||
AbsPathError::RootPath => (
|
||||
i.i("Path ends on root module").await,
|
||||
@@ -30,7 +30,7 @@ impl AbsPathError {
|
||||
format!("{path} is leading outside the root."),
|
||||
),
|
||||
};
|
||||
mk_err(descr, msg, [pos.into()])
|
||||
mk_errv(descr, msg, [pos])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -206,12 +206,16 @@ impl Extension {
|
||||
let sys = weak_sys.upgrade().expect("ResolveNames after sys drop");
|
||||
sys.name_resolver(*constid).await
|
||||
};
|
||||
let mut responses = vec![const { None }; names.len()];
|
||||
for (i, name) in names.iter().enumerate() {
|
||||
if let Some(abs) = resolver(&ctx.i.ex(*name).await[..]).await {
|
||||
responses[i] = Some(abs.to_sym(&ctx.i).await.to_api())
|
||||
let responses = stream! {
|
||||
for name in names {
|
||||
yield match resolver(&ctx.i.ex(*name).await[..]).await {
|
||||
Ok(abs) => Ok(abs.to_sym(&ctx.i).await.to_api()),
|
||||
Err(e) => Err(e.to_api()),
|
||||
}
|
||||
}
|
||||
}
|
||||
.collect()
|
||||
.await;
|
||||
hand.handle(rn, &responses).await
|
||||
},
|
||||
api::ExtHostReq::ExtAtomPrint(ref eap @ api::ExtAtomPrint(ref atom)) => {
|
||||
|
||||
@@ -10,11 +10,12 @@ use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use memo_map::MemoMap;
|
||||
use orchid_base::char_filter::char_filter_match;
|
||||
use orchid_base::error::{OrcErrv, OrcRes};
|
||||
use orchid_base::error::{OrcErrv, 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};
|
||||
use orchid_base::name::{NameLike, Sym, VName, VPath};
|
||||
use orchid_base::parse::Comment;
|
||||
use orchid_base::reqnot::{ReqNot, Requester};
|
||||
use orchid_base::tree::ttv_from_api;
|
||||
@@ -23,7 +24,7 @@ use substack::{Stackframe, Substack};
|
||||
|
||||
use crate::api;
|
||||
use crate::ctx::Ctx;
|
||||
use crate::dealias::{absolute_path, walk};
|
||||
use crate::dealias::walk;
|
||||
use crate::expr::{ExprParseCtx, ExprWillPanic};
|
||||
use crate::expr_store::ExprStore;
|
||||
use crate::extension::{Extension, WeakExtension};
|
||||
@@ -202,16 +203,39 @@ impl System {
|
||||
pub(crate) async fn name_resolver(
|
||||
&self,
|
||||
orig: api::ParsedConstId,
|
||||
) -> impl AsyncFnMut(&[Tok<String>]) -> Option<VName> + use<> {
|
||||
) -> impl AsyncFnMut(&[Tok<String>]) -> OrcRes<VName> + use<> {
|
||||
let root = self.0.ctx.root.read().await.upgrade().expect("find_names when root not in context");
|
||||
let orig = self.0.const_paths.get(&orig).expect("origin for find_names invalid").clone();
|
||||
let ctx = self.0.ctx.clone();
|
||||
async move |rel| {
|
||||
let cwd = orig.split_last_seg().1;
|
||||
let abs = absolute_path(cwd, rel, &ctx.i).await.ok()?;
|
||||
let root_data = &mut *root.0.write().await;
|
||||
let walk_ctx = &mut (ctx.clone(), &mut root_data.consts);
|
||||
walk(&root_data.root, false, abs.iter(), walk_ctx).await.is_ok().then_some(abs)
|
||||
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");
|
||||
if cmod.members.get(selector).is_some() {
|
||||
return Ok(VName::new(cwd.iter().chain(rel).cloned()).unwrap());
|
||||
}
|
||||
match cmod.imports.get(selector) {
|
||||
Some(Ok(dest)) => return Ok(dest.target.to_vname().suffix(tail.iter().cloned())),
|
||||
Some(Err(dests)) =>
|
||||
return Err(mk_errv_floating(
|
||||
ctx.i.i("Ambiguous name").await,
|
||||
format!(
|
||||
"{selector} could refer to {}",
|
||||
dests.iter().map(|ri| &ri.target).display("or")
|
||||
),
|
||||
)),
|
||||
None => (),
|
||||
}
|
||||
if tail.is_empty() {
|
||||
return Ok(VPath::new(cwd.iter().cloned()).name_with_suffix(selector.clone()));
|
||||
}
|
||||
Err(mk_errv_floating(
|
||||
ctx.i.i("Invalid name").await,
|
||||
format!("{selector} doesn't refer to a module"),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//! once
|
||||
use std::cell::RefCell;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::slice;
|
||||
|
||||
use async_once_cell::OnceCell;
|
||||
use async_std::sync::RwLock;
|
||||
@@ -10,7 +11,7 @@ use hashbrown::HashMap;
|
||||
use hashbrown::hash_map::Entry;
|
||||
use itertools::Itertools;
|
||||
use orchid_base::clone;
|
||||
use orchid_base::error::{OrcRes, Reporter, mk_err, mk_errv};
|
||||
use orchid_base::error::{OrcRes, Reporter, mk_errv};
|
||||
use orchid_base::interner::Tok;
|
||||
use orchid_base::location::{CodeGenInfo, Pos};
|
||||
use orchid_base::name::{NameLike, Sym, VPath};
|
||||
@@ -152,8 +153,8 @@ impl<'a> TreeFromApiCtx<'a> {
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ResolvedImport {
|
||||
target: Sym,
|
||||
pos: Pos,
|
||||
pub target: Sym,
|
||||
pub pos: Pos,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@@ -258,18 +259,16 @@ impl Module {
|
||||
match abs_path_res {
|
||||
Err(e) => ctx.rep.report(e.err_obj(&ctx.ctx.i, sr.pos(), &import.to_string()).await),
|
||||
Ok(abs_path) => {
|
||||
imports.insert(
|
||||
key,
|
||||
Ok(ResolvedImport { target: abs_path.to_sym(&ctx.ctx.i).await, pos: sr.pos() }),
|
||||
);
|
||||
let target = abs_path.to_sym(&ctx.ctx.i).await;
|
||||
imports.insert(key, Ok(ResolvedImport { target, pos: sr.pos() }));
|
||||
},
|
||||
}
|
||||
} else {
|
||||
for item in values {
|
||||
ctx.rep.report(mk_err(
|
||||
ctx.rep.report(mk_errv(
|
||||
conflicting_imports_msg.clone(),
|
||||
format!("{key} is imported multiple times from different modules"),
|
||||
[item.sr.pos().into()],
|
||||
[item.sr.pos()],
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -294,11 +293,12 @@ impl Module {
|
||||
let self_referential_msg = ctx.ctx.i.i("Self-referential import").await;
|
||||
for (key, value) in imports.iter() {
|
||||
let Ok(import) = value else { continue };
|
||||
if import.target.strip_prefix(&path[..]).is_some_and(|t| t.starts_with(&[key.clone()])) {
|
||||
ctx.rep.report(mk_err(
|
||||
if import.target.strip_prefix(&path[..]).is_some_and(|t| t.starts_with(slice::from_ref(key)))
|
||||
{
|
||||
ctx.rep.report(mk_errv(
|
||||
self_referential_msg.clone(),
|
||||
format!("import {} points to itself or a path within itself", &import.target),
|
||||
[import.pos.clone().into()],
|
||||
[import.pos.clone()],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user