From 505e6a34cc5aadac1831d31ef64b94b61c2ace13 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 9 Mar 2019 00:42:46 +0100 Subject: First import works ! --- dhall/src/imports.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++--- dhall/src/lib.rs | 47 +------------------------- dhall/src/main.rs | 3 +- dhall/tests/macros.rs | 31 +++++------------ dhall_core/src/core.rs | 10 ++++++ dhall_core/src/parser.rs | 4 ++- 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( +pub fn panic_imports( expr: &Expr, ) -> Expr { - 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, 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 for DhallError { + fn from(e: parser::ParseError) -> Self { + DhallError::ParseError(e) + } +} +impl From 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, 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 { + 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 for DhallError { - fn from(e: parser::ParseError) -> Self { - DhallError::ParseError(e) - } -} -impl From 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, - _resolve_imports: bool, -) -> Result, 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 = imports::resolve_imports(&expr.take_ownership_of_labels()); + let expr: Expr = + 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>, 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, 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 Expr> { + pub fn squash_embed(&self) -> Expr + { + 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; } ); -rule!(path; captured_str!(s) => s.into()); +rule!(path; + captured_str!(s) => (".".to_owned() + s).into() +); rule!(parent_path<(FilePrefix, PathBuf)>; children!(p: path) => (FilePrefix::Parent, p) -- cgit v1.2.3