September-october commit
- manual parser - stl refinements - all language constructs are now Send
This commit is contained in:
@@ -8,7 +8,7 @@ use crate::representations::project::{
|
||||
ItemKind, ProjectExt, ProjectItem, ProjectMod,
|
||||
};
|
||||
use crate::tree::{ModEntry, ModMember, Module};
|
||||
use crate::utils::pure_push::pushed;
|
||||
use crate::utils::pure_seq::pushed;
|
||||
use crate::{Interner, ProjectTree, Tok, VName};
|
||||
|
||||
#[must_use]
|
||||
@@ -74,7 +74,6 @@ fn resolve_aliases_rec(
|
||||
ModMember::Sub(module) =>
|
||||
ModMember::Sub(resolve_aliases_rec(root, module, updated, false)),
|
||||
ModMember::Item(item) => ModMember::Item(ProjectItem {
|
||||
is_op: item.is_op,
|
||||
kind: match &item.kind {
|
||||
ItemKind::Const(value) => ItemKind::Const(process_expr(value)),
|
||||
other => other.clone(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Source loader callback definition and builtin implementations
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::{fs, io};
|
||||
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
@@ -25,7 +25,7 @@ impl ProjectError for FileLoadingError {
|
||||
"Neither a file nor a directory could be read from the requested path"
|
||||
}
|
||||
fn one_position(&self) -> crate::Location {
|
||||
Location::File(Rc::new(self.path.clone()))
|
||||
Location::File(Arc::new(self.path.clone()))
|
||||
}
|
||||
fn message(&self) -> String {
|
||||
format!("File: {}\nDirectory: {}", self.file, self.dir)
|
||||
@@ -37,10 +37,10 @@ impl ProjectError for FileLoadingError {
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Loaded {
|
||||
/// Conceptually equivalent to a sourcefile
|
||||
Code(Rc<String>),
|
||||
Code(Arc<String>),
|
||||
/// Conceptually equivalent to the list of *.orc files in a folder, without
|
||||
/// the extension
|
||||
Collection(Rc<Vec<String>>),
|
||||
Collection(Arc<Vec<String>>),
|
||||
}
|
||||
impl Loaded {
|
||||
/// Is the loaded item source code (not a collection)?
|
||||
@@ -56,7 +56,7 @@ pub fn load_file(root: &Path, path: &[Tok<String>]) -> IOResult {
|
||||
let full_path = path.iter().fold(root.to_owned(), |p, t| p.join(t.as_str()));
|
||||
let file_path = full_path.with_extension("orc");
|
||||
let file_error = match fs::read_to_string(file_path) {
|
||||
Ok(string) => return Ok(Loaded::Code(Rc::new(string))),
|
||||
Ok(string) => return Ok(Loaded::Code(Arc::new(string))),
|
||||
Err(err) => err,
|
||||
};
|
||||
let dir = match fs::read_dir(&full_path) {
|
||||
@@ -83,7 +83,7 @@ pub fn load_file(root: &Path, path: &[Tok<String>]) -> IOResult {
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Ok(Loaded::Collection(Rc::new(names)))
|
||||
Ok(Loaded::Collection(Arc::new(names)))
|
||||
}
|
||||
|
||||
/// Generates a cached file loader for a directory
|
||||
@@ -102,7 +102,7 @@ pub fn load_embed<T: 'static + RustEmbed>(path: &str, ext: &str) -> IOResult {
|
||||
if let Some(file) = T::get(&file_path) {
|
||||
let s =
|
||||
String::from_utf8(file.data.to_vec()).expect("Embed must be valid UTF-8");
|
||||
Ok(Loaded::Code(Rc::new(s)))
|
||||
Ok(Loaded::Code(Arc::new(s)))
|
||||
} else {
|
||||
let entries = T::iter()
|
||||
.map(|c| c.to_string())
|
||||
@@ -121,7 +121,7 @@ pub fn load_embed<T: 'static + RustEmbed>(path: &str, ext: &str) -> IOResult {
|
||||
})
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
Ok(Loaded::Collection(Rc::new(entries)))
|
||||
Ok(Loaded::Collection(Arc::new(entries)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,9 +165,9 @@ pub fn embed_to_map<T: 'static + RustEmbed>(
|
||||
}
|
||||
}
|
||||
(files.into_iter())
|
||||
.map(|(k, s)| (k, Loaded::Code(Rc::new(s))))
|
||||
.map(|(k, s)| (k, Loaded::Code(Arc::new(s))))
|
||||
.chain((dirs.into_iter()).map(|(k, entv)| {
|
||||
(k, Loaded::Collection(Rc::new(entv.into_iter().collect())))
|
||||
(k, Loaded::Collection(Arc::new(entv.into_iter().collect())))
|
||||
}))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ mod import_abs_path;
|
||||
mod parse_layer;
|
||||
mod project_tree;
|
||||
mod source_loader;
|
||||
// mod tree_loader;
|
||||
|
||||
pub use parse_layer::parse_layer;
|
||||
|
||||
@@ -3,6 +3,7 @@ use super::file_loader::IOResult;
|
||||
use super::{project_tree, source_loader};
|
||||
use crate::error::ProjectResult;
|
||||
use crate::interner::{Interner, Tok};
|
||||
use crate::parse::{LexerPlugin, LineParser};
|
||||
use crate::representations::sourcefile::FileEntry;
|
||||
use crate::representations::VName;
|
||||
use crate::utils::never;
|
||||
@@ -21,10 +22,14 @@ pub fn parse_layer<'a>(
|
||||
loader: &impl Fn(&[Tok<String>]) -> IOResult,
|
||||
environment: &'a ProjectTree<VName>,
|
||||
prelude: &[FileEntry],
|
||||
lexer_plugins: &[&dyn LexerPlugin],
|
||||
line_parsers: &[&dyn LineParser],
|
||||
i: &Interner,
|
||||
) -> ProjectResult<ProjectTree<VName>> {
|
||||
let sl_ctx =
|
||||
source_loader::Context { prelude, i, lexer_plugins, line_parsers };
|
||||
let (preparsed, source) =
|
||||
source_loader::load_source(targets, prelude, i, loader, &|path| {
|
||||
source_loader::load_source(targets, sl_ctx, loader, &|path| {
|
||||
environment.0.walk_ref(&[], path, false).is_ok()
|
||||
})?;
|
||||
let tree =
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::sourcefile::{
|
||||
};
|
||||
use crate::tree::{ModEntry, ModMember, Module};
|
||||
use crate::utils::get_or::get_or_default;
|
||||
use crate::utils::pure_push::pushed_ref;
|
||||
use crate::utils::pure_seq::pushed_ref;
|
||||
use crate::{Tok, VName};
|
||||
|
||||
#[must_use = "A submodule may not be integrated into the tree"]
|
||||
@@ -28,7 +28,7 @@ pub struct TreeReport {
|
||||
pub fn build_tree(
|
||||
path: &VName,
|
||||
source: Vec<FileEntry>,
|
||||
Module { entries, extra }: PreMod,
|
||||
Module { entries, .. }: PreMod,
|
||||
imports: ImpMod,
|
||||
prelude: &[FileEntry],
|
||||
) -> ProjectResult<TreeReport> {
|
||||
@@ -56,20 +56,11 @@ pub fn build_tree(
|
||||
MemberKind::Constant(Constant { name, value }) => {
|
||||
consts.insert(name, value /* .prefix(path, &|_| false) */);
|
||||
},
|
||||
MemberKind::Operators(_) => (),
|
||||
MemberKind::Rule(rule) => rule_fragments.push(rule),
|
||||
},
|
||||
}
|
||||
}
|
||||
let mod_details = extra.details().expect("Directories handled elsewhere");
|
||||
let rules = (mod_details.patterns.iter())
|
||||
.zip(rule_fragments.into_iter())
|
||||
.map(|(p, Rule { prio, template: t, .. })| {
|
||||
// let p = p.iter().map(|e| e.prefix(path, &|_| false)).collect();
|
||||
// let t = t.into_iter().map(|e| e.prefix(path, &|_| false)).collect();
|
||||
Rule { pattern: p.clone(), prio, template: t }
|
||||
})
|
||||
.collect();
|
||||
let rules = rule_fragments;
|
||||
let (pre_subs, pre_items) = (entries.into_iter())
|
||||
.partition_map::<HashMap<_, _>, HashMap<_, _>, _, _, _>(
|
||||
|(k, ModEntry { exported, member })| match member {
|
||||
@@ -98,7 +89,7 @@ pub fn build_tree(
|
||||
Ok((k, ModEntry { exported, member }))
|
||||
})
|
||||
.chain((pre_items.into_iter()).map(
|
||||
|(k, (exported, PreItem { has_value, is_op, location }))| {
|
||||
|(k, (exported, PreItem { has_value, location }))| {
|
||||
let item = match imports_from.get(&k) {
|
||||
Some(_) if has_value => {
|
||||
// Local value cannot be assigned to imported key
|
||||
@@ -112,12 +103,10 @@ pub fn build_tree(
|
||||
},
|
||||
None => {
|
||||
let k = consts.remove(&k).map_or(ItemKind::None, ItemKind::Const);
|
||||
ProjectItem { is_op, kind: k }
|
||||
},
|
||||
Some(report) => ProjectItem {
|
||||
is_op: is_op | report.is_op,
|
||||
kind: ItemKind::Alias(report.source.clone()),
|
||||
ProjectItem { kind: k }
|
||||
},
|
||||
Some(report) =>
|
||||
ProjectItem { kind: ItemKind::Alias(report.source.clone()) },
|
||||
};
|
||||
Ok((k, ModEntry { exported, member: ModMember::Item(item) }))
|
||||
},
|
||||
@@ -129,7 +118,6 @@ pub fn build_tree(
|
||||
exported: false,
|
||||
member: ModMember::Item(ProjectItem {
|
||||
kind: ItemKind::Alias(from.source.clone()),
|
||||
is_op: from.is_op,
|
||||
}),
|
||||
})
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::representations::project::ImpReport;
|
||||
use crate::sourcefile::{absolute_path, Import};
|
||||
use crate::tree::{ErrKind, ModEntry, ModMember, Module, WalkError};
|
||||
use crate::utils::boxed_iter::{box_chain, box_once};
|
||||
use crate::utils::pure_push::pushed_ref;
|
||||
use crate::utils::pure_seq::pushed_ref;
|
||||
use crate::utils::{unwrap_or, BoxedIter};
|
||||
use crate::{Interner, ProjectTree, Tok, VName};
|
||||
|
||||
@@ -65,17 +65,13 @@ pub fn assert_visible_overlay<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn process_donor_module<'a, TItem: Clone>(
|
||||
module: &'a Module<TItem, impl Clone>,
|
||||
pub fn process_donor_module<TItem: Clone>(
|
||||
module: &Module<TItem, impl Clone>,
|
||||
abs_path: Rc<VName>,
|
||||
is_op: impl Fn(&TItem) -> bool + 'a,
|
||||
) -> impl Iterator<Item = (Tok<String>, VName, bool)> + 'a {
|
||||
(module.entries.iter()).filter(|(_, ent)| ent.exported).map(
|
||||
move |(n, ent)| {
|
||||
let is_op = ent.item().map_or(false, &is_op);
|
||||
(n.clone(), pushed_ref(abs_path.as_ref(), n.clone()), is_op)
|
||||
},
|
||||
)
|
||||
) -> impl Iterator<Item = (Tok<String>, VName)> + '_ {
|
||||
(module.entries.iter())
|
||||
.filter(|(_, ent)| ent.exported)
|
||||
.map(move |(n, _)| (n.clone(), pushed_ref(abs_path.as_ref(), n.clone())))
|
||||
}
|
||||
|
||||
pub fn import_tree(
|
||||
@@ -99,14 +95,7 @@ pub fn import_tree(
|
||||
// println!("Old root: {:#?}", &prev_root.0);
|
||||
panic!("{}", e.at(location))
|
||||
})?;
|
||||
let is_op = (root.0.walk1_ref(&[], &abs_path, false))
|
||||
.map(|(ent, _)| ent.item().map_or(false, |i| i.is_op))
|
||||
.or_else(|e| if e.kind == ErrKind::Missing {
|
||||
(prev_root.0.walk1_ref(&[], &abs_path, false))
|
||||
.map(|(ent, _)| ent.item().map_or(false, |i| i.is_op))
|
||||
} else {Err(e)})
|
||||
.map_err(|e| e.at(location))?;
|
||||
box_once((name.clone(), abs_path, is_op))
|
||||
box_once((name.clone(), abs_path))
|
||||
} else {
|
||||
let rc_path = Rc::new(abs_path);
|
||||
// wildcard imports are validated
|
||||
@@ -116,8 +105,7 @@ pub fn import_tree(
|
||||
let new_imports = match (root.0).walk_ref(&[], &rc_path, false) {
|
||||
Err(e) if e.kind == ErrKind::Missing => Err(e),
|
||||
Err(e) => return Err(e.at(location)),
|
||||
Ok(module)
|
||||
=> Ok(process_donor_module(module, rc_path.clone(), |i| i.is_op))
|
||||
Ok(module) => Ok(process_donor_module(module, rc_path.clone()))
|
||||
};
|
||||
let old_m = match (prev_root.0).walk_ref(&[], &rc_path, false) {
|
||||
Err(e) if e.kind != ErrKind::Missing => return Err(e.at(location)),
|
||||
@@ -134,7 +122,7 @@ pub fn import_tree(
|
||||
},
|
||||
Ok(old_m) => old_m,
|
||||
};
|
||||
let it1 = process_donor_module(old_m, rc_path.clone(), |i| i.is_op);
|
||||
let it1 = process_donor_module(old_m, rc_path.clone());
|
||||
match new_imports {
|
||||
Err(_) => Box::new(it1),
|
||||
Ok(it2) => box_chain!(it1, it2)
|
||||
@@ -144,10 +132,10 @@ pub fn import_tree(
|
||||
// leaf sets flattened to leaves
|
||||
.flatten_ok()
|
||||
// translated to entries
|
||||
.map_ok(|(name, source, is_op)| {
|
||||
.map_ok(|(name, source)| {
|
||||
(name, ModEntry {
|
||||
exported: false, // this is irrelevant but needed
|
||||
member: ModMember::Item(ImpReport { source, is_op }),
|
||||
member: ModMember::Item(ImpReport { source }),
|
||||
})
|
||||
})
|
||||
.chain(
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
|
||||
@@ -7,15 +5,14 @@ use super::build_tree::{build_tree, TreeReport};
|
||||
use super::import_tree::{import_tree, ImpMod};
|
||||
use crate::error::ProjectResult;
|
||||
use crate::pipeline::source_loader::{
|
||||
LoadedSourceTable, PreExtra, PreItem, PreMod, Preparsed,
|
||||
LoadedSourceTable, PreExtra, PreMod, Preparsed,
|
||||
};
|
||||
use crate::representations::project::{ImpReport, ProjectExt, ProjectMod};
|
||||
use crate::representations::project::{ProjectExt, ProjectMod};
|
||||
use crate::sourcefile::FileEntry;
|
||||
use crate::tree::{ModEntry, ModMember, Module};
|
||||
use crate::utils::never::{always, unwrap_always};
|
||||
use crate::utils::pure_push::pushed_ref;
|
||||
use crate::utils::pure_seq::pushed_ref;
|
||||
use crate::utils::unwrap_or;
|
||||
use crate::{parse, Interner, ProjectTree, Tok, VName};
|
||||
use crate::{Interner, ProjectTree, Tok, VName};
|
||||
|
||||
pub fn rebuild_file(
|
||||
path: Vec<Tok<String>>,
|
||||
@@ -23,35 +20,12 @@ pub fn rebuild_file(
|
||||
imports: ImpMod,
|
||||
source: &LoadedSourceTable,
|
||||
prelude: &[FileEntry],
|
||||
i: &Interner,
|
||||
) -> ProjectResult<ProjectMod<VName>> {
|
||||
let file = match &pre.extra {
|
||||
PreExtra::Dir => panic!("Dir should not hand this node off"),
|
||||
PreExtra::Submod(_) => panic!("should not have received this"),
|
||||
PreExtra::File(f) => f,
|
||||
};
|
||||
let mut ops = Vec::new();
|
||||
unwrap_always(imports.search_all((), &mut |_, module, ()| {
|
||||
ops.extend(
|
||||
(module.entries.iter())
|
||||
.filter(|(_, ent)| {
|
||||
matches!(ent.member, ModMember::Item(ImpReport { is_op: true, .. }))
|
||||
})
|
||||
.map(|(name, _)| name.clone()),
|
||||
);
|
||||
always(())
|
||||
}));
|
||||
unwrap_always(pre.search_all((), &mut |_, module, ()| {
|
||||
ops.extend(
|
||||
(module.entries.iter())
|
||||
.filter(|(_, ent)| {
|
||||
matches!(ent.member, ModMember::Item(PreItem { is_op: true, .. }))
|
||||
})
|
||||
.map(|(name, _)| name.clone()),
|
||||
);
|
||||
always(())
|
||||
}));
|
||||
let ctx = parse::ParsingContext::new(&ops, i, Rc::new(path.clone()));
|
||||
let src = source.get(&file.name).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"{} should have been preparsed already. Preparsed files are {}",
|
||||
@@ -62,13 +36,11 @@ pub fn rebuild_file(
|
||||
.join(", ")
|
||||
)
|
||||
});
|
||||
let entries = parse::parse2(&src.text, ctx)?;
|
||||
let TreeReport { entries: items, rules, imports_from } =
|
||||
let entries = src.entries.clone();
|
||||
let TreeReport { entries, rules, imports_from } =
|
||||
build_tree(&path, entries, pre, imports, prelude)?;
|
||||
Ok(Module {
|
||||
entries: items,
|
||||
extra: ProjectExt { file: Some(path.clone()), path, imports_from, rules },
|
||||
})
|
||||
let file = Some(path.clone());
|
||||
Ok(Module { entries, extra: ProjectExt { file, path, imports_from, rules } })
|
||||
}
|
||||
|
||||
pub fn rebuild_dir(
|
||||
@@ -77,15 +49,14 @@ pub fn rebuild_dir(
|
||||
mut imports: ImpMod,
|
||||
source: &LoadedSourceTable,
|
||||
prelude: &[FileEntry],
|
||||
i: &Interner,
|
||||
) -> ProjectResult<ProjectMod<VName>> {
|
||||
match pre.extra {
|
||||
PreExtra::Dir => (),
|
||||
PreExtra::File(_) =>
|
||||
return rebuild_file(path, pre, imports, source, prelude, i),
|
||||
return rebuild_file(path, pre, imports, source, prelude),
|
||||
PreExtra::Submod(_) => panic!("Dirs contain dirs and files"),
|
||||
}
|
||||
let items = (pre.entries.into_iter())
|
||||
let entries = (pre.entries.into_iter())
|
||||
.map(|(name, entry)| {
|
||||
match imports.entries.remove(&name).map(|e| e.member) {
|
||||
Some(ModMember::Sub(impmod)) => (name, entry, impmod),
|
||||
@@ -97,12 +68,8 @@ pub fn rebuild_dir(
|
||||
let pre = unwrap_or!(member => ModMember::Sub;
|
||||
panic!("Dirs can only contain submodules")
|
||||
);
|
||||
Ok((name, ModEntry {
|
||||
exported,
|
||||
member: ModMember::Sub(rebuild_dir(
|
||||
path, pre, impmod, source, prelude, i,
|
||||
)?),
|
||||
}))
|
||||
let module = rebuild_dir(path, pre, impmod, source, prelude)?;
|
||||
Ok((name, ModEntry { exported, member: ModMember::Sub(module) }))
|
||||
})
|
||||
.collect::<Result<HashMap<_, _>, _>>()?;
|
||||
Ok(Module {
|
||||
@@ -112,7 +79,7 @@ pub fn rebuild_dir(
|
||||
rules: Vec::new(),
|
||||
file: None,
|
||||
},
|
||||
entries: items,
|
||||
entries,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -126,6 +93,6 @@ pub fn rebuild_tree(
|
||||
) -> ProjectResult<ProjectTree<VName>> {
|
||||
let imports =
|
||||
import_tree(Vec::new(), &preparsed.0, &preparsed, prev_root, i)?;
|
||||
rebuild_dir(Vec::new(), preparsed.0, imports, source, prelude, i)
|
||||
rebuild_dir(Vec::new(), preparsed.0, imports, source, prelude)
|
||||
.map(ProjectTree)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use super::loaded_source::{LoadedSource, LoadedSourceTable};
|
||||
@@ -7,24 +9,32 @@ use crate::error::{
|
||||
NoTargets, ProjectError, ProjectResult, UnexpectedDirectory,
|
||||
};
|
||||
use crate::interner::{Interner, Tok};
|
||||
use crate::parse::{self, LexerPlugin, LineParser, ParsingContext};
|
||||
use crate::pipeline::file_loader::{IOResult, Loaded};
|
||||
use crate::pipeline::import_abs_path::import_abs_path;
|
||||
use crate::representations::sourcefile::FileEntry;
|
||||
use crate::tree::Module;
|
||||
use crate::utils::pure_push::pushed_ref;
|
||||
use crate::utils::pure_seq::pushed_ref;
|
||||
use crate::utils::{split_max_prefix, unwrap_or};
|
||||
use crate::Location;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Context<'a> {
|
||||
pub prelude: &'a [FileEntry],
|
||||
pub i: &'a Interner,
|
||||
pub lexer_plugins: &'a [&'a dyn LexerPlugin],
|
||||
pub line_parsers: &'a [&'a dyn LineParser],
|
||||
}
|
||||
|
||||
/// Load the source at the given path or all within if it's a collection,
|
||||
/// and all sources imported from these.
|
||||
fn load_abs_path_rec(
|
||||
abs_path: &[Tok<String>],
|
||||
mut all: Preparsed,
|
||||
source: &mut LoadedSourceTable,
|
||||
prelude: &[FileEntry],
|
||||
i: &Interner,
|
||||
get_source: &impl Fn(&[Tok<String>]) -> IOResult,
|
||||
is_injected_module: &impl Fn(&[Tok<String>]) -> bool,
|
||||
ctx @ Context { i, lexer_plugins, line_parsers, prelude }: Context,
|
||||
) -> ProjectResult<Preparsed> {
|
||||
// # Termination
|
||||
//
|
||||
@@ -47,8 +57,15 @@ fn load_abs_path_rec(
|
||||
let text = unwrap_or!(get_source(filename)? => Loaded::Code; {
|
||||
return Err(UnexpectedDirectory { path: filename.to_vec() }.rc())
|
||||
});
|
||||
source.insert(filename.to_vec(), LoadedSource { text: text.clone() });
|
||||
let preparsed = preparse(filename.to_vec(), text.as_str(), prelude, i)?;
|
||||
let entries = parse::parse2(ParsingContext::new(
|
||||
i,
|
||||
Arc::new(filename.to_vec()),
|
||||
text,
|
||||
lexer_plugins,
|
||||
line_parsers,
|
||||
))?;
|
||||
let preparsed = preparse(filename.to_vec(), entries.clone(), prelude)?;
|
||||
source.insert(filename.to_vec(), LoadedSource { entries });
|
||||
// recurse on all imported modules
|
||||
// will be taken and returned by the closure. None iff an error is thrown
|
||||
all = preparsed.0.search_all(all, &mut |modpath,
|
||||
@@ -73,10 +90,9 @@ fn load_abs_path_rec(
|
||||
&abs_pathv,
|
||||
all,
|
||||
source,
|
||||
prelude,
|
||||
i,
|
||||
get_source,
|
||||
is_injected_module,
|
||||
ctx,
|
||||
)?;
|
||||
}
|
||||
Ok(all)
|
||||
@@ -105,10 +121,9 @@ fn load_abs_path_rec(
|
||||
&abs_subpath,
|
||||
all,
|
||||
source,
|
||||
prelude,
|
||||
i,
|
||||
get_source,
|
||||
is_injected_module,
|
||||
ctx,
|
||||
)?;
|
||||
}
|
||||
Ok(all)
|
||||
@@ -123,8 +138,7 @@ fn load_abs_path_rec(
|
||||
/// injected data (the ProjectTree doesn't make a distinction between the two)
|
||||
pub fn load_source<'a>(
|
||||
targets: impl Iterator<Item = &'a [Tok<String>]>,
|
||||
prelude: &[FileEntry],
|
||||
i: &Interner,
|
||||
ctx: Context,
|
||||
get_source: &impl Fn(&[Tok<String>]) -> IOResult,
|
||||
is_injected_module: &impl Fn(&[Tok<String>]) -> bool,
|
||||
) -> ProjectResult<(Preparsed, LoadedSourceTable)> {
|
||||
@@ -138,10 +152,9 @@ pub fn load_source<'a>(
|
||||
target,
|
||||
all,
|
||||
&mut table,
|
||||
prelude,
|
||||
i,
|
||||
get_source,
|
||||
is_injected_module,
|
||||
ctx,
|
||||
)?;
|
||||
}
|
||||
if any_target { Ok((all, table)) } else { Err(NoTargets.rc()) }
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::representations::VName;
|
||||
use crate::sourcefile::FileEntry;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LoadedSource {
|
||||
pub text: Rc<String>,
|
||||
pub entries: Vec<FileEntry>
|
||||
}
|
||||
|
||||
pub type LoadedSourceTable = HashMap<VName, LoadedSource>;
|
||||
|
||||
@@ -20,6 +20,6 @@ mod loaded_source;
|
||||
mod preparse;
|
||||
mod types;
|
||||
|
||||
pub use load_source::load_source;
|
||||
pub use load_source::{load_source, Context};
|
||||
pub use loaded_source::{LoadedSource, LoadedSourceTable};
|
||||
pub use types::{PreExtra, PreFileExt, PreItem, PreMod, PreSubExt, Preparsed};
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
|
||||
use super::types::{PreFileExt, PreItem, PreSubExt};
|
||||
use super::{PreExtra, Preparsed};
|
||||
use crate::ast::{Clause, Constant, Expr};
|
||||
use crate::ast::{Clause, Constant};
|
||||
use crate::error::{
|
||||
ConflictingRoles, ProjectError, ProjectResult, VisibilityMismatch,
|
||||
};
|
||||
use crate::interner::Interner;
|
||||
use crate::parse::{self, ParsingContext};
|
||||
use crate::representations::sourcefile::{FileEntry, MemberKind};
|
||||
use crate::representations::tree::{ModEntry, ModMember, Module};
|
||||
use crate::sourcefile::{FileEntryKind, Import, Member, ModuleBlock};
|
||||
use crate::utils::get_or::{get_or_default, get_or_make};
|
||||
use crate::utils::pure_push::pushed;
|
||||
use crate::utils::pure_seq::pushed;
|
||||
use crate::{Location, Tok, VName};
|
||||
|
||||
struct FileReport {
|
||||
entries: HashMap<Tok<String>, ModEntry<PreItem, PreExtra>>,
|
||||
patterns: Vec<Vec<Expr<VName>>>,
|
||||
imports: Vec<Import>,
|
||||
}
|
||||
|
||||
@@ -32,12 +27,11 @@ fn to_module(
|
||||
prelude: &[FileEntry],
|
||||
) -> ProjectResult<FileReport> {
|
||||
let mut imports = Vec::new();
|
||||
let mut patterns = Vec::new();
|
||||
let mut items = HashMap::<Tok<String>, (bool, PreItem)>::new();
|
||||
let mut to_export = HashMap::<Tok<String>, Vec<Location>>::new();
|
||||
let mut submods =
|
||||
HashMap::<Tok<String>, (bool, Vec<Location>, Vec<FileEntry>)>::new();
|
||||
let entries = prelude.iter().cloned().chain(src.into_iter());
|
||||
let entries = prelude.iter().cloned().chain(src);
|
||||
for FileEntry { kind, locations } in entries {
|
||||
match kind {
|
||||
FileEntryKind::Import(imp) => imports.extend(imp.into_iter()),
|
||||
@@ -72,17 +66,7 @@ fn to_module(
|
||||
submods.insert(name.clone(), (exported, locations, body.clone()));
|
||||
}
|
||||
},
|
||||
MemberKind::Operators(ops) =>
|
||||
for op in ops {
|
||||
let (prev_exported, it) = get_or_default(&mut items, &op);
|
||||
if let Some(loc) = locations.get(0) {
|
||||
it.location = it.location.clone().or(loc.clone())
|
||||
}
|
||||
*prev_exported |= exported;
|
||||
it.is_op = true;
|
||||
},
|
||||
MemberKind::Rule(r) => {
|
||||
patterns.push(r.pattern.clone());
|
||||
MemberKind::Rule(r) =>
|
||||
if exported {
|
||||
for ex in r.pattern {
|
||||
ex.search_all(&mut |ex| {
|
||||
@@ -95,8 +79,7 @@ fn to_module(
|
||||
None::<()>
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
@@ -111,11 +94,11 @@ fn to_module(
|
||||
.try_insert(subname.clone(), ModEntry {
|
||||
member: ModMember::Sub({
|
||||
name.push(subname);
|
||||
let FileReport { imports, entries: items, patterns } =
|
||||
let FileReport { imports, entries: items } =
|
||||
to_module(file, name.clone(), body, prelude)?;
|
||||
Module {
|
||||
entries: items,
|
||||
extra: PreExtra::Submod(PreSubExt { imports, patterns }),
|
||||
extra: PreExtra::Submod(PreSubExt { imports }),
|
||||
}
|
||||
}),
|
||||
exported,
|
||||
@@ -125,7 +108,6 @@ fn to_module(
|
||||
for (item, locations) in to_export {
|
||||
get_or_make(&mut entries, &item, || ModEntry {
|
||||
member: ModMember::Item(PreItem {
|
||||
is_op: false,
|
||||
has_value: false,
|
||||
location: locations[0].clone(),
|
||||
}),
|
||||
@@ -133,26 +115,22 @@ fn to_module(
|
||||
})
|
||||
.exported = true
|
||||
}
|
||||
Ok(FileReport { entries, imports, patterns })
|
||||
Ok(FileReport { entries, imports })
|
||||
}
|
||||
|
||||
/// Preparse the module. At this stage, only the imports and
|
||||
/// names defined by the module can be parsed
|
||||
pub fn preparse(
|
||||
file: VName,
|
||||
source: &str,
|
||||
entries: Vec<FileEntry>,
|
||||
prelude: &[FileEntry],
|
||||
i: &Interner,
|
||||
) -> ProjectResult<Preparsed> {
|
||||
// Parse with no operators
|
||||
let ctx = ParsingContext::new(&[], i, Rc::new(file.clone()));
|
||||
let entries = parse::parse2(source, ctx)?;
|
||||
let FileReport { entries, imports, patterns } =
|
||||
let FileReport { entries, imports } =
|
||||
to_module(&file, file.clone(), entries, prelude)?;
|
||||
let mut module = Module {
|
||||
entries,
|
||||
extra: PreExtra::File(PreFileExt {
|
||||
details: PreSubExt { patterns, imports },
|
||||
details: PreSubExt { imports },
|
||||
name: file.clone(),
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::fmt::Display;
|
||||
use std::ops::Add;
|
||||
|
||||
use crate::ast::Expr;
|
||||
use crate::error::ProjectResult;
|
||||
use crate::sourcefile::Import;
|
||||
use crate::tree::Module;
|
||||
@@ -9,34 +8,27 @@ use crate::{Interner, Location, VName};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PreItem {
|
||||
pub is_op: bool,
|
||||
pub has_value: bool,
|
||||
pub location: Location,
|
||||
}
|
||||
|
||||
impl Display for PreItem {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { has_value, is_op, location } = self;
|
||||
let description = match (is_op, has_value) {
|
||||
(true, true) => "operator with value",
|
||||
(true, false) => "operator",
|
||||
(false, true) => "value",
|
||||
(false, false) => "keyword",
|
||||
};
|
||||
let Self { has_value, location } = self;
|
||||
let description = if *has_value { "value" } else { "keyword" };
|
||||
write!(f, "{description} {location}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PreItem {
|
||||
fn default() -> Self {
|
||||
PreItem { is_op: false, has_value: false, location: Location::Unknown }
|
||||
PreItem { has_value: false, location: Location::Unknown }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PreSubExt {
|
||||
pub imports: Vec<Import>,
|
||||
pub patterns: Vec<Vec<Expr<VName>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
||||
Reference in New Issue
Block a user