summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dhall/src/imports.rs86
-rw-r--r--dhall/src/lib.rs47
-rw-r--r--dhall/src/main.rs3
-rw-r--r--dhall/tests/macros.rs31
-rw-r--r--dhall_core/src/core.rs10
-rw-r--r--dhall_core/src/parser.rs4
6 files changed, 106 insertions, 75 deletions
diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs
index ad0ae0f..d6da4d7 100644
--- a/dhall/src/imports.rs
+++ b/dhall/src/imports.rs
@@ -1,11 +1,89 @@
// use dhall_core::{Expr, FilePrefix, Import, ImportLocation, ImportMode, X};
-use dhall_core::{Expr, StringLike, Import, X};
+use dhall_core::{Expr, Import, StringLike, X};
// use std::path::Path;
-// use std::path::PathBuf;
+use dhall_core::*;
+use std::fmt;
+use std::fs::File;
+use std::io::Read;
+use std::path::Path;
+use std::path::PathBuf;
-pub fn resolve_imports<Label: StringLike, S: Clone>(
+pub fn panic_imports<Label: StringLike, S: Clone>(
expr: &Expr<Label, S, Import>,
) -> Expr<Label, S, X> {
- let no_import = |_: &Import| -> X { panic!("ahhh import") };
+ let no_import = |i: &Import| -> X { panic!("ahhh import: {:?}", i) };
expr.map_embed(&no_import)
}
+
+/// A root from which to resolve relative imports.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum ImportRoot {
+ LocalDir(PathBuf),
+}
+
+fn resolve_import(
+ import: &Import,
+ root: &ImportRoot,
+) -> Result<Expr<String, X, X>, DhallError> {
+ use self::ImportRoot::*;
+ use dhall_core::FilePrefix::*;
+ use dhall_core::ImportLocation::*;
+ let cwd = match root {
+ LocalDir(cwd) => cwd,
+ };
+ match &import.location {
+ Local(prefix, path) => {
+ let path = match prefix {
+ Parent => cwd.parent().unwrap().join(path),
+ _ => unimplemented!(),
+ };
+ load_dhall_file(&path, false)
+ }
+ }
+}
+
+#[derive(Debug)]
+pub enum DhallError {
+ ParseError(parser::ParseError),
+ IOError(std::io::Error),
+}
+impl From<parser::ParseError> for DhallError {
+ fn from(e: parser::ParseError) -> Self {
+ DhallError::ParseError(e)
+ }
+}
+impl From<std::io::Error> for DhallError {
+ fn from(e: std::io::Error) -> Self {
+ DhallError::IOError(e)
+ }
+}
+impl fmt::Display for DhallError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ use self::DhallError::*;
+ match self {
+ ParseError(e) => e.fmt(f),
+ IOError(e) => e.fmt(f),
+ }
+ }
+}
+
+pub fn load_dhall_file(
+ f: &Path,
+ resolve_imports: bool,
+) -> Result<Expr<String, X, X>, DhallError> {
+ let mut buffer = String::new();
+ File::open(f)?.read_to_string(&mut buffer)?;
+ let expr = parser::parse_expr(&*buffer)?;
+ let expr = expr.take_ownership_of_labels();
+ let expr = if resolve_imports {
+ let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned());
+ let resolve = |import: &Import| -> Expr<String, X, X> {
+ resolve_import(import, &root).unwrap()
+ };
+ let expr = expr.map_embed(&resolve).squash_embed();
+ expr
+ } else {
+ panic_imports(&expr)
+ };
+ Ok(expr)
+}
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs
index 95f7f6f..8add5b6 100644
--- a/dhall/src/lib.rs
+++ b/dhall/src/lib.rs
@@ -7,49 +7,4 @@ pub use crate::normalize::*;
pub mod imports;
pub mod typecheck;
-use dhall_core::*;
-use std::fmt;
-use std::fs::File;
-use std::io::Read;
-use std::path::Path;
-
-#[derive(Debug)]
-pub enum DhallError {
- ParseError(parser::ParseError),
- IOError(std::io::Error),
-}
-impl From<parser::ParseError> for DhallError {
- fn from(e: parser::ParseError) -> Self {
- DhallError::ParseError(e)
- }
-}
-impl From<std::io::Error> for DhallError {
- fn from(e: std::io::Error) -> Self {
- DhallError::IOError(e)
- }
-}
-impl fmt::Display for DhallError {
- fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- use self::DhallError::*;
- match self {
- ParseError(e) => e.fmt(f),
- IOError(e) => e.fmt(f),
- }
- }
-}
-
-/// `source_pool` is a Vec of strings to be used to store the contents of imported files.
-/// No ideal but necessary for lifetime reasons for now.
-pub fn load_dhall_file<'i, 'a: 'i>(
- f: &Path,
- source_pool: &'a mut Vec<String>,
- _resolve_imports: bool,
-) -> Result<Expr<String, X, X>, DhallError> {
- source_pool.push(String::new());
- let mut buffer = source_pool.last_mut().unwrap();
- File::open(f)?.read_to_string(&mut buffer)?;
- let expr = parser::parse_expr(&*buffer)?;
- let expr = expr.take_ownership_of_labels();
- let expr = imports::resolve_imports(&expr);
- Ok(expr)
-}
+pub use crate::imports::{load_dhall_file, DhallError};
diff --git a/dhall/src/main.rs b/dhall/src/main.rs
index 23c8108..d072fe7 100644
--- a/dhall/src/main.rs
+++ b/dhall/src/main.rs
@@ -65,7 +65,8 @@ fn main() {
}
};
- let expr: Expr<String, _, _> = imports::resolve_imports(&expr.take_ownership_of_labels());
+ let expr: Expr<String, _, _> =
+ imports::panic_imports(&expr.take_ownership_of_labels());
let type_expr = match typecheck::type_of(&expr) {
Err(e) => {
diff --git a/dhall/tests/macros.rs b/dhall/tests/macros.rs
index 83510a3..5175238 100644
--- a/dhall/tests/macros.rs
+++ b/dhall/tests/macros.rs
@@ -41,7 +41,6 @@ macro_rules! make_spec_test {
#[allow(unused_imports)]
fn $name() {
use crate::macros::*;
- use dhall::imports::resolve_imports;
use dhall::*;
use dhall_core::*;
use std::thread;
@@ -61,10 +60,7 @@ macro_rules! make_spec_test {
}
use dhall::*;
-use dhall_core::parser::*;
use dhall_core::*;
-use std::fs::File;
-use std::io::Read;
use std::path::PathBuf;
pub enum Feature {
@@ -79,29 +75,23 @@ pub enum ExpectedResult {
pub fn read_dhall_file<'i>(
file_path: &str,
- mut buffer: &'i mut String,
-) -> Result<Box<Expr<String, X, Import>>, ParseError> {
- let mut file = File::open(&file_path).unwrap();
- file.read_to_string(&mut buffer).unwrap();
- let expr = parser::parse_expr(&*buffer)?;
- Ok(Box::new(expr.take_ownership_of_labels()))
+) -> Result<Expr<String, X, X>, DhallError> {
+ load_dhall_file(&PathBuf::from(file_path), true)
}
pub fn run_test(base_path: &str, feature: Feature, expected: ExpectedResult) {
use self::{ExpectedResult, Feature};
- let mut source_pool = Vec::new();
match (feature, expected) {
(Feature::Parser, ExpectedResult::Success) => {
- let file_path: PathBuf = (base_path.to_owned() + "A.dhall").into();
- let _expr = load_dhall_file(&file_path, &mut source_pool, true)
+ let file_path = base_path.to_owned() + "A.dhall";
+ let _expr = read_dhall_file(&file_path)
.map_err(|e| println!("{}", e))
.unwrap();
// panic!("{:?}", _expr);
}
(Feature::Parser, ExpectedResult::Failure) => {
- let file_path: PathBuf = (base_path.to_owned() + ".dhall").into();
- let err = load_dhall_file(&file_path, &mut source_pool, true)
- .unwrap_err();
+ let file_path = base_path.to_owned() + ".dhall";
+ let err = read_dhall_file(&file_path).unwrap_err();
match err {
DhallError::ParseError(_) => {}
e => panic!("Expected parse error, got: {:?}", e),
@@ -109,14 +99,9 @@ pub fn run_test(base_path: &str, feature: Feature, expected: ExpectedResult) {
}
(Feature::Normalization, ExpectedResult::Success) => {
let expr_file_path = base_path.to_owned() + "A.dhall";
- let mut expr_buffer = String::new();
- let expr =
- read_dhall_file(&expr_file_path, &mut expr_buffer).unwrap();
let expected_file_path = base_path.to_owned() + "B.dhall";
- let mut expected_buffer = String::new();
- let expected =
- read_dhall_file(&expected_file_path, &mut expected_buffer)
- .unwrap();
+ let expr = read_dhall_file(&expr_file_path).unwrap();
+ let expected = read_dhall_file(&expected_file_path).unwrap();
assert_eq_!(
normalize::<_, _, X, _>(&expr),
diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs
index 72389c5..3b98b39 100644
--- a/dhall_core/src/core.rs
+++ b/dhall_core/src/core.rs
@@ -376,6 +376,16 @@ impl<'i, S: Clone, A: Clone> Expr<&'i str, S, A> {
}
}
+impl<L: StringLike, S: Clone, A: Clone> Expr<L, S, Expr<L, S, A>> {
+ pub fn squash_embed(&self) -> Expr<L, S, A>
+ {
+ match self {
+ Expr::Embed(e) => e.clone(),
+ e => e.map_shallow(|e| e.squash_embed(), |x| x.clone(), |_| unreachable!(), |x| x.clone())
+ }
+ }
+}
+
// There is a one-to-one correspondence between the formatters in this section
// and the grammar in grammar.lalrpop. Each formatter is named after the
// corresponding grammar rule and the relationship between formatters exactly matches
diff --git a/dhall_core/src/parser.rs b/dhall_core/src/parser.rs
index 9d0a88b..164d410 100644
--- a/dhall_core/src/parser.rs
+++ b/dhall_core/src/parser.rs
@@ -486,7 +486,9 @@ rule!(integer_literal_raw<core::Integer>;
}
);
-rule!(path<PathBuf>; captured_str!(s) => s.into());
+rule!(path<PathBuf>;
+ captured_str!(s) => (".".to_owned() + s).into()
+);
rule!(parent_path<(FilePrefix, PathBuf)>;
children!(p: path) => (FilePrefix::Parent, p)