diff options
Diffstat (limited to '')
-rw-r--r-- | dhall/src/lib.rs | 46 | ||||
-rw-r--r-- | dhall/tests/macros.rs | 139 |
2 files changed, 126 insertions, 59 deletions
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index 4e56264..4e183b4 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -6,3 +6,49 @@ mod normalize; pub use crate::normalize::*; pub mod imports; pub mod typecheck; + +use dhall_core::*; +use std::fs::File; +use std::io::Read; +use std::path::Path; +use std::fmt; + +#[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<'i, 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 = imports::resolve_imports(&expr); + Ok(expr) +} diff --git a/dhall/tests/macros.rs b/dhall/tests/macros.rs index 28be70b..ef518ed 100644 --- a/dhall/tests/macros.rs +++ b/dhall/tests/macros.rs @@ -1,79 +1,34 @@ #[macro_export] -macro_rules! include_test_str { - ($x:expr) => { - include_str!(concat!("../../dhall-lang/tests/", $x, ".dhall")) - }; -} - -#[macro_export] -macro_rules! include_test_strs_ab { - ($x:expr) => { - ( - include_test_str!(concat!($x, "A")), - include_test_str!(concat!($x, "B")), - ) - }; -} - -#[macro_export] -macro_rules! parse_str { - ($str:expr) => {{ - let pest_expr = parser::parse_expr(&$str) - .map_err(|e| println!("{}", e)) - .unwrap(); - // panic!("{:?}", pest_expr); - pest_expr - }}; -} - -#[macro_export] macro_rules! assert_eq_ { - ($left:expr, $right:expr) => ({ + ($left:expr, $right:expr) => {{ match (&$left, &$right) { (left_val, right_val) => { if !(*left_val == *right_val) { - panic!(r#"assertion failed: `(left == right)` - left: `{}`, - right: `{}`"#, left_val, right_val) - } - } - } - }); - ($left:expr, $right:expr,) => ({ - assert_eq!($left, $right) - }); - ($left:expr, $right:expr, $($arg:tt)+) => ({ - match (&($left), &($right)) { - (left_val, right_val) => { - if !(*left_val == *right_val) { - panic!(r#"assertion failed: `(left == right)` - left: `{:?}`, - right: `{:?}`: {}"#, left_val, right_val, - format_args!($($arg)+)) + panic!( + r#"assertion failed: `(left == right)` + left: `{}`, +right: `{}`"#, + left_val, right_val + ) } } } - }); + }}; } #[macro_export] macro_rules! run_spec_test { (normalization, $path:expr) => { - let (expr_str, expected_str) = include_test_strs_ab!($path); - let expr = parse_str!(expr_str); - let expected = parse_str!(expected_str); - assert_eq_!( - normalize::<_, X, _>(&expr), - normalize::<_, X, _>(&expected) - ); + let base_path = concat!("../dhall-lang/tests/", $path); + run_test(base_path, Feature::Normalization, ExpectedResult::Success); }; (parser, $path:expr) => { - let expr_str = include_test_str!(concat!($path, "A")); - parse_str!(expr_str); + let base_path = concat!("../dhall-lang/tests/", $path); + run_test(base_path, Feature::Parser, ExpectedResult::Success); }; (parser_failure, $path:expr) => { - let expr_str = include_test_str!($path); - parser::parse_expr(&expr_str).unwrap_err(); + let base_path = concat!("../dhall-lang/tests/", $path); + run_test(base_path, Feature::Parser, ExpectedResult::Failure); }; } @@ -85,10 +40,14 @@ macro_rules! make_spec_test { #[allow(unused_variables)] #[allow(unused_imports)] fn $name() { + use crate::macros::*; + use dhall::imports::resolve_imports; use dhall::*; use dhall_core::*; use std::thread; + // The parser stack overflows even on small files + // when compiled without optimizations thread::Builder::new() .stack_size(16 * 1024 * 1024) .spawn(move || { @@ -100,3 +59,65 @@ macro_rules! make_spec_test { } }; } + +use dhall::*; +use dhall_core::*; +use dhall_core::parser::*; +use std::fs::File; +use std::io::Read; +use std::path::PathBuf; + +pub enum Feature { + Parser, + Normalization, +} + +pub enum ExpectedResult { + Success, + Failure, +} + +pub fn read_dhall_file<'i>( + file_path: &str, + mut buffer: &'i mut String, +) -> Result<Box<Expr<'i, X, Import>>, ParseError> { + let mut file = File::open(&file_path).unwrap(); + file.read_to_string(&mut buffer).unwrap(); + parser::parse_expr(&*buffer) +} + +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) + .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(); + match err { + DhallError::ParseError(_) => {}, + e => panic!("Expected parse error, got: {:?}", e), + } + } + (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(); + + assert_eq_!( + normalize::<_, X, _>(&expr), + normalize::<_, X, _>(&expected) + ); + } + _ => unimplemented!(), + } +} |