temp commit

This commit is contained in:
2025-07-12 00:46:10 +02:00
parent 1868f1a506
commit fe89188c4b
60 changed files with 1536 additions and 709 deletions

View File

@@ -1,16 +1,9 @@
use std::collections::VecDeque;
use futures::FutureExt;
use hashbrown::{HashMap, HashSet};
use itertools::{Either, Itertools};
use hashbrown::HashSet;
use itertools::Itertools;
use orchid_base::error::{OrcErr, OrcRes, Reporter, mk_err, mk_errv};
use orchid_base::interner::{Interner, Tok};
use orchid_base::location::Pos;
use orchid_base::name::{NameLike, Sym, VName};
use substack::Substack;
use crate::expr::Expr;
use crate::parsed::{ItemKind, ParsedMemberKind, ParsedModule};
use orchid_base::name::VName;
/// Errors produced by absolute_path
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
@@ -48,29 +41,24 @@ impl AbsPathError {
///
/// if the relative path contains as many or more `super` segments than the
/// length of the absolute path.
pub fn absolute_path(
pub async fn absolute_path(
mut cwd: &[Tok<String>],
mut rel: &[Tok<String>],
i: &Interner,
) -> Result<VName, AbsPathError> {
let mut relative = false;
if rel.first().map(|t| t.as_str()) == Some("self") {
relative = true;
rel = rel.split_first().expect("checked above").1;
let i_self = i.i("self").await;
let i_super = i.i("super").await;
let relative = rel.first().is_some_and(|s| *s != i_self && *s != i_super);
if let Some((_, tail)) = rel.split_first().filter(|(h, _)| **h != i_self) {
rel = tail;
} else {
while rel.first().map(|t| t.as_str()) == Some("super") {
match cwd.split_last() {
Some((_, torso)) => cwd = torso,
None => return Err(AbsPathError::TooManySupers),
};
rel = rel.split_first().expect("checked above").1;
relative = true;
while let Some((_, tail)) = rel.split_first().filter(|(h, _)| **h == i_super) {
cwd = cwd.split_last().ok_or(AbsPathError::TooManySupers)?.1;
rel = tail;
}
}
match relative {
true => VName::new(cwd.iter().chain(rel).cloned()),
false => VName::new(rel.to_vec()),
}
.map_err(|_| AbsPathError::RootPath)
if relative { VName::new(cwd.iter().chain(rel).cloned()) } else { VName::new(rel.to_vec()) }
.map_err(|_| AbsPathError::RootPath)
}
pub struct DealiasCtx<'a> {
@@ -84,8 +72,7 @@ pub async fn resolv_glob<Mod: Tree>(
abs_path: &[Tok<String>],
pos: Pos,
i: &Interner,
rep: &Reporter,
ctx: &mut Mod::Ctx,
ctx: &mut Mod::Ctx<'_>,
) -> OrcRes<HashSet<Tok<String>>> {
let coprefix_len = cwd.iter().zip(abs_path).take_while(|(a, b)| a == b).count();
let (co_prefix, diff_path) = abs_path.split_at(abs_path.len().min(coprefix_len + 1));
@@ -96,35 +83,34 @@ pub async fn resolv_glob<Mod: Tree>(
Err(e) => {
let path = abs_path[..=coprefix_len + e.pos].iter().join("::");
let (tk, msg) = match e.kind {
ChildErrorKind::Constant =>
(i.i("Invalid import path").await, format!("{path} is a const")),
ChildErrorKind::Missing => (i.i("Invalid import path").await, format!("{path} not found")),
ChildErrorKind::Private => (i.i("Import inaccessible").await, format!("{path} is private")),
ChildErrorKind::Constant => ("Invalid import path", format!("{path} is a const")),
ChildErrorKind::Missing => ("Invalid import path", format!("{path} not found")),
ChildErrorKind::Private => ("Import inaccessible", format!("{path} is private")),
};
return Err(mk_errv(tk, msg, [pos.into()]));
return Err(mk_errv(i.i(tk).await, msg, [pos]));
},
};
Ok(target_module.children(coprefix_len < abs_path.len()))
}
pub enum ChildResult<'a, T: Tree + ?Sized> {
Value(&'a T),
Err(ChildErrorKind),
Alias(&'a [Tok<String>]),
}
pub type ChildResult<'a, T> = Result<&'a T, ChildErrorKind>;
pub trait Tree {
type Ctx;
type Ctx<'a>;
#[must_use]
fn children(&self, public_only: bool) -> HashSet<Tok<String>>;
#[must_use]
fn child(
&self,
key: Tok<String>,
public_only: bool,
ctx: &mut Self::Ctx,
ctx: &mut Self::Ctx<'_>,
) -> impl Future<Output = ChildResult<'_, Self>>;
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum ChildErrorKind {
Missing,
/// Only thrown if public_only is true
Private,
Constant,
}
@@ -144,42 +130,17 @@ pub struct ChildError {
//
// caveat: we need to check EVERY IMPORT to ensure that all
// errors are raised
async fn walk_no_access_chk<'a, T: Tree>(
root: &'a T,
cur: &mut &'a T,
path: impl IntoIterator<Item = Tok<String>, IntoIter: DoubleEndedIterator>,
ctx: &mut T::Ctx,
) -> Result<(), ChildErrorKind> {
// this VecDeque is used like a stack to leverage its Extend implementation.
let mut path: VecDeque<Tok<String>> = path.into_iter().rev().collect();
while let Some(step) = path.pop_back() {
match cur.child(step, false, ctx).await {
ChildResult::Alias(target) => {
path.extend(target.iter().cloned().rev());
*cur = root;
},
ChildResult::Err(e) => return Err(e),
ChildResult::Value(v) => *cur = v,
}
}
Ok(())
}
async fn walk<'a, T: Tree>(
pub async fn walk<'a, T: Tree>(
root: &'a T,
public_only: bool,
path: impl IntoIterator<Item = Tok<String>>,
ctx: &mut T::Ctx,
ctx: &mut T::Ctx<'_>,
) -> Result<&'a T, ChildError> {
let mut cur = root;
for (i, item) in path.into_iter().enumerate() {
match cur.child(item, public_only, ctx).await {
ChildResult::Value(v) => cur = v,
ChildResult::Ok(v) => cur = v,
ChildResult::Err(kind) => return Err(ChildError { pos: i, kind }),
ChildResult::Alias(path) => (walk_no_access_chk(root, &mut cur, path.iter().cloned(), ctx)
.await)
.map_err(|kind| ChildError { kind, pos: i })?,
}
}
Ok(cur)