September-october commit

- manual parser
- stl refinements
- all language constructs are now Send
This commit is contained in:
2023-10-11 18:27:50 +01:00
parent 56679dcc01
commit 86e520e8b8
127 changed files with 1666 additions and 1872 deletions

View File

@@ -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(),

View File

@@ -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()
}

View File

@@ -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;

View File

@@ -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 =

View File

@@ -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,
}),
})
});

View File

@@ -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(

View File

@@ -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)
}

View File

@@ -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()) }

View File

@@ -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>;

View File

@@ -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};

View File

@@ -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(),
}),
};

View File

@@ -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)]