From 78a0c10a4595683c034b8d3617f55c88cea2aa3c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 8 Mar 2019 18:17:22 +0100 Subject: Slowly propagate the new type parameter throughout the codebase --- dhall/src/lib.rs | 2 +- dhall/src/main.rs | 2 +- dhall/src/normalize.rs | 53 +++++---- dhall/src/typecheck.rs | 126 +++++++++++---------- dhall/tests/macros.rs | 6 +- dhall_core/src/context.rs | 4 +- dhall_core/src/core.rs | 269 +++++++++++++++++++++++++++++++-------------- dhall_generator/src/lib.rs | 14 +-- 8 files changed, 298 insertions(+), 178 deletions(-) diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs index 4e183b4..6372768 100644 --- a/dhall/src/lib.rs +++ b/dhall/src/lib.rs @@ -43,7 +43,7 @@ impl fmt::Display for DhallError { pub fn load_dhall_file<'i, 'a: 'i>( f: &Path, source_pool: &'a mut Vec, - resolve_imports: bool, + _resolve_imports: bool, ) -> Result, DhallError> { source_pool.push(String::new()); let mut buffer = source_pool.last_mut().unwrap(); diff --git a/dhall/src/main.rs b/dhall/src/main.rs index 493f9be..dbe80a3 100644 --- a/dhall/src/main.rs +++ b/dhall/src/main.rs @@ -89,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 246a3c0..d3766d5 100644 --- a/dhall/src/normalize.rs +++ b/dhall/src/normalize.rs @@ -12,7 +12,9 @@ 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<'i, S, T, A>(e: &Expr<'i, S, A>) -> Expr<'i, T, A> +pub fn normalize( + e: &Expr_, +) -> Expr_ where S: Clone + fmt::Debug, T: Clone + fmt::Debug, @@ -24,9 +26,9 @@ where match e { // Matches that don't normalize everything right away Let(f, _, r, b) => { - let r2 = shift::<_, S, _>(1, V(f, 0), r); - let b2 = subst(V(f, 0), &r2, b); - let b3 = shift::<_, T, _>(-1, V(f, 0), &b2); + 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); normalize(&b3) } BoolIf(b, t, f) => match normalize(b) { @@ -36,16 +38,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)) | @@ -87,13 +89,14 @@ where (Builtin(NaturalOdd), NaturalLit(n)) => BoolLit(n % 2 != 0), (Builtin(NaturalToInteger), NaturalLit(n)) => IntegerLit(n as isize), (Builtin(NaturalShow), NaturalLit(n)) => TextLit(n.to_string()), - (App(box Builtin(ListBuild), a0), k) => { - let k = bx(k); - let a1 = bx(shift(1, V("a", 0), &a0)); - normalize(&dhall!(k (List a0) (λ(a : a0) -> λ(as : List a1) -> [ a ] # as) ([] : List a0))) - } + // TODO: restore when handling variables generically fixed + // (App(box Builtin(ListBuild), a0), k) => { + // let k = bx(k); + // let a1 = bx(shift(1, V("a", 0), &a0)); + // normalize(&dhall!(k (List a0) (λ(a : a0) -> λ(as : List a1) -> [ a ] # as) ([] : List a0))) + // } (App(box App(box App(box App(box Builtin(ListFold), _), box ListLit(_, xs)), _), cons), nil) => { - let e2: Expr<_, _> = xs.into_iter().rev().fold(nil, |y, ys| { + let e2: Expr_<_, _, _> = xs.into_iter().rev().fold(nil, |y, ys| { let y = bx(y); let ys = bx(ys); dhall!(cons y ys) @@ -130,23 +133,29 @@ where ] */ (App(box App(box App(box App(box Builtin(OptionalFold), _), box OptionalLit(_, xs)), _), just), nothing) => { - let e2: Expr<_, _> = xs.into_iter().fold(nothing, |y, _| { + let e2: Expr_<_, _, _> = xs.into_iter().fold(nothing, |y, _| { let y = bx(y); dhall!(just y) }); normalize(&e2) } - (App(box Builtin(OptionalBuild), a0), g) => { - let g = bx(g); - normalize(&dhall!((g (Optional a0)) (λ(x: a0) -> [x] : Optional a0) ([] : Optional a0))) - } + // TODO: restore when handling variables generically fixed + // (App(box Builtin(OptionalBuild), a0), g) => { + // let g = bx(g); + // normalize(&dhall!((g (Optional a0)) (λ(x: a0) -> [x] : Optional a0) ([] : Optional a0))) + // } (f2, a2) => app(f2, a2), }, }, // Normalize everything else before matching e => { - match e.map_shallow(normalize, |_| unreachable!(), |x| x.clone()) { + match e.map_shallow( + normalize, + |_| unreachable!(), + |x| x.clone(), + |x| x.clone(), + ) { BinOp(BoolAnd, box BoolLit(x), box BoolLit(y)) => { BoolLit(x && y) } @@ -180,7 +189,7 @@ where ListLit(t, xs.chain(ys).collect()) } Merge(_x, _y, _t) => unimplemented!(), - Field(box RecordLit(kvs), x) => match kvs.get(x) { + Field(box RecordLit(kvs), x) => match kvs.get(&x) { Some(r) => r.clone(), None => Field(bx(RecordLit(kvs)), x), }, diff --git a/dhall/src/typecheck.rs b/dhall/src/typecheck.rs index 23ab7a6..c2a2ca3 100644 --- a/dhall/src/typecheck.rs +++ b/dhall/src/typecheck.rs @@ -10,7 +10,7 @@ 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, V, X}; +use dhall_core::core::{bx, shift, subst, Expr, Expr_, V, X}; use self::TypeMessage::*; @@ -155,7 +155,7 @@ fn op2_type<'i, S, EF>( ) -> Result, TypeError<'i, S>> where S: Clone + ::std::fmt::Debug + 'i, - EF: FnOnce(Expr<'i, S, X>, Expr<'i, S, X>) -> TypeMessage<'i, S>, + EF: FnOnce(Expr<'i, S, X>, Expr<'i, S, X>) -> TypeMessage<&'i str, S>, { let tl = normalize(&type_with(ctx, l)?); match tl { @@ -189,7 +189,7 @@ where use dhall_core::Expr_; match *e { Const(c) => axiom(c).map(Const), //.map(Cow::Owned), - Var(V(x, n)) => { + Var(V(ref x, n)) => { ctx.lookup(x, n) .cloned() //.map(Cow::Borrowed) @@ -206,7 +206,7 @@ where Ok(p) } Pi(x, ref tA, ref tB) => { - let tA2 = normalize::(&type_with(ctx, tA)?); + let tA2 = normalize::<_, S, S, X>(&type_with(ctx, tA)?); let kA = match tA2 { Const(k) => k, _ => { @@ -253,9 +253,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::<&str, S, S, X>(1, vx0, a); let tB2 = subst(vx0, &a2, &tB); - let tB3 = shift::(-1, vx0, &tB2); + let tB3 = shift::<&str, S, S, X>(-1, vx0, &tB2); Ok(tB3) } else { let nf_A = normalize(&tA); @@ -269,7 +269,7 @@ where } Let(f, ref mt, ref r, ref b) => { let tR = type_with(ctx, r)?; - let ttR = normalize::(&type_with(ctx, &tR)?); + let ttR = normalize::<_, S, S, X>(&type_with(ctx, &tR)?); let kR = match ttR { Const(k) => k, // Don't bother to provide a `let`-specific version of this error @@ -279,7 +279,7 @@ where let ctx2 = ctx.insert(f, tR.clone()); let tB = type_with(&ctx2, b)?; - let ttB = normalize::(&type_with(ctx, &tB)?); + let ttB = normalize::<_, S, S, X>(&type_with(ctx, &tB)?); let kB = match ttB { Const(k) => k, // Don't bother to provide a `let`-specific version of this error @@ -426,7 +426,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))), @@ -512,7 +512,7 @@ where } }; - let s = normalize::<_, S, _>(&type_with(ctx, &t)?); + let s = normalize::<_, _, S, _>(&type_with(ctx, &t)?); match s { Const(Type) => {} _ => { @@ -561,7 +561,7 @@ where | Builtin(Double) | Builtin(Text) => Ok(Const(Type)), Record(ref kts) => { for (k, t) in kts { - let s = normalize::(&type_with(ctx, t)?); + let s = normalize::<_, S, S, X>(&type_with(ctx, t)?); match s { Const(Type) => {} _ => { @@ -580,7 +580,7 @@ where .iter() .map(|(&k, v)| { let t = type_with(ctx, v)?; - let s = normalize::(&type_with(ctx, &t)?); + let s = normalize::<_, S, S, X>(&type_with(ctx, &t)?); match s { Const(Type) => {} _ => { @@ -717,57 +717,71 @@ pub fn type_of<'i, S: Clone + ::std::fmt::Debug + 'i>( /// The specific type error #[derive(Debug)] -pub enum TypeMessage<'i, S> { +pub enum TypeMessage { UnboundVariable, - InvalidInputType(Expr<'i, S, X>), - InvalidOutputType(Expr<'i, S, X>), - NotAFunction(Expr<'i, S, X>, Expr<'i, S, X>), + InvalidInputType(Expr_), + InvalidOutputType(Expr_), + NotAFunction(Expr_, Expr_), TypeMismatch( - Expr<'i, S, X>, - Expr<'i, S, X>, - Expr<'i, S, X>, - Expr<'i, S, X>, + Expr_, + Expr_, + Expr_, + Expr_, ), - AnnotMismatch(Expr<'i, S, X>, Expr<'i, S, X>, Expr<'i, S, X>), + AnnotMismatch(Expr_, Expr_, Expr_), Untyped, - InvalidListElement(usize, Expr<'i, S, X>, Expr<'i, S, X>, Expr<'i, S, X>), - InvalidListType(Expr<'i, S, X>), - InvalidOptionalElement(Expr<'i, S, X>, Expr<'i, S, X>, Expr<'i, S, X>), + InvalidListElement( + usize, + Expr_, + Expr_, + Expr_, + ), + InvalidListType(Expr_), + InvalidOptionalElement( + Expr_, + Expr_, + Expr_, + ), InvalidOptionalLiteral(usize), - InvalidOptionalType(Expr<'i, S, X>), - InvalidPredicate(Expr<'i, S, X>, Expr<'i, S, X>), + InvalidOptionalType(Expr_), + InvalidPredicate(Expr_, Expr_), IfBranchMismatch( - Expr<'i, S, X>, - Expr<'i, S, X>, - Expr<'i, S, X>, - Expr<'i, S, X>, + Expr_, + Expr_, + Expr_, + Expr_, + ), + IfBranchMustBeTerm( + bool, + Expr_, + Expr_, + Expr_, ), - IfBranchMustBeTerm(bool, Expr<'i, S, X>, Expr<'i, S, X>, Expr<'i, S, X>), - InvalidField(String, Expr<'i, S, X>), - InvalidFieldType(String, Expr<'i, S, X>), - InvalidAlternative(String, Expr<'i, S, X>), - InvalidAlternativeType(String, Expr<'i, S, X>), + InvalidField(String, Expr_), + InvalidFieldType(String, Expr_), + InvalidAlternative(String, Expr_), + InvalidAlternativeType(String, Expr_), DuplicateAlternative(String), - MustCombineARecord(Expr<'i, S, X>, Expr<'i, S, X>), + MustCombineARecord(Expr_, Expr_), FieldCollision(String), - MustMergeARecord(Expr<'i, S, X>, Expr<'i, S, X>), - MustMergeUnion(Expr<'i, S, X>, Expr<'i, S, X>), + MustMergeARecord(Expr_, Expr_), + MustMergeUnion(Expr_, Expr_), UnusedHandler(HashSet), MissingHandler(HashSet), - HandlerInputTypeMismatch(String, Expr<'i, S, X>, Expr<'i, S, X>), - HandlerOutputTypeMismatch(String, Expr<'i, S, X>, Expr<'i, S, X>), - HandlerNotAFunction(String, Expr<'i, S, X>), - NotARecord(String, Expr<'i, S, X>, Expr<'i, S, X>), - MissingField(String, Expr<'i, S, X>), - CantAnd(Expr<'i, S, X>, Expr<'i, S, X>), - CantOr(Expr<'i, S, X>, Expr<'i, S, X>), - CantEQ(Expr<'i, S, X>, Expr<'i, S, X>), - CantNE(Expr<'i, S, X>, Expr<'i, S, X>), - CantTextAppend(Expr<'i, S, X>, Expr<'i, S, X>), - CantAdd(Expr<'i, S, X>, Expr<'i, S, X>), - CantMultiply(Expr<'i, S, X>, Expr<'i, S, X>), - NoDependentLet(Expr<'i, S, X>, Expr<'i, S, X>), - NoDependentTypes(Expr<'i, S, X>, Expr<'i, S, X>), + HandlerInputTypeMismatch(String, Expr_, Expr_), + HandlerOutputTypeMismatch(String, Expr_, Expr_), + HandlerNotAFunction(String, Expr_), + NotARecord(String, Expr_, Expr_), + MissingField(String, Expr_), + CantAnd(Expr_, Expr_), + CantOr(Expr_, Expr_), + CantEQ(Expr_, Expr_), + CantNE(Expr_, Expr_), + CantTextAppend(Expr_, Expr_), + CantAdd(Expr_, Expr_), + CantMultiply(Expr_, Expr_), + NoDependentLet(Expr_, Expr_), + NoDependentTypes(Expr_, Expr_), } /// A structured type error that includes context @@ -775,14 +789,14 @@ pub enum TypeMessage<'i, S> { pub struct TypeError<'i, S> { pub context: Context<&'i str, Expr<'i, S, X>>, pub current: Expr<'i, S, X>, - pub type_message: TypeMessage<'i, S>, + pub type_message: TypeMessage<&'i str, S>, } impl<'i, S: Clone> TypeError<'i, S> { pub fn new( context: &Context<&'i str, Expr<'i, S, X>>, current: &Expr<'i, S, X>, - type_message: TypeMessage<'i, S>, + type_message: TypeMessage<&'i str, S>, ) -> Self { TypeError { context: context.clone(), @@ -792,7 +806,7 @@ impl<'i, S: Clone> TypeError<'i, S> { } } -impl<'i, S: fmt::Debug> ::std::error::Error for TypeMessage<'i, S> { +impl<'i, S: fmt::Debug> ::std::error::Error for TypeMessage<&'i str, S> { fn description(&self) -> &str { match *self { UnboundVariable => "Unbound variable", @@ -805,7 +819,7 @@ impl<'i, S: fmt::Debug> ::std::error::Error for TypeMessage<'i, S> { } } -impl<'i, S> fmt::Display for TypeMessage<'i, S> { +impl<'i, S> fmt::Display for TypeMessage<&'i str, S> { 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 ef518ed..b27b850 100644 --- a/dhall/tests/macros.rs +++ b/dhall/tests/macros.rs @@ -61,8 +61,8 @@ macro_rules! make_spec_test { } use dhall::*; -use dhall_core::*; use dhall_core::parser::*; +use dhall_core::*; use std::fs::File; use std::io::Read; use std::path::PathBuf; @@ -114,8 +114,8 @@ pub fn run_test(base_path: &str, feature: Feature, expected: ExpectedResult) { let expected = read_dhall_file(&expected_file_path, &mut expected_buffer).unwrap(); assert_eq_!( - normalize::<_, X, _>(&expr), - normalize::<_, X, _>(&expected) + normalize::<_, _, X, _>(&expr), + normalize::<_, _, X, _>(&expected) ); } _ => unimplemented!(), diff --git a/dhall_core/src/context.rs b/dhall_core/src/context.rs index 412d3f0..877843d 100644 --- a/dhall_core/src/context.rs +++ b/dhall_core/src/context.rs @@ -31,8 +31,8 @@ impl Context { /// lookup k n (insert k v c) = lookup k (n - 1) c -- 1 <= n /// lookup k n (insert j v c) = lookup k n c -- k /= j /// ``` - pub fn lookup<'a>(&'a self, k: K, n: usize) -> Option<&'a T> { - self.0.get(&k).and_then(|v| v.get(v.len() - 1 - n)) + pub fn lookup<'a>(&'a self, k: &K, n: usize) -> Option<&'a T> { + self.0.get(k).and_then(|v| v.get(v.len() - 1 - n)) } pub fn map U>(&self, f: F) -> Context { diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index cbf0654..d832a18 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -1,6 +1,7 @@ #![allow(non_snake_case)] use std::collections::BTreeMap; use std::fmt::{self, Display}; +use std::hash::Hash; use std::path::PathBuf; /// Constants for a pure type system @@ -144,12 +145,23 @@ pub enum Expr_ { /// `Var (V x n) ~ x@n` Var(V