STL rework

- fixed lots of bugs
- overlay libraries work correctly and reliably
- the STL is an overlay library
- examples updated
This commit is contained in:
2023-06-17 21:12:23 +01:00
parent 5bb8a12fc2
commit aebbf51228
91 changed files with 1444 additions and 1395 deletions

View File

@@ -57,11 +57,7 @@ fn source_to_module(
let imports = data
.iter()
.filter_map(|ent| {
if let FileEntry::Import(impv) = ent {
Some(impv.iter())
} else {
None
}
if let FileEntry::Import(impv) = ent { Some(impv.iter()) } else { None }
})
.flatten()
.cloned()
@@ -182,6 +178,10 @@ fn files_to_module(
i: &Interner,
) -> Rc<Module<Expr, ProjectExt>> {
let lvl = path.len();
debug_assert!(
files.iter().map(|f| f.path.len()).max().unwrap() >= lvl,
"path is longer than any of the considered file paths"
);
let path_v = path.iter().rev_vec_clone();
if files.len() == 1 && files[0].path.len() == lvl {
return source_to_module(
@@ -227,6 +227,7 @@ pub fn build_tree(
prelude: &[FileEntry],
injected: &impl InjectedOperatorsFn,
) -> Result<ProjectTree, Rc<dyn ProjectError>> {
assert!(!files.is_empty(), "A tree requires at least one module");
let ops_cache = collect_ops::mk_cache(&files, i, injected);
let mut entries = files
.iter()

View File

@@ -1,16 +1,13 @@
use std::println;
use std::rc::Rc;
use hashbrown::HashSet;
use itertools::Itertools;
use trait_set::trait_set;
use crate::interner::{Interner, Sym, Tok};
use crate::pipeline::error::{ModuleNotFound, ProjectError};
use crate::pipeline::source_loader::LoadedSourceTable;
use crate::pipeline::split_name::split_name;
use crate::representations::tree::WalkErrorKind;
use crate::utils::Cache;
use crate::utils::{split_max_prefix, unwrap_or, Cache};
pub type OpsResult = Result<Rc<HashSet<Tok<String>>>, Rc<dyn ProjectError>>;
pub type ExportedOpsCache<'a> = Cache<'a, Sym, OpsResult>;
@@ -33,34 +30,24 @@ pub fn collect_exported_ops(
i: &Interner,
injected: &impl InjectedOperatorsFn,
) -> OpsResult {
if let Some(ops) = injected(path) {
if path == i.i(&[i.i("prelude")][..]) {
println!("%%% Prelude exported ops %%%");
println!("{}", ops.iter().map(|t| i.r(*t)).join(", "));
}
return Ok(ops);
}
let injected = injected(path).unwrap_or_else(|| Rc::new(HashSet::new()));
let is_file = |n: &[Tok<String>]| loaded.contains_key(&i.i(n));
let path_s = &i.r(path)[..];
let name_split = split_name(path_s, &is_file);
let (fpath_v, subpath_v) = if let Some(f) = name_split {
f
} else {
return Ok(Rc::new(
loaded
.keys()
.copied()
.filter_map(|modname| {
let modname_s = i.r(modname);
if path_s.len() == coprefix(path_s.iter(), modname_s.iter()) {
Some(modname_s[path_s.len()])
} else {
None
}
})
.collect::<HashSet<_>>(),
));
};
let name_split = split_max_prefix(path_s, &is_file);
let (fpath_v, subpath_v) = unwrap_or!(name_split; return Ok(Rc::new(
(loaded.keys())
.copied()
.filter_map(|modname| {
let modname_s = i.r(modname);
if path_s.len() == coprefix(path_s.iter(), modname_s.iter()) {
Some(modname_s[path_s.len()])
} else {
None
}
})
.chain(injected.iter().copied())
.collect::<HashSet<_>>(),
)));
let fpath = i.i(fpath_v);
let preparsed = &loaded[&fpath].preparsed;
let module = preparsed.0.walk(subpath_v, false).map_err(|walk_err| {
@@ -70,8 +57,7 @@ pub fn collect_exported_ops(
},
WalkErrorKind::Missing => ModuleNotFound {
file: i.extern_vec(fpath),
subpath: subpath_v
.iter()
subpath: (subpath_v.iter())
.take(walk_err.pos)
.map(|t| i.r(*t))
.cloned()
@@ -80,12 +66,11 @@ pub fn collect_exported_ops(
.rc(),
}
})?;
let out: HashSet<_> =
module.items.iter().filter(|(_, v)| v.exported).map(|(k, _)| *k).collect();
if path == i.i(&[i.i("prelude")][..]) {
println!("%%% Prelude exported ops %%%");
println!("{}", out.iter().map(|t| i.r(*t)).join(", "));
}
let out = (module.items.iter())
.filter(|(_, v)| v.exported)
.map(|(k, _)| *k)
.chain(injected.iter().copied())
.collect::<HashSet<_>>();
Ok(Rc::new(out))
}

View File

@@ -1,7 +1,6 @@
use std::rc::Rc;
use hashbrown::HashSet;
use itertools::Itertools;
use super::exported_ops::{ExportedOpsCache, OpsResult};
use crate::interner::{Interner, Tok};
@@ -34,13 +33,11 @@ pub fn collect_ops_for(
) -> OpsResult {
let tree = &loaded[&i.i(file)].preparsed.0;
let mut ret = HashSet::new();
println!("collecting ops for {}", i.extern_all(file).join("::"));
tree_all_ops(tree.as_ref(), &mut ret);
tree.visit_all_imports(&mut |modpath, _module, import| {
if let Some(n) = import.name {
ret.insert(n);
} else {
println!("\tglob import from {}", i.extern_vec(import.path).join("::"));
let path = import_abs_path(file, modpath, &i.r(import.path)[..], i)
.expect("This error should have been caught during loading");
ret.extend(ops_cache.find(&i.i(&path))?.iter().copied());
@@ -48,9 +45,5 @@ pub fn collect_ops_for(
Ok::<_, Rc<dyn ProjectError>>(())
})?;
ret.drain_filter(|t| !is_op(i.r(*t)));
if file == &[i.i("map")][..] {
println!(" %%% ops in map %%% ");
println!("{}", ret.iter().map(|t| i.r(*t)).join(", "))
}
Ok(Rc::new(ret))
}

View File

@@ -41,6 +41,7 @@ impl Add for ProjectExt {
pub type ProjectModule = Module<Expr, ProjectExt>;
/// Module corresponding to the root of a project
#[derive(Debug, Clone)]
pub struct ProjectTree(pub Rc<ProjectModule>);
fn collect_rules_rec(bag: &mut Vec<Rule>, module: &ProjectModule) {