diff options
author | Nadrieril | 2019-04-06 20:04:04 +0200 |
---|---|---|
committer | Nadrieril | 2019-04-06 20:13:22 +0200 |
commit | 396ec334bac1e8d10a2d2b2d683c93e3b2ff4d8d (patch) | |
tree | 53503ab8fa9fa90cfc440ff06f4942bc74ade27f /dhall | |
parent | 366bc783e62682c9597e8caba1dac56638d34fa9 (diff) |
Massage import loading into new API
Closes #9
Diffstat (limited to '')
-rw-r--r-- | dhall/src/expr.rs | 30 | ||||
-rw-r--r-- | dhall/src/imports.rs | 95 | ||||
-rw-r--r-- | dhall/tests/common/mod.rs | 9 | ||||
-rw-r--r-- | dhall_core/src/core.rs | 39 |
4 files changed, 122 insertions, 51 deletions
diff --git a/dhall/src/expr.rs b/dhall/src/expr.rs index 0d093cb..72633ea 100644 --- a/dhall/src/expr.rs +++ b/dhall/src/expr.rs @@ -1,17 +1,27 @@ +use crate::imports::ImportError; +use crate::imports::ImportRoot; use crate::typecheck::TypeError; use dhall_core::*; -pub struct Parsed(SubExpr<X, Import>); -pub struct Resolved(SubExpr<X, X>); -pub struct Typed(SubExpr<X, X>, Type); -pub struct Type(Box<Normalized>); -pub struct Normalized(SubExpr<X, X>); +#[derive(Debug, Clone)] +pub struct Parsed(pub(crate) SubExpr<X, Import>, pub(crate) ImportRoot); +#[derive(Debug, Clone)] +pub struct Resolved(pub(crate) SubExpr<X, X>); +#[derive(Debug, Clone)] +pub struct Typed(pub(crate) SubExpr<X, X>, Type); +#[derive(Debug, Clone)] +pub struct Type(pub(crate) Box<Normalized>); +#[derive(Debug, Clone)] +pub struct Normalized(pub(crate) SubExpr<X, X>); -// impl Parsed { -// pub fn resolve(self) -> Result<Resolved, ImportError> { -// Ok(Resolved(crate::imports::resolve(self.0)?)) -// } -// } +impl Parsed { + pub fn resolve(self) -> Result<Resolved, ImportError> { + crate::imports::resolve_expr(self, true) + } + pub fn resolve_no_imports(self) -> Result<Resolved, ImportError> { + crate::imports::resolve_expr(self, false) + } +} impl Resolved { pub fn typecheck(self) -> Result<Typed, TypeError<X>> { let typ = Type(Box::new(Normalized(crate::typecheck::type_of( diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs index 95cf6fa..bc38bb6 100644 --- a/dhall/src/imports.rs +++ b/dhall/src/imports.rs @@ -1,6 +1,7 @@ // use dhall_core::{Expr, FilePrefix, Import, ImportLocation, ImportMode, X}; use dhall_core::{Expr, Import, X}; // use std::path::Path; +use crate::expr::*; use dhall_core::*; use std::fmt; use std::fs::File; @@ -8,6 +9,34 @@ use std::io::Read; use std::path::Path; use std::path::PathBuf; +#[derive(Debug)] +pub enum ImportError { + ParseError(ParseError), + IOError(std::io::Error), + UnexpectedImportError(Import), +} +impl From<ParseError> for ImportError { + fn from(e: ParseError) -> Self { + ImportError::ParseError(e) + } +} +impl From<std::io::Error> for ImportError { + fn from(e: std::io::Error) -> Self { + ImportError::IOError(e) + } +} +impl fmt::Display for ImportError { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + use self::ImportError::*; + match self { + ParseError(e) => e.fmt(f), + IOError(e) => e.fmt(f), + UnexpectedImportError(e) => e.fmt(f), + } + } +} + +// Deprecated pub fn panic_imports<S: Clone>(expr: &Expr<S, Import>) -> Expr<S, X> { let no_import = |i: &Import| -> X { panic!("ahhh import: {:?}", i) }; expr.map_embed(&no_import) @@ -42,55 +71,43 @@ fn resolve_import( } } -#[derive(Debug)] -pub enum ImportError { - ParseError(ParseError), - IOError(std::io::Error), -} -impl From<ParseError> for ImportError { - fn from(e: ParseError) -> Self { - ImportError::ParseError(e) - } -} -impl From<std::io::Error> for ImportError { - fn from(e: std::io::Error) -> Self { - ImportError::IOError(e) - } -} -impl fmt::Display for ImportError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - use self::ImportError::*; - match self { - ParseError(e) => e.fmt(f), - IOError(e) => e.fmt(f), +pub(crate) fn resolve_expr( + Parsed(expr, root): Parsed, + allow_imports: bool, +) -> Result<Resolved, ImportError> { + let resolve = |import: &Import| -> Result<SubExpr<X, X>, ImportError> { + if allow_imports { + let expr = resolve_import(import, &root)?; + Ok(expr.roll()) + } else { + Err(ImportError::UnexpectedImportError(import.clone())) } - } + }; + let expr = expr.as_ref().traverse_embed(&resolve)?; + Ok(Resolved(expr.squash_embed())) +} + +pub fn load_from_file(f: &Path) -> Result<Parsed, ImportError> { + let mut buffer = String::new(); + File::open(f)?.read_to_string(&mut buffer)?; + let expr = parse_expr(&*buffer)?; + let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned()); + Ok(Parsed(expr, root)) } +// Deprecated pub fn load_dhall_file( f: &Path, resolve_imports: bool, ) -> Result<Expr<X, X>, ImportError> { - let mut buffer = String::new(); - File::open(f)?.read_to_string(&mut buffer)?; - let expr = parse_expr(&*buffer)?; - let expr = if resolve_imports { - let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned()); - let resolve = |import: &Import| -> Expr<X, X> { - resolve_import(import, &root).unwrap() - }; - expr.as_ref().map_embed(&resolve).squash_embed() - } else { - panic_imports(expr.as_ref()) - }; - Ok(expr) + let expr = load_from_file(f)?; + let expr = resolve_expr(expr, resolve_imports)?; + Ok(expr.0.unroll()) } +// Deprecated pub fn load_dhall_file_no_resolve_imports( f: &Path, ) -> Result<ParsedExpr, ImportError> { - let mut buffer = String::new(); - File::open(f)?.read_to_string(&mut buffer)?; - let expr = parse_expr(&*buffer)?; - Ok(expr) + Ok(load_from_file(f)?.0) } diff --git a/dhall/tests/common/mod.rs b/dhall/tests/common/mod.rs index e748cf0..70b7d81 100644 --- a/dhall/tests/common/mod.rs +++ b/dhall/tests/common/mod.rs @@ -54,6 +54,12 @@ pub fn read_dhall_file_no_resolve_imports<'i>( load_dhall_file_no_resolve_imports(&PathBuf::from(file_path)) } +pub fn load_from_file_str<'i>( + file_path: &str, +) -> Result<dhall::Parsed, ImportError> { + load_from_file(&PathBuf::from(file_path)) +} + pub fn run_test(base_path: &str, feature: Feature) { use self::Feature::*; let base_path_prefix = match feature { @@ -90,8 +96,7 @@ pub fn run_test(base_path: &str, feature: Feature) { } ParserFailure => { let file_path = base_path + ".dhall"; - let err = - read_dhall_file_no_resolve_imports(&file_path).unwrap_err(); + let err = load_from_file_str(&file_path).unwrap_err(); match err { ImportError::ParseError(_) => {} e => panic!("Expected parse error, got: {:?}", e), diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index a56c5a3..d832cd5 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -285,6 +285,28 @@ impl<S, A> Expr<S, A> { self.map_shallow(recurse, |x| x.clone(), map_embed, |x| x.clone()) } + #[inline(always)] + pub fn traverse_embed<B, Err, F>( + &self, + map_embed: &F, + ) -> Result<Expr<S, B>, Err> + where + S: Clone, + B: Clone, + F: Fn(&A) -> Result<B, Err>, + { + let recurse = |e: &SubExpr<S, A>| -> Result<SubExpr<S, B>, Err> { + Ok(e.as_ref().traverse_embed(map_embed)?.roll()) + }; + self.as_ref().traverse( + |e| recurse(e), + |_, e| recurse(e), + |x| Ok(S::clone(x)), + map_embed, + |x| Ok(Label::clone(x)), + ) + } + pub fn map_label<F>(&self, map_label: &F) -> Self where A: Clone, @@ -319,6 +341,23 @@ impl<S: Clone, A: Clone> Expr<S, Expr<S, A>> { } } +impl<S: Clone, A: Clone> Expr<S, SubExpr<S, A>> { + pub fn squash_embed(&self) -> SubExpr<S, A> { + match self.as_ref() { + ExprF::Embed(e) => e.clone(), + e => e + .map( + |e| e.as_ref().squash_embed(), + |_, e| e.as_ref().squash_embed(), + S::clone, + |_| unreachable!(), + Label::clone, + ) + .roll(), + } + } +} + impl<SE, L, N, E> ExprF<SE, L, N, E> { #[inline(always)] pub fn as_ref(&self) -> ExprF<&SE, &L, &N, &E> |