From 09c93f4461c7f56a57396bab26f14d23bc3fe67c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 5 May 2019 19:29:53 +0200 Subject: Remove main --- dhall/src/main.rs | 93 ------------------------------------------------------- 1 file changed, 93 deletions(-) delete mode 100644 dhall/src/main.rs diff --git a/dhall/src/main.rs b/dhall/src/main.rs deleted file mode 100644 index e25a535..0000000 --- a/dhall/src/main.rs +++ /dev/null @@ -1,93 +0,0 @@ -// use std::error::Error; -// use std::io::{self, Read}; -// use term_painter::ToStyle; - -// const ERROR_STYLE: term_painter::Color = term_painter::Color::Red; -// const BOLD: term_painter::Attr = term_painter::Attr::Bold; - -// fn print_error(message: &str, source: &str, start: usize, end: usize) { -// let line_number = bytecount::count(source[..start].as_bytes(), b'\n'); -// let line_start = source[..start].rfind('\n').map(|i| i + 1).unwrap_or(0); -// let line_end = source[end..].find('\n').unwrap_or(0) + end; -// let context_prefix = &source[line_start..start]; -// let context_highlighted = &source[start..end]; -// let context_suffix = &source[end..line_end]; - -// let line_number_str = line_number.to_string(); -// let line_number_width = line_number_str.len(); - -// BOLD.with(|| { -// ERROR_STYLE.with(|| { -// print!("error: "); -// }); -// println!("{}", message); -// }); -// BOLD.with(|| { -// print!(" -->"); -// }); -// println!(" (stdin):{}:0", line_number); -// BOLD.with(|| { -// println!("{:w$} |", "", w = line_number_width); -// print!("{} |", line_number_str); -// }); -// print!(" {}", context_prefix); -// BOLD.with(|| { -// ERROR_STYLE.with(|| { -// print!("{}", context_highlighted); -// }); -// }); -// println!("{}", context_suffix); -// BOLD.with(|| { -// print!("{:w$} |", "", w = line_number_width); -// ERROR_STYLE.with(|| { -// println!( -// " {:so$}{:^>ew$}", -// "", -// "", -// so = source[line_start..start].chars().count(), -// ew = ::std::cmp::max(1, source[start..end].chars().count()) -// ); -// }); -// }); -// } - -fn main() { - // let mut buffer = String::new(); - // io::stdin().read_to_string(&mut buffer).unwrap(); - - // TODO: public API is too restricted for this - // let expr = match dhall::expr::Parsed::parse_str(&buffer) { - // Ok(expr) => expr, - // Err(e) => { - // print_error(&format!("Parse error {}", e), &buffer, 0, 0); - // return; - // } - // }; - - // let expr = expr.resolve().unwrap(); - - // let expr = match expr.typecheck() { - // Ok(expr) => expr, - // Err(e) => { - // // TODO: implement pretty type error printing - // // let explain = ::std::env::args().any(|s| s == "--explain"); - // // if !explain { - // // term_painter::Color::BrightBlack.with(|| { - // // println!("Use \"dhall --explain\" for detailed errors"); - // // }); - // // } - // // ERROR_STYLE.with(|| print!("Error: ")); - // // println!("{}", e.type_message.description()); - // // if explain { - // // println!("{}", e.type_message); - // // } - // // println!("{}", e.current); - // // // FIXME Print source position - // return; - // } - // }; - - // let expr = expr.normalize(); - - // println!("{}", expr); -} -- cgit v1.2.3 From 2075cba6d883278a534afd2d8fe8f0a5e9b2f0d0 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 6 May 2019 00:42:15 +0200 Subject: Merge TypedInternal and Typed --- dhall/src/expr.rs | 72 ++++++++++++++++------------------------ dhall/src/normalize.rs | 26 +++------------ dhall/src/traits/dynamic_type.rs | 2 +- dhall/src/typecheck.rs | 9 ----- 4 files changed, 34 insertions(+), 75 deletions(-) diff --git a/dhall/src/expr.rs b/dhall/src/expr.rs index 7dbbf1c..896753c 100644 --- a/dhall/src/expr.rs +++ b/dhall/src/expr.rs @@ -34,13 +34,10 @@ derive_other_traits!(Parsed); pub(crate) struct Resolved(pub(crate) SubExpr); derive_other_traits!(Resolved); -pub(crate) use self::typed::TypedInternal; +pub(crate) use self::typed::Typed; #[derive(Debug, Clone)] -pub(crate) struct Typed(pub(crate) TypedInternal); - -#[derive(Debug, Clone)] -pub(crate) struct Normalized(pub(crate) TypedInternal); +pub(crate) struct Normalized(pub(crate) Typed); impl std::cmp::PartialEq for Normalized { fn eq(&self, other: &Self) -> bool { @@ -57,7 +54,7 @@ impl std::fmt::Display for Normalized { } mod typed { - use super::{Type, Typed}; + use super::Type; use crate::normalize::{AlphaVar, Thunk, Value}; use crate::typecheck::{ TypeError, TypeInternal, TypeMessage, TypecheckContext, @@ -66,27 +63,27 @@ mod typed { use std::borrow::Cow; #[derive(Debug, Clone)] - pub(crate) enum TypedInternal { + pub(crate) enum Typed { // The `Sort` higher-kinded type doesn't have a type Sort, // Any other value, along with its type Value(Thunk, Option), } - impl TypedInternal { + impl Typed { pub(crate) fn from_thunk_and_type(th: Thunk, t: Type) -> Self { - TypedInternal::Value(th, Some(t)) + Typed::Value(th, Some(t)) } pub(crate) fn from_thunk_untyped(th: Thunk) -> Self { - TypedInternal::Value(th, None) + Typed::Value(th, None) } // TODO: Avoid cloning if possible pub(crate) fn to_value(&self) -> Value { match self { - TypedInternal::Value(th, _) => th.to_value(), - TypedInternal::Sort => Value::Const(Const::Sort), + Typed::Value(th, _) => th.to_value(), + Typed::Sort => Value::Const(Const::Sort), } } @@ -100,33 +97,29 @@ mod typed { pub(crate) fn to_thunk(&self) -> Thunk { match self { - TypedInternal::Value(th, _) => th.clone(), - TypedInternal::Sort => { - Thunk::from_value(Value::Const(Const::Sort)) - } + Typed::Value(th, _) => th.clone(), + Typed::Sort => Thunk::from_value(Value::Const(Const::Sort)), } } pub(crate) fn to_type(&self) -> Type { match self { - TypedInternal::Sort => Type(TypeInternal::Const(Const::Sort)), - TypedInternal::Value(th, _) => match &*th.as_value() { + Typed::Sort => Type(TypeInternal::Const(Const::Sort)), + Typed::Value(th, _) => match &*th.as_value() { Value::Const(c) => Type(TypeInternal::Const(*c)), - _ => { - Type(TypeInternal::Typed(Box::new(Typed(self.clone())))) - } + _ => Type(TypeInternal::Typed(Box::new(self.clone()))), }, } } pub(crate) fn get_type(&self) -> Result, TypeError> { match self { - TypedInternal::Value(_, Some(t)) => Ok(Cow::Borrowed(t)), - TypedInternal::Value(_, None) => Err(TypeError::new( + Typed::Value(_, Some(t)) => Ok(Cow::Borrowed(t)), + Typed::Value(_, None) => Err(TypeError::new( &TypecheckContext::new(), TypeMessage::Untyped, )), - TypedInternal::Sort => Err(TypeError::new( + Typed::Sort => Err(TypeError::new( &TypecheckContext::new(), TypeMessage::Sort, )), @@ -135,32 +128,35 @@ mod typed { pub(crate) fn shift(&self, delta: isize, var: &AlphaVar) -> Self { match self { - TypedInternal::Value(th, t) => TypedInternal::Value( + Typed::Value(th, t) => Typed::Value( th.shift(delta, var), t.as_ref().map(|x| x.shift(delta, var)), ), - TypedInternal::Sort => TypedInternal::Sort, + Typed::Sort => Typed::Sort, } } pub(crate) fn subst_shift(&self, var: &AlphaVar, val: &Typed) -> Self { match self { - TypedInternal::Value(th, t) => TypedInternal::Value( + Typed::Value(th, t) => Typed::Value( th.subst_shift(var, val), t.as_ref().map(|x| x.subst_shift(var, val)), ), - TypedInternal::Sort => TypedInternal::Sort, + Typed::Sort => Typed::Sort, } } + pub(crate) fn const_sort() -> Self { + Typed::Sort + } } - impl std::cmp::PartialEq for TypedInternal { + impl std::cmp::PartialEq for Typed { fn eq(&self, other: &Self) -> bool { self.to_value() == other.to_value() } } - impl std::cmp::Eq for TypedInternal {} + impl std::cmp::Eq for Typed {} } /// A Dhall expression representing a simple type. @@ -208,13 +204,13 @@ impl From> for SimpleType { #[doc(hidden)] impl From for Typed { fn from(x: Normalized) -> Typed { - Typed(x.0) + x.0 } } impl Normalized { pub(crate) fn from_thunk_and_type(th: Thunk, t: Type) -> Self { - Normalized(TypedInternal::from_thunk_and_type(th, t)) + Normalized(Typed::from_thunk_and_type(th, t)) } pub(crate) fn to_expr(&self) -> SubExpr { self.0.to_expr() @@ -230,15 +226,3 @@ impl Normalized { self.0.to_thunk() } } - -impl Typed { - pub(crate) fn from_thunk_and_type(th: Thunk, t: Type) -> Self { - Typed(TypedInternal::from_thunk_and_type(th, t)) - } - pub(crate) fn from_thunk_untyped(th: Thunk) -> Self { - Typed(TypedInternal::from_thunk_untyped(th)) - } - pub(crate) fn const_sort() -> Self { - Typed(TypedInternal::Sort) - } -} diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs index 35ab45d..1d306bc 100644 --- a/dhall/src/normalize.rs +++ b/dhall/src/normalize.rs @@ -9,7 +9,7 @@ use dhall_syntax::{ Natural, Span, SubExpr, V, X, }; -use crate::expr::{Normalized, Type, Typed, TypedInternal}; +use crate::expr::{Normalized, Type, Typed}; type InputSubExpr = SubExpr; type OutputSubExpr = SubExpr; @@ -25,29 +25,13 @@ impl Typed { /// leave ill-typed sub-expressions unevaluated. /// pub fn normalize(self) -> Normalized { - match &self.0 { - TypedInternal::Sort => {} - TypedInternal::Value(thunk, _) => { + match &self { + Typed::Sort => {} + Typed::Value(thunk, _) => { thunk.normalize_nf(); } } - Normalized(self.0) - } - - pub(crate) fn shift(&self, delta: isize, var: &AlphaVar) -> Self { - Typed(self.0.shift(delta, var)) - } - - pub(crate) fn subst_shift(&self, var: &AlphaVar, val: &Typed) -> Self { - Typed(self.0.subst_shift(var, val)) - } - - pub(crate) fn to_value(&self) -> Value { - self.0.to_value() - } - - pub(crate) fn to_thunk(&self) -> Thunk { - self.0.to_thunk() + Normalized(self) } } diff --git a/dhall/src/traits/dynamic_type.rs b/dhall/src/traits/dynamic_type.rs index 858642e..4c8e1fd 100644 --- a/dhall/src/traits/dynamic_type.rs +++ b/dhall/src/traits/dynamic_type.rs @@ -30,6 +30,6 @@ impl DynamicType for Normalized { impl DynamicType for Typed { fn get_type(&self) -> Result, TypeError> { - self.0.get_type() + self.get_type() } } diff --git a/dhall/src/typecheck.rs b/dhall/src/typecheck.rs index 8d6b6eb..4dde883 100644 --- a/dhall/src/typecheck.rs +++ b/dhall/src/typecheck.rs @@ -35,15 +35,6 @@ impl Resolved { } } -impl Typed { - fn to_type(&self) -> Type { - match &self.to_value() { - Value::Const(c) => Type(TypeInternal::Const(*c)), - _ => Type(TypeInternal::Typed(Box::new(self.clone()))), - } - } -} - impl Normalized { fn shift(&self, delta: isize, var: &AlphaVar) -> Self { Normalized(self.0.shift(delta, var)) -- cgit v1.2.3 From 423fdeebe9247b16744fae4b50df415bbd08be04 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 6 May 2019 22:09:55 +0200 Subject: Reorganize dhall into a phase structure --- dhall/src/binary.rs | 363 -------- dhall/src/error.rs | 38 +- dhall/src/expr.rs | 228 ----- dhall/src/imports.rs | 170 ---- dhall/src/lib.rs | 11 +- dhall/src/normalize.rs | 1909 -------------------------------------- dhall/src/parser.rs | 6 - dhall/src/phase/binary.rs | 363 ++++++++ dhall/src/phase/mod.rs | 389 ++++++++ dhall/src/phase/normalize.rs | 1888 +++++++++++++++++++++++++++++++++++++ dhall/src/phase/parse.rs | 38 + dhall/src/phase/resolve.rs | 139 +++ dhall/src/phase/typecheck.rs | 1276 +++++++++++++++++++++++++ dhall/src/serde.rs | 2 +- dhall/src/tests.rs | 2 +- dhall/src/traits/deserialize.rs | 2 +- dhall/src/traits/dynamic_type.rs | 7 +- dhall/src/traits/static_type.rs | 6 +- dhall/src/typecheck.rs | 1393 --------------------------- 19 files changed, 4126 insertions(+), 4104 deletions(-) delete mode 100644 dhall/src/binary.rs delete mode 100644 dhall/src/expr.rs delete mode 100644 dhall/src/imports.rs delete mode 100644 dhall/src/normalize.rs delete mode 100644 dhall/src/parser.rs create mode 100644 dhall/src/phase/binary.rs create mode 100644 dhall/src/phase/mod.rs create mode 100644 dhall/src/phase/normalize.rs create mode 100644 dhall/src/phase/parse.rs create mode 100644 dhall/src/phase/resolve.rs create mode 100644 dhall/src/phase/typecheck.rs delete mode 100644 dhall/src/typecheck.rs diff --git a/dhall/src/binary.rs b/dhall/src/binary.rs deleted file mode 100644 index 9c31d4c..0000000 --- a/dhall/src/binary.rs +++ /dev/null @@ -1,363 +0,0 @@ -use dhall_syntax::*; -use itertools::*; -use serde_cbor::value::value as cbor; - -type ParsedExpr = SubExpr; - -#[derive(Debug)] -pub enum DecodeError { - CBORError(serde_cbor::error::Error), - WrongFormatError(String), -} - -pub fn decode(data: &[u8]) -> Result { - match serde_cbor::de::from_slice(data) { - Ok(v) => cbor_value_to_dhall(&v), - Err(e) => Err(DecodeError::CBORError(e)), - } -} - -fn cbor_value_to_dhall(data: &cbor::Value) -> Result { - use cbor::Value::*; - use dhall_syntax::{BinOp, Builtin, Const}; - use ExprF::*; - Ok(rc(match data { - String(s) => match Builtin::parse(s) { - Some(b) => ExprF::Builtin(b), - None => match s.as_str() { - "True" => BoolLit(true), - "False" => BoolLit(false), - "Type" => Const(Const::Type), - "Kind" => Const(Const::Kind), - "Sort" => Const(Const::Sort), - _ => Err(DecodeError::WrongFormatError("builtin".to_owned()))?, - }, - }, - U64(n) => Var(V(Label::from("_"), *n as usize)), - F64(x) => DoubleLit((*x).into()), - Bool(b) => BoolLit(*b), - Array(vec) => match vec.as_slice() { - [String(l), U64(n)] => { - let l = Label::from(l.as_str()); - Var(V(l, *n as usize)) - } - [U64(0), f, args..] => { - let mut f = cbor_value_to_dhall(&f)?; - for a in args { - let a = cbor_value_to_dhall(&a)?; - f = rc(App(f, a)) - } - return Ok(f); - } - [U64(1), x, y] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - Lam(Label::from("_"), x, y) - } - [U64(1), String(l), x, y] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - let l = Label::from(l.as_str()); - Lam(l, x, y) - } - [U64(2), x, y] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - Pi(Label::from("_"), x, y) - } - [U64(2), String(l), x, y] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - let l = Label::from(l.as_str()); - Pi(l, x, y) - } - [U64(3), U64(n), x, y] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - use BinOp::*; - let op = match n { - 0 => BoolOr, - 1 => BoolAnd, - 2 => BoolEQ, - 3 => BoolNE, - 4 => NaturalPlus, - 5 => NaturalTimes, - 6 => TextAppend, - 7 => ListAppend, - 8 => Combine, - 9 => Prefer, - 10 => CombineTypes, - 11 => ImportAlt, - _ => { - Err(DecodeError::WrongFormatError("binop".to_owned()))? - } - }; - BinOp(op, x, y) - } - [U64(4), t] => { - let t = cbor_value_to_dhall(&t)?; - EmptyListLit(t) - } - [U64(4), Null, rest..] => { - let rest = rest - .iter() - .map(cbor_value_to_dhall) - .collect::, _>>()?; - NEListLit(rest) - } - [U64(5), t] => { - let t = cbor_value_to_dhall(&t)?; - OldOptionalLit(None, t) - } - [U64(5), Null, x] => { - let x = cbor_value_to_dhall(&x)?; - SomeLit(x) - } - [U64(5), t, x] => { - let x = cbor_value_to_dhall(&x)?; - let t = cbor_value_to_dhall(&t)?; - OldOptionalLit(Some(x), t) - } - [U64(6), x, y] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - Merge(x, y, None) - } - [U64(6), x, y, z] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - let z = cbor_value_to_dhall(&z)?; - Merge(x, y, Some(z)) - } - [U64(7), Object(map)] => { - let map = cbor_map_to_dhall_map(map)?; - RecordType(map) - } - [U64(8), Object(map)] => { - let map = cbor_map_to_dhall_map(map)?; - RecordLit(map) - } - [U64(9), x, String(l)] => { - let x = cbor_value_to_dhall(&x)?; - let l = Label::from(l.as_str()); - Field(x, l) - } - [U64(11), Object(map)] => { - let map = cbor_map_to_dhall_opt_map(map)?; - UnionType(map) - } - [U64(12), String(l), x, Object(map)] => { - let map = cbor_map_to_dhall_opt_map(map)?; - let x = cbor_value_to_dhall(&x)?; - let l = Label::from(l.as_str()); - UnionLit(l, x, map) - } - [U64(14), x, y, z] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - let z = cbor_value_to_dhall(&z)?; - BoolIf(x, y, z) - } - [U64(15), U64(x)] => NaturalLit(*x as Natural), - [U64(16), U64(x)] => IntegerLit(*x as Integer), - [U64(16), I64(x)] => IntegerLit(*x as Integer), - [U64(18), String(first), rest..] => { - TextLit(InterpolatedText::from(( - first.clone(), - rest.iter() - .tuples() - .map(|(x, y)| { - let x = cbor_value_to_dhall(&x)?; - let y = match y { - String(s) => s.clone(), - _ => Err(DecodeError::WrongFormatError( - "text".to_owned(), - ))?, - }; - Ok((x, y)) - }) - .collect::>()?, - ))) - } - [U64(24), hash, U64(mode), U64(scheme), rest..] => { - let mode = match mode { - 1 => ImportMode::RawText, - _ => ImportMode::Code, - }; - let hash = match hash { - Null => None, - Array(vec) => match vec.as_slice() { - [String(protocol), String(hash)] => Some(Hash { - protocol: protocol.clone(), - hash: hash.clone(), - }), - _ => Err(DecodeError::WrongFormatError( - "import/hash".to_owned(), - ))?, - }, - _ => Err(DecodeError::WrongFormatError( - "import/hash".to_owned(), - ))?, - }; - let mut rest = rest.iter(); - let location = match scheme { - 0 | 1 => { - let scheme = match scheme { - 0 => Scheme::HTTP, - _ => Scheme::HTTPS, - }; - let headers = match rest.next() { - Some(Null) => None, - Some(x) => { - match cbor_value_to_dhall(&x)?.as_ref() { - Embed(import) => Some(Box::new( - import.location_hashed.clone(), - )), - _ => Err(DecodeError::WrongFormatError( - "import/remote/headers".to_owned(), - ))?, - } - } - _ => Err(DecodeError::WrongFormatError( - "import/remote/headers".to_owned(), - ))?, - }; - let authority = match rest.next() { - Some(String(s)) => s.to_owned(), - _ => Err(DecodeError::WrongFormatError( - "import/remote/authority".to_owned(), - ))?, - }; - let query = match rest.next_back() { - Some(Null) => None, - Some(String(s)) => Some(s.to_owned()), - _ => Err(DecodeError::WrongFormatError( - "import/remote/query".to_owned(), - ))?, - }; - let path = rest - .map(|s| { - s.as_string().ok_or_else(|| { - DecodeError::WrongFormatError( - "import/remote/path".to_owned(), - ) - }) - }) - .collect::>()?; - ImportLocation::Remote(URL { - scheme, - authority, - path, - query, - headers, - }) - } - 2 | 3 | 4 | 5 => { - let prefix = match scheme { - 2 => FilePrefix::Absolute, - 3 => FilePrefix::Here, - 4 => FilePrefix::Parent, - 5 => FilePrefix::Home, - _ => Err(DecodeError::WrongFormatError( - "import/local/prefix".to_owned(), - ))?, - }; - let path = rest - .map(|s| { - s.as_string().ok_or_else(|| { - DecodeError::WrongFormatError( - "import/local/path".to_owned(), - ) - }) - }) - .collect::>()?; - ImportLocation::Local(prefix, path) - } - 6 => { - let env = match rest.next() { - Some(String(s)) => s.to_owned(), - _ => Err(DecodeError::WrongFormatError( - "import/env".to_owned(), - ))?, - }; - ImportLocation::Env(env) - } - 7 => ImportLocation::Missing, - _ => Err(DecodeError::WrongFormatError( - "import/type".to_owned(), - ))?, - }; - Embed(Import { - mode, - location_hashed: ImportHashed { hash, location }, - }) - } - [U64(25), bindings..] => { - let mut tuples = bindings.iter().tuples(); - let bindings = (&mut tuples) - .map(|(x, t, v)| { - let x = x.as_string().ok_or_else(|| { - DecodeError::WrongFormatError( - "let/label".to_owned(), - ) - })?; - let x = Label::from(x.as_str()); - let t = match t { - Null => None, - t => Some(cbor_value_to_dhall(&t)?), - }; - let v = cbor_value_to_dhall(&v)?; - Ok((x, t, v)) - }) - .collect::, _>>()?; - let expr = tuples.into_buffer().next().ok_or_else(|| { - DecodeError::WrongFormatError("let/expr".to_owned()) - })?; - let expr = cbor_value_to_dhall(expr)?; - return Ok(bindings - .into_iter() - .rev() - .fold(expr, |acc, (x, t, v)| rc(Let(x, t, v, acc)))); - } - [U64(26), x, y] => { - let x = cbor_value_to_dhall(&x)?; - let y = cbor_value_to_dhall(&y)?; - Annot(x, y) - } - _ => Err(DecodeError::WrongFormatError(format!("{:?}", data)))?, - }, - _ => Err(DecodeError::WrongFormatError(format!("{:?}", data)))?, - })) -} - -fn cbor_map_to_dhall_map( - map: &std::collections::BTreeMap, -) -> Result, DecodeError> { - map.iter() - .map(|(k, v)| -> Result<(_, _), _> { - let k = k.as_string().ok_or_else(|| { - DecodeError::WrongFormatError("map/key".to_owned()) - })?; - let v = cbor_value_to_dhall(v)?; - Ok((Label::from(k.as_ref()), v)) - }) - .collect::>() -} - -fn cbor_map_to_dhall_opt_map( - map: &std::collections::BTreeMap, -) -> Result>, DecodeError> -{ - map.iter() - .map(|(k, v)| -> Result<(_, _), _> { - let k = k.as_string().ok_or_else(|| { - DecodeError::WrongFormatError("map/key".to_owned()) - })?; - let v = match v { - cbor::Value::Null => None, - _ => Some(cbor_value_to_dhall(v)?), - }; - Ok((Label::from(k.as_ref()), v)) - }) - .collect::>() -} diff --git a/dhall/src/error.rs b/dhall/src/error.rs index 6ed0bfb..8497a91 100644 --- a/dhall/src/error.rs +++ b/dhall/src/error.rs @@ -1,13 +1,21 @@ +use std::io::Error as IOError; + +use dhall_syntax::ParseError; + +use crate::phase::binary::DecodeError; +use crate::phase::resolve::ImportError; +use crate::phase::typecheck::TypeError; + pub type Result = std::result::Result; #[derive(Debug)] #[non_exhaustive] pub enum Error { - IO(std::io::Error), - Parse(dhall_syntax::ParseError), - Decode(crate::binary::DecodeError), - Resolve(crate::imports::ImportError), - Typecheck(crate::typecheck::TypeError), + IO(IOError), + Parse(ParseError), + Decode(DecodeError), + Resolve(ImportError), + Typecheck(TypeError), Deserialize(String), } @@ -25,28 +33,28 @@ impl std::fmt::Display for Error { } impl std::error::Error for Error {} -impl From for Error { - fn from(err: std::io::Error) -> Error { +impl From for Error { + fn from(err: IOError) -> Error { Error::IO(err) } } -impl From for Error { - fn from(err: dhall_syntax::ParseError) -> Error { +impl From for Error { + fn from(err: ParseError) -> Error { Error::Parse(err) } } -impl From for Error { - fn from(err: crate::binary::DecodeError) -> Error { +impl From for Error { + fn from(err: DecodeError) -> Error { Error::Decode(err) } } -impl From for Error { - fn from(err: crate::imports::ImportError) -> Error { +impl From for Error { + fn from(err: ImportError) -> Error { Error::Resolve(err) } } -impl From for Error { - fn from(err: crate::typecheck::TypeError) -> Error { +impl From for Error { + fn from(err: TypeError) -> Error { Error::Typecheck(err) } } diff --git a/dhall/src/expr.rs b/dhall/src/expr.rs deleted file mode 100644 index 896753c..0000000 --- a/dhall/src/expr.rs +++ /dev/null @@ -1,228 +0,0 @@ -use crate::imports::ImportRoot; -use crate::normalize::{Thunk, Value}; -use dhall_syntax::*; - -macro_rules! derive_other_traits { - ($ty:ident) => { - impl std::cmp::PartialEq for $ty { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - - impl std::cmp::Eq for $ty {} - - impl std::fmt::Display for $ty { - fn fmt( - &self, - f: &mut std::fmt::Formatter, - ) -> Result<(), std::fmt::Error> { - self.0.fmt(f) - } - } - }; -} - -#[derive(Debug, Clone)] -pub(crate) struct Parsed( - pub(crate) SubExpr, - pub(crate) ImportRoot, -); -derive_other_traits!(Parsed); - -#[derive(Debug, Clone)] -pub(crate) struct Resolved(pub(crate) SubExpr); -derive_other_traits!(Resolved); - -pub(crate) use self::typed::Typed; - -#[derive(Debug, Clone)] -pub(crate) struct Normalized(pub(crate) Typed); - -impl std::cmp::PartialEq for Normalized { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} - -impl std::cmp::Eq for Normalized {} - -impl std::fmt::Display for Normalized { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - self.to_expr().fmt(f) - } -} - -mod typed { - use super::Type; - use crate::normalize::{AlphaVar, Thunk, Value}; - use crate::typecheck::{ - TypeError, TypeInternal, TypeMessage, TypecheckContext, - }; - use dhall_syntax::{Const, SubExpr, X}; - use std::borrow::Cow; - - #[derive(Debug, Clone)] - pub(crate) enum Typed { - // The `Sort` higher-kinded type doesn't have a type - Sort, - // Any other value, along with its type - Value(Thunk, Option), - } - - impl Typed { - pub(crate) fn from_thunk_and_type(th: Thunk, t: Type) -> Self { - Typed::Value(th, Some(t)) - } - - pub(crate) fn from_thunk_untyped(th: Thunk) -> Self { - Typed::Value(th, None) - } - - // TODO: Avoid cloning if possible - pub(crate) fn to_value(&self) -> Value { - match self { - Typed::Value(th, _) => th.to_value(), - Typed::Sort => Value::Const(Const::Sort), - } - } - - pub(crate) fn to_expr(&self) -> SubExpr { - self.to_value().normalize_to_expr() - } - - pub(crate) fn to_expr_alpha(&self) -> SubExpr { - self.to_value().normalize_to_expr_maybe_alpha(true) - } - - pub(crate) fn to_thunk(&self) -> Thunk { - match self { - Typed::Value(th, _) => th.clone(), - Typed::Sort => Thunk::from_value(Value::Const(Const::Sort)), - } - } - - pub(crate) fn to_type(&self) -> Type { - match self { - Typed::Sort => Type(TypeInternal::Const(Const::Sort)), - Typed::Value(th, _) => match &*th.as_value() { - Value::Const(c) => Type(TypeInternal::Const(*c)), - _ => Type(TypeInternal::Typed(Box::new(self.clone()))), - }, - } - } - - pub(crate) fn get_type(&self) -> Result, TypeError> { - match self { - Typed::Value(_, Some(t)) => Ok(Cow::Borrowed(t)), - Typed::Value(_, None) => Err(TypeError::new( - &TypecheckContext::new(), - TypeMessage::Untyped, - )), - Typed::Sort => Err(TypeError::new( - &TypecheckContext::new(), - TypeMessage::Sort, - )), - } - } - - pub(crate) fn shift(&self, delta: isize, var: &AlphaVar) -> Self { - match self { - Typed::Value(th, t) => Typed::Value( - th.shift(delta, var), - t.as_ref().map(|x| x.shift(delta, var)), - ), - Typed::Sort => Typed::Sort, - } - } - - pub(crate) fn subst_shift(&self, var: &AlphaVar, val: &Typed) -> Self { - match self { - Typed::Value(th, t) => Typed::Value( - th.subst_shift(var, val), - t.as_ref().map(|x| x.subst_shift(var, val)), - ), - Typed::Sort => Typed::Sort, - } - } - pub(crate) fn const_sort() -> Self { - Typed::Sort - } - } - - impl std::cmp::PartialEq for Typed { - fn eq(&self, other: &Self) -> bool { - self.to_value() == other.to_value() - } - } - - impl std::cmp::Eq for Typed {} -} - -/// A Dhall expression representing a simple type. -/// -/// This captures what is usually simply called a "type", like -/// `Bool`, `{ x: Integer }` or `Natural -> Text`. -/// -/// For a more general notion of "type", see [Type]. -#[derive(Debug, Clone)] -pub struct SimpleType(pub(crate) SubExpr); -derive_other_traits!(SimpleType); - -pub(crate) use crate::typecheck::TypeInternal; - -/// A Dhall expression representing a (possibly higher-kinded) type. -/// -/// This includes [SimpleType]s but also higher-kinded expressions like -/// `Type`, `Kind` and `{ x: Type }`. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Type(pub(crate) TypeInternal); - -impl std::fmt::Display for Type { - fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - self.to_normalized().fmt(f) - } -} - -// Exposed for the macros -#[doc(hidden)] -impl From for SubExpr { - fn from(x: SimpleType) -> SubExpr { - x.0 - } -} - -// Exposed for the macros -#[doc(hidden)] -impl From> for SimpleType { - fn from(x: SubExpr) -> SimpleType { - SimpleType(x) - } -} - -// Exposed for the macros -#[doc(hidden)] -impl From for Typed { - fn from(x: Normalized) -> Typed { - x.0 - } -} - -impl Normalized { - pub(crate) fn from_thunk_and_type(th: Thunk, t: Type) -> Self { - Normalized(Typed::from_thunk_and_type(th, t)) - } - pub(crate) fn to_expr(&self) -> SubExpr { - self.0.to_expr() - } - #[allow(dead_code)] - pub(crate) fn to_expr_alpha(&self) -> SubExpr { - self.0.to_expr_alpha() - } - pub(crate) fn to_value(&self) -> Value { - self.0.to_value() - } - pub(crate) fn to_thunk(&self) -> Thunk { - self.0.to_thunk() - } -} diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs deleted file mode 100644 index 87642a2..0000000 --- a/dhall/src/imports.rs +++ /dev/null @@ -1,170 +0,0 @@ -use crate::error::Error; -use crate::expr::*; -use dhall_syntax::*; -use std::collections::HashMap; -use std::fs::File; -use std::io::Read; -use std::path::Path; -use std::path::PathBuf; - -#[derive(Debug)] -pub enum ImportError { - Recursive(Import, Box), - UnexpectedImport(Import), - ImportCycle(ImportStack, Import), -} - -/// A root from which to resolve relative imports. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ImportRoot { - LocalDir(PathBuf), -} - -type ImportCache = HashMap; - -type ImportStack = Vec; - -fn resolve_import( - import: &Import, - root: &ImportRoot, - import_cache: &mut ImportCache, - import_stack: &ImportStack, -) -> Result { - use self::ImportRoot::*; - use dhall_syntax::FilePrefix::*; - use dhall_syntax::ImportLocation::*; - let cwd = match root { - LocalDir(cwd) => cwd, - }; - match &import.location_hashed.location { - Local(prefix, path) => { - let path = match prefix { - // TODO: fail gracefully - Parent => cwd.parent().unwrap().join(path), - Here => cwd.join(path), - _ => unimplemented!("{:?}", import), - }; - Ok(load_import(&path, import_cache, import_stack).map_err(|e| { - ImportError::Recursive(import.clone(), Box::new(e)) - })?) - } - _ => unimplemented!("{:?}", import), - } -} - -fn load_import( - f: &Path, - import_cache: &mut ImportCache, - import_stack: &ImportStack, -) -> Result { - Ok( - do_resolve_expr(Parsed::parse_file(f)?, import_cache, import_stack)? - .typecheck()? - .normalize(), - ) -} - -fn do_resolve_expr( - Parsed(expr, root): Parsed, - import_cache: &mut ImportCache, - import_stack: &ImportStack, -) -> Result { - let resolve = |import: &Import| -> Result { - if import_stack.contains(import) { - return Err(ImportError::ImportCycle( - import_stack.clone(), - import.clone(), - )); - } - match import_cache.get(import) { - Some(expr) => Ok(expr.clone()), - None => { - // Copy the import stack and push the current import - let mut import_stack = import_stack.clone(); - import_stack.push(import.clone()); - - // Resolve the import recursively - let expr = - resolve_import(import, &root, import_cache, &import_stack)?; - - // Add the import to the cache - import_cache.insert(import.clone(), expr.clone()); - Ok(expr) - } - } - }; - let expr = expr.traverse_embed(resolve)?; - Ok(Resolved(expr)) -} - -fn skip_resolve_expr( - Parsed(expr, _root): Parsed, -) -> Result { - let resolve = |import: &Import| -> Result { - Err(ImportError::UnexpectedImport(import.clone())) - }; - let expr = expr.traverse_embed(resolve)?; - Ok(Resolved(expr)) -} - -impl Parsed { - pub fn parse_file(f: &Path) -> Result { - 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.unnote().note_absurd(), root)) - } - - pub fn parse_str(s: &str) -> Result { - let expr = parse_expr(s)?; - let root = ImportRoot::LocalDir(std::env::current_dir()?); - Ok(Parsed(expr, root)) - } - - #[allow(dead_code)] - pub fn parse_binary_file(f: &Path) -> Result { - let mut buffer = Vec::new(); - File::open(f)?.read_to_end(&mut buffer)?; - let expr = crate::binary::decode(&buffer)?; - let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned()); - Ok(Parsed(expr.note_absurd(), root)) - } - - pub fn resolve(self) -> Result { - crate::imports::do_resolve_expr(self, &mut HashMap::new(), &Vec::new()) - } - - #[allow(dead_code)] - pub fn skip_resolve(self) -> Result { - crate::imports::skip_resolve_expr(self) - } -} - -#[cfg(test)] -mod spec_tests { - #![rustfmt::skip] - - macro_rules! import_success { - ($name:ident, $path:expr) => { - make_spec_test!(Import, Success, $name, $path); - }; - } - - // macro_rules! import_failure { - // ($name:ident, $path:expr) => { - // make_spec_test!(Import, Failure, $name, $path); - // }; - // } - - // import_success!(success_alternativeEnvNatural, "alternativeEnvNatural"); - // import_success!(success_alternativeEnvSimple, "alternativeEnvSimple"); - // import_success!(success_alternativeNatural, "alternativeNatural"); - // import_success!(success_asText, "asText"); - import_success!(success_fieldOrder, "fieldOrder"); - // import_failure!(failure_alternativeEnv, "alternativeEnv"); - // import_failure!(failure_alternativeEnvMissing, "alternativeEnvMissing"); - // import_failure!(failure_cycle, "cycle"); - // import_failure!(failure_missing, "missing"); - // import_failure!(failure_referentiallyInsane, "referentiallyInsane"); -} diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index a531f64..ec110f7 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -123,18 +123,11 @@ #[macro_use] mod tests; -#[cfg(test)] -mod parser; - -mod binary; /// When manipulating Dhall expressions goes wrong. pub mod error; -pub mod expr; -mod imports; -mod normalize; +mod phase; mod serde; mod traits; -mod typecheck; /// Deserialization of Dhall expressions into Rust pub mod de { @@ -153,7 +146,7 @@ pub mod de { /// expression has that type. pub fn from_str<'a, T: Deserialize<'a>>( s: &'a str, - ty: Option<&crate::expr::Type>, + ty: Option<&crate::phase::Type>, ) -> crate::error::Result { T::from_str(s, ty) } diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs deleted file mode 100644 index 1d306bc..0000000 --- a/dhall/src/normalize.rs +++ /dev/null @@ -1,1909 +0,0 @@ -#![allow(non_snake_case)] -use std::collections::BTreeMap; -use std::rc::Rc; - -use dhall_proc_macros as dhall; -use dhall_syntax::context::Context; -use dhall_syntax::{ - rc, BinOp, Builtin, Const, ExprF, Integer, InterpolatedTextContents, Label, - Natural, Span, SubExpr, V, X, -}; - -use crate::expr::{Normalized, Type, Typed}; - -type InputSubExpr = SubExpr; -type OutputSubExpr = SubExpr; - -impl Typed { - /// Reduce an expression to its normal form, performing beta reduction - /// - /// `normalize` does not type-check the expression. You may want to type-check - /// expressions before normalizing them since normalization can convert an - /// ill-typed expression into a well-typed expression. - /// - /// However, `normalize` will not fail if the expression is ill-typed and will - /// leave ill-typed sub-expressions unevaluated. - /// - pub fn normalize(self) -> Normalized { - match &self { - Typed::Sort => {} - Typed::Value(thunk, _) => { - thunk.normalize_nf(); - } - } - Normalized(self) - } -} - -/// Stores a pair of variables: a normal one and if relevant one -/// that corresponds to the alpha-normalized version of the first one. -#[derive(Debug, Clone, Eq)] -pub(crate) struct AlphaVar { - normal: V