From a0ac45ccc6bd0168f05626fdf1886560006fcda1 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 9 Mar 2019 15:36:39 +0100 Subject: Use new Label type everywhere --- dhall/src/imports.rs | 11 ++--- dhall/src/main.rs | 5 +- dhall/src/normalize.rs | 20 ++++---- dhall/src/typecheck.rs | 110 +++++++++++++++++------------------------ dhall/tests/macros.rs | 6 +-- dhall_core/src/core.rs | 119 ++++++++++++++------------------------------- dhall_generator/src/lib.rs | 16 +++--- 7 files changed, 109 insertions(+), 178 deletions(-) diff --git a/dhall/src/imports.rs b/dhall/src/imports.rs index d9f0b33..3b8ba6d 100644 --- a/dhall/src/imports.rs +++ b/dhall/src/imports.rs @@ -1,5 +1,5 @@ // use dhall_core::{Expr, FilePrefix, Import, ImportLocation, ImportMode, X}; -use dhall_core::{Expr, Import, StringLike, X}; +use dhall_core::{Expr, Import, X}; // use std::path::Path; use dhall_core::*; use std::fmt; @@ -8,7 +8,7 @@ use std::io::Read; use std::path::Path; use std::path::PathBuf; -pub fn panic_imports( +pub fn panic_imports( expr: &Expr, ) -> Expr { let no_import = |i: &Import| -> X { panic!("ahhh import: {:?}", i) }; @@ -24,7 +24,7 @@ pub enum ImportRoot { fn resolve_import( import: &Import, root: &ImportRoot, -) -> Result, DhallError> { +) -> Result, DhallError> { use self::ImportRoot::*; use dhall_core::FilePrefix::*; use dhall_core::ImportLocation::*; @@ -71,14 +71,13 @@ impl fmt::Display for DhallError { pub fn load_dhall_file( f: &Path, resolve_imports: bool, -) -> Result, DhallError> { +) -> Result, DhallError> { let mut buffer = String::new(); File::open(f)?.read_to_string(&mut buffer)?; let expr = parser::parse_expr(&*buffer)?; - let expr = expr.map_label(&|l| String::from(l.clone())); let expr = if resolve_imports { let root = ImportRoot::LocalDir(f.parent().unwrap().to_owned()); - let resolve = |import: &Import| -> Expr { + let resolve = |import: &Import| -> Expr { resolve_import(import, &root).unwrap() }; let expr = expr.map_embed(&resolve).squash_embed(); diff --git a/dhall/src/main.rs b/dhall/src/main.rs index db69a46..349af3d 100644 --- a/dhall/src/main.rs +++ b/dhall/src/main.rs @@ -65,8 +65,7 @@ fn main() { } }; - let expr: Expr = - imports::panic_imports(&expr); + let expr: Expr = imports::panic_imports(&expr); let type_expr = match typecheck::type_of(&expr) { Err(e) => { @@ -90,5 +89,5 @@ fn main() { println!("{}", type_expr); println!(""); - println!("{}", normalize::<_, _, X, _>(&expr)); + println!("{}", normalize::<_, X, _>(&expr)); } diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs index 16d670f..6344c52 100644 --- a/dhall/src/normalize.rs +++ b/dhall/src/normalize.rs @@ -12,9 +12,7 @@ use std::fmt; /// However, `normalize` will not fail if the expression is ill-typed and will /// leave ill-typed sub-expressions unevaluated. /// -pub fn normalize( - e: &Expr, -) -> Expr +pub fn normalize(e: &Expr) -> Expr where S: Clone + fmt::Debug, T: Clone + fmt::Debug, @@ -26,9 +24,9 @@ where match e { // Matches that don't normalize everything right away Let(f, _, r, b) => { - let r2 = shift::(1, &V(f.clone(), 0), r); - let b2 = subst::(&V(f.clone(), 0), &r2, b); - let b3 = shift::(-1, &V(f.clone(), 0), &b2); + let r2 = shift::<_, S, _>(1, &V(f.clone(), 0), r); + let b2 = subst::<_, S, _>(&V(f.clone(), 0), &r2, b); + let b3 = shift::<_, T, _>(-1, &V(f.clone(), 0), &b2); normalize(&b3) } BoolIf(b, t, f) => match normalize(b) { @@ -38,16 +36,16 @@ where }, Annot(x, _) => normalize(x), Note(_, e) => normalize(e), - App(f, a) => match normalize::(f) { + App(f, a) => match normalize::(f) { Lam(x, _A, b) => { // Beta reduce let vx0 = &V(x, 0); - let a2 = shift::(1, vx0, a); - let b2 = subst::(vx0, &a2, &b); - let b3 = shift::(-1, vx0, &b2); + let a2 = shift::(1, vx0, a); + let b2 = subst::(vx0, &a2, &b); + let b3 = shift::(-1, vx0, &b2); normalize(&b3) } - f2 => match (f2, normalize::(a)) { + f2 => match (f2, normalize::(a)) { // fold/build fusion for `List` (App(box Builtin(ListBuild), _), App(box App(box Builtin(ListFold), _), box e2)) | (App(box Builtin(ListFold), _), App(box App(box Builtin(ListBuild), _), box e2)) | diff --git a/dhall/src/typecheck.rs b/dhall/src/typecheck.rs index 6e7775c..0dbb2f9 100644 --- a/dhall/src/typecheck.rs +++ b/dhall/src/typecheck.rs @@ -10,13 +10,11 @@ use dhall_core::core::Builtin::*; use dhall_core::core::Const::*; use dhall_core::core::Expr::*; use dhall_core::core::{app, pi}; -use dhall_core::core::{bx, shift, subst, Expr, StringLike, V, X}; +use dhall_core::core::{bx, shift, subst, Expr, Label, V, X}; use self::TypeMessage::*; -fn axiom( - c: core::Const, -) -> Result> { +fn axiom(c: core::Const) -> Result> { match c { Type => Ok(Kind), Kind => Err(TypeError::new(&Context::new(), &Const(Kind), Untyped)), @@ -48,18 +46,15 @@ fn match_vars(vl: &V, vr: &V, ctx: &[(L, L)]) -> bool { } } -fn prop_equal( - eL0: &Expr, - eR0: &Expr, -) -> bool +fn prop_equal(eL0: &Expr, eR0: &Expr) -> bool where S: Clone + ::std::fmt::Debug, T: Clone + ::std::fmt::Debug, { - fn go( - ctx: &mut Vec<(L, L)>, - el: &Expr, - er: &Expr, + fn go( + ctx: &mut Vec<(Label, Label)>, + el: &Expr, + er: &Expr, ) -> bool where S: Clone + ::std::fmt::Debug, @@ -145,20 +140,20 @@ where } } let mut ctx = vec![]; - go::(&mut ctx, &normalize(eL0), &normalize(eR0)) + go::(&mut ctx, &normalize(eL0), &normalize(eR0)) } -fn op2_type( +fn op2_type( ctx: &Context>, e: &Expr, t: core::Builtin, ef: EF, l: &Expr, r: &Expr, -) -> Result, TypeError> +) -> Result, TypeError> where S: Clone + ::std::fmt::Debug, - EF: FnOnce(Expr, Expr) -> TypeMessage, + EF: FnOnce(Expr, Expr) -> TypeMessage, { let tl = normalize(&type_with(ctx, l)?); match tl { @@ -181,10 +176,10 @@ where /// `type_with` does not necessarily normalize the type since full normalization /// is not necessary for just type-checking. If you actually care about the /// returned type then you may want to `normalize` it afterwards. -pub fn type_with( +pub fn type_with( ctx: &Context>, e: &Expr, -) -> Result, TypeError> +) -> Result, TypeError> where S: Clone + ::std::fmt::Debug, { @@ -209,7 +204,7 @@ where Ok(p) } Pi(ref x, ref tA, ref tB) => { - let tA2 = normalize::<_, S, S, X>(&type_with(ctx, tA)?); + let tA2 = normalize::(&type_with(ctx, tA)?); let kA = match tA2 { Const(k) => k, _ => { @@ -256,9 +251,9 @@ where let tA2 = type_with(ctx, a)?; if prop_equal(&tA, &tA2) { let vx0 = &V(x, 0); - let a2 = shift::(1, vx0, a); + let a2 = shift::(1, vx0, a); let tB2 = subst(vx0, &a2, &tB); - let tB3 = shift::(-1, vx0, &tB2); + let tB3 = shift::(-1, vx0, &tB2); Ok(tB3) } else { let nf_A = normalize(&tA); @@ -272,7 +267,7 @@ where } Let(ref f, ref mt, ref r, ref b) => { let tR = type_with(ctx, r)?; - let ttR = normalize::<_, S, S, X>(&type_with(ctx, &tR)?); + let ttR = normalize::(&type_with(ctx, &tR)?); let kR = match ttR { Const(k) => k, // Don't bother to provide a `let`-specific version of this error @@ -282,7 +277,7 @@ where let ctx2 = ctx.insert(f.clone(), tR.clone()); let tB = type_with(&ctx2, b)?; - let ttB = normalize::<_, S, S, X>(&type_with(ctx, &tB)?); + let ttB = normalize::(&type_with(ctx, &tB)?); let kB = match ttB { Const(k) => k, // Don't bother to provide a `let`-specific version of this error @@ -390,8 +385,7 @@ where pi("zero", "natural", "natural"), ), ), - ) - .take_ownership_of_labels()), + )), Builtin(NaturalBuild) => Ok(pi( "_", pi( @@ -404,14 +398,9 @@ where ), ), Natural, - ) - .take_ownership_of_labels()), + )), Builtin(NaturalIsZero) | Builtin(NaturalEven) | Builtin(NaturalOdd) => { - Ok(Pi( - "_".to_owned().into(), - bx(Natural.into()), - bx(Bool.into()), - )) + Ok(pi("_", Natural, Bool)) } BinOp(NaturalPlus, ref l, ref r) => { op2_type(ctx, e, Natural, CantAdd, l, r) @@ -435,7 +424,7 @@ where } }; - let s = normalize::<_, _, S, _>(&type_with(ctx, &t)?); + let s = normalize::<_, S, _>(&type_with(ctx, &t)?); match s { Const(Type) => {} _ => return Err(TypeError::new(ctx, e, InvalidListType(*t))), @@ -470,8 +459,7 @@ where ), app(List, "a"), ), - ) - .take_ownership_of_labels()), + )), Builtin(ListFold) => Ok(pi( "a", Const(Type), @@ -488,18 +476,15 @@ where ), ), ), - ) - .take_ownership_of_labels()), + )), Builtin(ListLength) => { - Ok(pi("a", Const(Type), pi("_", app(List, "a"), Natural)) - .take_ownership_of_labels()) + Ok(pi("a", Const(Type), pi("_", app(List, "a"), Natural))) } Builtin(ListHead) | Builtin(ListLast) => Ok(pi( "a", Const(Type), pi("_", app(List, "a"), app(Optional, "a")), - ) - .take_ownership_of_labels()), + )), Builtin(ListIndexed) => { let mut m: BTreeMap> = BTreeMap::new(); m.insert("index".into(), Builtin(Natural)); @@ -510,12 +495,11 @@ where pi("_", app(List, Var(V("a".into(), 0))), app(List, Record(m))), )) } - Builtin(ListReverse) => { - Ok( - pi("a", Const(Type), pi("_", app(List, "a"), app(List, "a"))) - .take_ownership_of_labels(), - ) - } + Builtin(ListReverse) => Ok(pi( + "a", + Const(Type), + pi("_", app(List, "a"), app(List, "a")), + )), OptionalLit(ref t, ref xs) => { let mut iter = xs.iter(); let t: Box> = match t { @@ -526,7 +510,7 @@ where } }; - let s = normalize::<_, _, S, _>(&type_with(ctx, &t)?); + let s = normalize::<_, S, _>(&type_with(ctx, &t)?); match s { Const(Type) => {} _ => { @@ -567,16 +551,15 @@ where ), ), ), - ) - .take_ownership_of_labels()), + )), Builtin(List) | Builtin(Optional) => { - Ok(pi("_", Const(Type), Const(Type)).take_ownership_of_labels()) + Ok(pi("_", Const(Type), Const(Type))) } Builtin(Bool) | Builtin(Natural) | Builtin(Integer) | Builtin(Double) | Builtin(Text) => Ok(Const(Type)), Record(ref kts) => { for (k, t) in kts { - let s = normalize::<_, S, S, X>(&type_with(ctx, t)?); + let s = normalize::(&type_with(ctx, t)?); match s { Const(Type) => {} _ => { @@ -595,7 +578,7 @@ where .iter() .map(|(k, v)| { let t = type_with(ctx, v)?; - let s = normalize::<_, S, S, X>(&type_with(ctx, &t)?); + let s = normalize::(&type_with(ctx, &t)?); match s { Const(Type) => {} _ => { @@ -723,19 +706,16 @@ where /// `typeOf` is the same as `type_with` with an empty context, meaning that the /// expression must be closed (i.e. no free variables), otherwise type-checking /// will fail. -pub fn type_of< - Label: StringLike + From, - S: Clone + ::std::fmt::Debug, ->( +pub fn type_of( e: &Expr, -) -> Result, TypeError> { +) -> Result, TypeError> { let ctx = Context::new(); type_with(&ctx, e) //.map(|e| e.into_owned()) } /// The specific type error #[derive(Debug)] -pub enum TypeMessage { +pub enum TypeMessage { UnboundVariable, InvalidInputType(Expr), InvalidOutputType(Expr), @@ -804,17 +784,17 @@ pub enum TypeMessage { /// A structured type error that includes context #[derive(Debug)] -pub struct TypeError { +pub struct TypeError { pub context: Context>, pub current: Expr, - pub type_message: TypeMessage, + pub type_message: TypeMessage, } -impl TypeError { +impl TypeError { pub fn new( context: &Context>, current: &Expr, - type_message: TypeMessage, + type_message: TypeMessage, ) -> Self { TypeError { context: context.clone(), @@ -824,7 +804,7 @@ impl TypeError { } } -impl ::std::error::Error for TypeMessage { +impl ::std::error::Error for TypeMessage { fn description(&self) -> &str { match *self { UnboundVariable => "Unbound variable", @@ -837,7 +817,7 @@ impl ::std::error::Error for TypeMessage { } } -impl fmt::Display for TypeMessage { +impl fmt::Display for TypeMessage { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { UnboundVariable => { diff --git a/dhall/tests/macros.rs b/dhall/tests/macros.rs index 5175238..10c4f5c 100644 --- a/dhall/tests/macros.rs +++ b/dhall/tests/macros.rs @@ -75,7 +75,7 @@ pub enum ExpectedResult { pub fn read_dhall_file<'i>( file_path: &str, -) -> Result, DhallError> { +) -> Result, DhallError> { load_dhall_file(&PathBuf::from(file_path), true) } @@ -104,8 +104,8 @@ pub fn run_test(base_path: &str, feature: Feature, expected: ExpectedResult) { let expected = read_dhall_file(&expected_file_path).unwrap(); assert_eq_!( - normalize::<_, _, X, _>(&expr), - normalize::<_, _, X, _>(&expected) + normalize::<_, X, _>(&expr), + normalize::<_, X, _>(&expected) ); } _ => unimplemented!(), diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index 7bd1318..7eaf08e 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -296,67 +296,52 @@ pub enum Builtin { TextShow, } -pub trait StringLike: - Display - + fmt::Debug - + Clone - + Hash - + Ord - + Eq - + Into - + From - + From<&'static str> -{ -} - -impl StringLike for T where - T: Display - + fmt::Debug - + Clone - + Hash - + Ord - + Eq - + Into - + From - + From<&'static str> -{ -} - -impl