Import and export improved

- Import paths are now vname and not sym
- Imports and exports accept multiple space-delimited operators in []

as a result, we can now reliably import and export the operator *

- error reporting ergonomics
This commit is contained in:
2023-08-18 21:10:29 +01:00
parent 3fdabc29da
commit 9186bce956
33 changed files with 269 additions and 228 deletions

View File

@@ -6,13 +6,12 @@ use std::{fs, io};
use hashbrown::{HashMap, HashSet};
use rust_embed::RustEmbed;
use crate::error::{ErrorPosition, ProjectError, ProjectResult};
use crate::error::{ProjectError, ProjectResult};
#[allow(unused)] // for doc
use crate::facade::System;
use crate::interner::Interner;
use crate::utils::iter::box_once;
use crate::utils::{BoxedIter, Cache};
use crate::{Stok, VName};
use crate::utils::Cache;
use crate::{Location, Stok, VName};
/// All the data available about a failed source load call
#[derive(Debug)]
@@ -25,8 +24,8 @@ impl ProjectError for FileLoadingError {
fn description(&self) -> &str {
"Neither a file nor a directory could be read from the requested path"
}
fn positions(&self, _i: &Interner) -> BoxedIter<ErrorPosition> {
box_once(ErrorPosition::just_file(self.path.clone()))
fn one_position(&self, _i: &Interner) -> crate::Location {
Location::File(Rc::new(self.path.clone()))
}
fn message(&self, _i: &Interner) -> String {
format!("File: {}\nDirectory: {}", self.file, self.dir)

View File

@@ -14,7 +14,10 @@ fn assert_visible(
target: &[Tok<String>], // may point to a symbol or module of any kind
project: &ProjectTree<VName>,
) -> ProjectResult<()> {
let (tgt_item, tgt_path) = unwrap_or!(target.split_last(); return Ok(()));
let (tgt_item, tgt_path) = unwrap_or! {
target.split_last();
return Ok(())
};
let shared_len =
source.iter().zip(tgt_path.iter()).take_while(|(a, b)| a == b).count();
let vis_ignored_len = usize::min(tgt_path.len(), shared_len + 1);

View File

@@ -75,7 +75,7 @@ fn source_to_module(
.collect::<Vec<_>>();
let imports_from = (imports.iter())
.map(|imp| -> ProjectResult<_> {
let mut imp_path_v = i.r(imp.path).clone();
let mut imp_path_v = imp.path.clone();
imp_path_v.push(imp.name.expect("glob imports had just been resolved"));
let mut abs_path = absolute_path(&path_v, &imp_path_v, i)
.expect("should have failed in preparsing");

View File

@@ -7,7 +7,7 @@ use crate::error::{NotFound, ProjectError, ProjectResult};
use crate::interner::{Interner, Tok};
use crate::pipeline::source_loader::LoadedSourceTable;
use crate::representations::tree::WalkErrorKind;
use crate::utils::{split_max_prefix, unwrap_or, Cache};
use crate::utils::{split_max_prefix, Cache};
use crate::Sym;
pub type OpsResult = ProjectResult<Rc<HashSet<Tok<String>>>>;
@@ -33,40 +33,43 @@ pub fn collect_exported_ops(
) -> OpsResult {
let injected = injected(path).unwrap_or_else(|| Rc::new(HashSet::new()));
let path_s = &i.r(path)[..];
let name_split = split_max_prefix(path_s, &|n| loaded.contains_key(n));
let (fpath, subpath) = unwrap_or!(name_split; return Ok(Rc::new(
(loaded.keys())
.filter_map(|modname| {
if path_s.len() == coprefix(path_s.iter(), modname.iter()) {
Some(modname[path_s.len()])
} else {
None
}
})
.chain(injected.iter().copied())
.collect::<HashSet<_>>(),
)));
let preparsed = &loaded[fpath].preparsed;
let module =
preparsed.0.walk_ref(subpath, false).map_err(
|walk_err| match walk_err.kind {
WalkErrorKind::Private => {
unreachable!("visibility is not being checked here")
match split_max_prefix(path_s, &|n| loaded.contains_key(n)) {
None => {
let ops = (loaded.keys())
.filter_map(|modname| {
if path_s.len() == coprefix(path_s.iter(), modname.iter()) {
Some(modname[path_s.len()])
} else {
None
}
})
.chain(injected.iter().copied())
.collect::<HashSet<_>>();
Ok(Rc::new(ops))
},
Some((fpath, subpath)) => {
let preparsed = &loaded[fpath].preparsed;
let module = preparsed.0.walk_ref(subpath, false).map_err(
|walk_err| match walk_err.kind {
WalkErrorKind::Private => {
unreachable!("visibility is not being checked here")
},
WalkErrorKind::Missing => NotFound {
source: None,
file: fpath.to_vec(),
subpath: subpath[..walk_err.pos].to_vec(),
}
.rc(),
},
WalkErrorKind::Missing => NotFound {
source: None,
file: fpath.to_vec(),
subpath: subpath[..walk_err.pos].to_vec(),
}
.rc(),
},
)?;
let out = (module.items.iter())
.filter(|(_, v)| v.exported)
.map(|(k, _)| *k)
.chain(injected.iter().copied())
.collect::<HashSet<_>>();
Ok(Rc::new(out))
)?;
let out = (module.items.iter())
.filter(|(_, v)| v.exported)
.map(|(k, _)| *k)
.chain(injected.iter().copied())
.collect::<HashSet<_>>();
Ok(Rc::new(out))
},
}
}
pub fn mk_cache<'a>(

View File

@@ -44,7 +44,7 @@ pub fn collect_ops_for(
ret.insert(n);
} else {
let path = i.expect(
import_abs_path(file, modpath, &i.r(import.path)[..], i),
import_abs_path(file, modpath, &import.path, i),
"This error should have been caught during loading",
);
ret.extend(ops_cache.find(&i.i(&path))?.iter().copied());

View File

@@ -59,7 +59,7 @@ fn entv_rec(
.flat_map(|import| {
if let Import { name: None, path } = import {
let p = i.expect(
import_abs_path(mod_path, mod_stack, &i.r(path)[..], i),
import_abs_path(mod_path, mod_stack, &path, i),
"Should have emerged in preparsing",
);
let names = i.expect(
@@ -67,7 +67,7 @@ fn entv_rec(
"Should have emerged in second parsing",
);
let imports = (names.iter())
.map(move |&n| Import { name: Some(n), path })
.map(|&n| Import { name: Some(n), path: path.clone() })
.collect::<Vec<_>>();
Box::new(imports.into_iter()) as BoxedIter<Import>
} else {

View File

@@ -56,7 +56,7 @@ fn load_abs_path_rec(
// recurse on all imported modules
preparsed.0.visit_all_imports(&mut |modpath, _module, import| {
let abs_pathv =
import_abs_path(filename, modpath, &import.nonglob_path(i), i)?;
import_abs_path(filename, modpath, &import.nonglob_path(), i)?;
if abs_path.starts_with(&abs_pathv) {
return Ok(());
}