Public API and docs
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
//! Various errors the pipeline can produce
|
||||
mod module_not_found;
|
||||
mod not_exported;
|
||||
mod parse_error_with_path;
|
||||
|
||||
@@ -4,6 +4,7 @@ use super::{ErrorPosition, ProjectError};
|
||||
use crate::representations::location::Location;
|
||||
use crate::utils::BoxedIter;
|
||||
|
||||
/// An import refers to a symbol which exists but is not exported.
|
||||
#[derive(Debug)]
|
||||
pub struct NotExported {
|
||||
pub file: Vec<String>,
|
||||
|
||||
@@ -29,7 +29,7 @@ pub trait ProjectError: Debug {
|
||||
}
|
||||
/// Code positions relevant to this error
|
||||
fn positions(&self) -> BoxedIter<ErrorPosition>;
|
||||
/// Convert the error into an [Rc<dyn ProjectError>] to be able to
|
||||
/// Convert the error into an `Rc<dyn ProjectError>` to be able to
|
||||
/// handle various errors together
|
||||
fn rc(self) -> Rc<dyn ProjectError>
|
||||
where
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::representations::location::Location;
|
||||
use crate::utils::iter::box_once;
|
||||
use crate::utils::BoxedIter;
|
||||
|
||||
/// Multiple occurences of the same namespace with different visibility
|
||||
#[derive(Debug)]
|
||||
pub struct VisibilityMismatch {
|
||||
pub namespace: Vec<String>,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//! File system implementation of the source loader callback
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::{fs, io};
|
||||
@@ -9,6 +10,7 @@ use crate::pipeline::error::{
|
||||
use crate::utils::iter::box_once;
|
||||
use crate::utils::{BoxedIter, Cache};
|
||||
|
||||
/// All the data available about a failed source load call
|
||||
#[derive(Debug)]
|
||||
pub struct FileLoadingError {
|
||||
file: io::Error,
|
||||
@@ -40,10 +42,9 @@ impl Loaded {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returned by any source loading callback
|
||||
pub type IOResult = Result<Loaded, Rc<dyn ProjectError>>;
|
||||
|
||||
pub type FileCache<'a> = Cache<'a, Sym, IOResult>;
|
||||
|
||||
/// Load a file from a path expressed in Rust strings, but relative to
|
||||
/// a root expressed as an OS Path.
|
||||
pub fn load_file(root: &Path, path: &[impl AsRef<str>]) -> IOResult {
|
||||
@@ -81,7 +82,7 @@ pub fn load_file(root: &Path, path: &[impl AsRef<str>]) -> IOResult {
|
||||
}
|
||||
|
||||
/// Generates a cached file loader for a directory
|
||||
pub fn mk_cache(root: PathBuf, i: &Interner) -> FileCache {
|
||||
pub fn mk_cache(root: PathBuf, i: &Interner) -> Cache<Sym, IOResult> {
|
||||
Cache::new(move |token: Sym, _this| -> IOResult {
|
||||
let path = i.r(token).iter().map(|t| i.r(*t).as_str()).collect::<Vec<_>>();
|
||||
load_file(&root, &path)
|
||||
|
||||
@@ -90,17 +90,17 @@ fn apply_aliases_rec(
|
||||
.rules
|
||||
.iter()
|
||||
.map(|rule| {
|
||||
let Rule { source, prio, target } = rule;
|
||||
let Rule { pattern, prio, template } = rule;
|
||||
Rule {
|
||||
prio: *prio,
|
||||
source: Rc::new(
|
||||
source
|
||||
pattern: Rc::new(
|
||||
pattern
|
||||
.iter()
|
||||
.map(|expr| process_expr(expr, alias_map, injected_as, i))
|
||||
.collect::<Vec<_>>(),
|
||||
),
|
||||
target: Rc::new(
|
||||
target
|
||||
template: Rc::new(
|
||||
template
|
||||
.iter()
|
||||
.map(|expr| process_expr(expr, alias_map, injected_as, i))
|
||||
.collect::<Vec<_>>(),
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
use trait_set::trait_set;
|
||||
|
||||
use crate::interner::{Sym, Tok};
|
||||
|
||||
pub trait InjectedAsFn = Fn(&[Tok<String>]) -> Option<Sym>;
|
||||
trait_set! {
|
||||
pub trait InjectedAsFn = Fn(&[Tok<String>]) -> Option<Sym>;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//! Loading Orchid modules from source
|
||||
pub mod error;
|
||||
pub mod file_loader;
|
||||
mod import_abs_path;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
|
||||
use super::collect_ops::InjectedOperatorsFn;
|
||||
use super::parse_file::parse_file;
|
||||
@@ -87,7 +88,7 @@ fn source_to_module(
|
||||
Member::Namespace(ns) => box_once(mk_ent(ns.name)),
|
||||
Member::Rule(rule) => {
|
||||
let mut names = Vec::new();
|
||||
for e in rule.source.iter() {
|
||||
for e in rule.pattern.iter() {
|
||||
e.visit_names(Substack::Bottom, &mut |n| {
|
||||
if let Some([name]) = i.r(n).strip_prefix(&path_v[..]) {
|
||||
names.push((*name, n))
|
||||
@@ -177,7 +178,7 @@ fn source_to_module(
|
||||
|
||||
fn files_to_module(
|
||||
path: Substack<Tok<String>>,
|
||||
files: &[ParsedSource],
|
||||
files: Vec<ParsedSource>,
|
||||
i: &Interner,
|
||||
) -> Rc<Module<Expr, ProjectExt>> {
|
||||
let lvl = path.len();
|
||||
@@ -192,11 +193,13 @@ fn files_to_module(
|
||||
);
|
||||
}
|
||||
let items = files
|
||||
.group_by(|a, b| a.path[lvl] == b.path[lvl])
|
||||
.map(|files| {
|
||||
let namespace = files[0].path[lvl];
|
||||
.into_iter()
|
||||
.group_by(|f| f.path[lvl])
|
||||
.into_iter()
|
||||
.map(|(namespace, files)| {
|
||||
let subpath = path.push(namespace);
|
||||
let module = files_to_module(subpath, files, i);
|
||||
let files_v = files.collect::<Vec<_>>();
|
||||
let module = files_to_module(subpath, files_v, i);
|
||||
let member = ModMember::Sub(module);
|
||||
(namespace, ModEntry { exported: true, member })
|
||||
})
|
||||
@@ -206,11 +209,6 @@ fn files_to_module(
|
||||
.copied()
|
||||
.map(|name| (name, i.i(&pushed(&path_v, name))))
|
||||
.collect();
|
||||
// println!(
|
||||
// "Constructing module {} with items ({})",
|
||||
// i.extern_all(&path_v[..]).join("::"),
|
||||
// exports.keys().map(|t| i.r(*t)).join(", ")
|
||||
// );
|
||||
Rc::new(Module {
|
||||
items,
|
||||
imports: vec![],
|
||||
@@ -250,5 +248,5 @@ pub fn build_tree(
|
||||
path: path.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
Ok(ProjectTree(files_to_module(Substack::Bottom, &files, i)))
|
||||
Ok(ProjectTree(files_to_module(Substack::Bottom, files, i)))
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ 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};
|
||||
@@ -14,7 +15,9 @@ use crate::utils::Cache;
|
||||
pub type OpsResult = Result<Rc<HashSet<Tok<String>>>, Rc<dyn ProjectError>>;
|
||||
pub type ExportedOpsCache<'a> = Cache<'a, Sym, OpsResult>;
|
||||
|
||||
pub trait InjectedOperatorsFn = Fn(Sym) -> Option<Rc<HashSet<Tok<String>>>>;
|
||||
trait_set! {
|
||||
pub trait InjectedOperatorsFn = Fn(Sym) -> Option<Rc<HashSet<Tok<String>>>>;
|
||||
}
|
||||
|
||||
fn coprefix<T: Eq>(
|
||||
l: impl Iterator<Item = T>,
|
||||
|
||||
@@ -12,23 +12,30 @@ use crate::representations::tree::{ModEntry, ModMember, Module};
|
||||
use crate::representations::Primitive;
|
||||
use crate::utils::{pushed, Substack};
|
||||
|
||||
/// A lightweight module tree that can be built declaratively by hand to
|
||||
/// describe libraries of external functions in Rust. It implements [Add] for
|
||||
/// added convenience
|
||||
pub enum ConstTree {
|
||||
Const(Expr),
|
||||
Tree(HashMap<Tok<String>, ConstTree>),
|
||||
}
|
||||
impl ConstTree {
|
||||
/// Describe a [Primitive]
|
||||
pub fn primitive(primitive: Primitive) -> Self {
|
||||
Self::Const(Expr {
|
||||
location: Location::Unknown,
|
||||
value: Clause::P(primitive),
|
||||
})
|
||||
}
|
||||
/// Describe an [ExternFn]
|
||||
pub fn xfn(xfn: impl ExternFn + 'static) -> Self {
|
||||
Self::primitive(Primitive::ExternFn(Box::new(xfn)))
|
||||
}
|
||||
/// Describe an [Atomic]
|
||||
pub fn atom(atom: impl Atomic + 'static) -> Self {
|
||||
Self::primitive(Primitive::Atom(Atom(Box::new(atom))))
|
||||
}
|
||||
/// Describe a module
|
||||
pub fn tree(arr: impl IntoIterator<Item = (Tok<String>, Self)>) -> Self {
|
||||
Self::Tree(arr.into_iter().collect())
|
||||
}
|
||||
@@ -89,6 +96,8 @@ fn from_const_tree_rec(
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a map of [ConstTree] into a [ProjectTree] that can be used with the
|
||||
/// layered parsing system
|
||||
pub fn from_const_tree(
|
||||
consts: HashMap<Tok<String>, ConstTree>,
|
||||
file: &[Tok<String>],
|
||||
|
||||
@@ -35,11 +35,11 @@ fn member_rec(
|
||||
}),
|
||||
Member::Rule(rule) => Member::Rule(Rule {
|
||||
prio: rule.prio,
|
||||
source: Rc::new(
|
||||
rule.source.iter().map(|e| e.prefix(prefix, i, &except)).collect(),
|
||||
pattern: Rc::new(
|
||||
rule.pattern.iter().map(|e| e.prefix(prefix, i, &except)).collect(),
|
||||
),
|
||||
target: Rc::new(
|
||||
rule.target.iter().map(|e| e.prefix(prefix, i, &except)).collect(),
|
||||
template: Rc::new(
|
||||
rule.template.iter().map(|e| e.prefix(prefix, i, &except)).collect(),
|
||||
),
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -8,11 +8,13 @@ use crate::interner::{Interner, Sym, Tok};
|
||||
use crate::representations::tree::{ModMember, Module};
|
||||
use crate::utils::Substack;
|
||||
|
||||
/// Additional data about a loaded module beyond the list of constants and
|
||||
/// submodules
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ProjectExt {
|
||||
/// Pairs each foreign token to the module it was imported from
|
||||
pub imports_from: HashMap<Tok<String>, Sym>,
|
||||
/// Pairs each exported token to its original full name.
|
||||
/// Pairs each exported token to its original full name
|
||||
pub exports: HashMap<Tok<String>, Sym>,
|
||||
/// All rules defined in this module, exported or not
|
||||
pub rules: Vec<Rule>,
|
||||
@@ -35,7 +37,10 @@ impl Add for ProjectExt {
|
||||
}
|
||||
}
|
||||
|
||||
/// A node in the tree describing the project
|
||||
pub type ProjectModule = Module<Expr, ProjectExt>;
|
||||
|
||||
/// Module corresponding to the root of a project
|
||||
pub struct ProjectTree(pub Rc<ProjectModule>);
|
||||
|
||||
fn collect_rules_rec(bag: &mut Vec<Rule>, module: &ProjectModule) {
|
||||
@@ -47,6 +52,8 @@ fn collect_rules_rec(bag: &mut Vec<Rule>, module: &ProjectModule) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect the complete list of rules to be used by the rule repository from
|
||||
/// the [ProjectTree]
|
||||
pub fn collect_rules(project: &ProjectTree) -> Vec<Rule> {
|
||||
let mut rules = Vec::new();
|
||||
collect_rules_rec(&mut rules, project.0.as_ref());
|
||||
@@ -72,6 +79,7 @@ fn collect_consts_rec(
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the symbol table from a [ProjectTree]
|
||||
pub fn collect_consts(
|
||||
project: &ProjectTree,
|
||||
i: &Interner,
|
||||
|
||||
Reference in New Issue
Block a user