From 372c78ab875c8aa1e967ffb594f26df8beb43bea Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Tue, 7 May 2019 20:30:05 +0200 Subject: Slight improvement to typecheck ergonomics --- dhall/src/phase/typecheck.rs | 87 ++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 59 deletions(-) (limited to 'dhall') diff --git a/dhall/src/phase/typecheck.rs b/dhall/src/phase/typecheck.rs index bfe85b9..b163af6 100644 --- a/dhall/src/phase/typecheck.rs +++ b/dhall/src/phase/typecheck.rs @@ -35,19 +35,19 @@ macro_rules! ensure_simple_type { #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) enum TypeIntermediate { - Pi(TypecheckContext, Label, Type, Type), - RecordType(TypecheckContext, BTreeMap), - UnionType(TypecheckContext, BTreeMap>), - ListType(TypecheckContext, Type), - OptionalType(TypecheckContext, Type), + Pi(Label, Type, Type), + RecordType(BTreeMap), + UnionType(BTreeMap>), + ListType(Type), + OptionalType(Type), } impl TypeIntermediate { - fn typecheck(self) -> Result { + fn typecheck(self, ctx: &TypecheckContext) -> Result { use crate::error::TypeMessage::*; - let mkerr = |ctx, msg| TypeError::new(ctx, msg); + let mkerr = |ctx: &TypecheckContext, msg| TypeError::new(ctx, msg); Ok(match &self { - TypeIntermediate::Pi(ctx, x, ta, tb) => { + TypeIntermediate::Pi(x, ta, tb) => { let ctx2 = ctx.insert_type(x, ta.clone()); let kA = match ta.get_type()?.as_const() { @@ -101,7 +101,7 @@ impl TypeIntermediate { Type::from_const(k), ) } - TypeIntermediate::RecordType(ctx, kts) => { + TypeIntermediate::RecordType(kts) => { // Check that all types are the same const let mut k = None; for (x, t) in kts { @@ -131,7 +131,7 @@ impl TypeIntermediate { Type::from_const(k), ) } - TypeIntermediate::UnionType(ctx, kts) => { + TypeIntermediate::UnionType(kts) => { // Check that all types are the same const let mut k = None; for (x, t) in kts { @@ -170,7 +170,7 @@ impl TypeIntermediate { Type::from_const(k), ) } - TypeIntermediate::ListType(ctx, t) => { + TypeIntermediate::ListType(t) => { ensure_simple_type!( t, mkerr(ctx, InvalidListType(t.clone().to_normalized())), @@ -182,7 +182,7 @@ impl TypeIntermediate { Type::from_const(Const::Type), ) } - TypeIntermediate::OptionalType(ctx, t) => { + TypeIntermediate::OptionalType(t) => { ensure_simple_type!( t, mkerr(ctx, InvalidOptionalType(t.clone().to_normalized())), @@ -337,6 +337,7 @@ enum Ret { RetTyped(Typed), /// Use the contained Type as the type of the input expression RetType(Type), + RetTypeIntermediate(TypeIntermediate), } /// Type-check an expression and return the expression alongside its type if type-checking @@ -356,20 +357,13 @@ fn type_with( let ctx2 = ctx.insert_type(x, tx.clone()); let b = type_with(&ctx2, b.clone())?; let tb = b.get_type()?.into_owned(); - Ok(RetType( - TypeIntermediate::Pi(ctx.clone(), x.clone(), tx, tb) - .typecheck()? - .to_type(), - )) + Ok(RetTypeIntermediate(TypeIntermediate::Pi(x.clone(), tx, tb))) } Pi(x, ta, tb) => { let ta = mktype(ctx, ta.clone())?; let ctx2 = ctx.insert_type(x, ta.clone()); let tb = mktype(&ctx2, tb.clone())?; - Ok(RetTyped( - TypeIntermediate::Pi(ctx.clone(), x.clone(), ta, tb) - .typecheck()?, - )) + return TypeIntermediate::Pi(x.clone(), ta, tb).typecheck(ctx); } Let(x, t, v, e) => { let v = if let Some(t) = t { @@ -379,9 +373,7 @@ fn type_with( }; let v = type_with(ctx, v)?; - let e = type_with(&ctx.insert_value(x, v.clone())?, e.clone())?; - - Ok(RetType(e.get_type()?.into_owned())) + return type_with(&ctx.insert_value(x, v.clone())?, e.clone()); } OldOptionalLit(None, t) => { let none = SubExpr::from_expr_no_note(ExprF::Builtin( @@ -411,6 +403,10 @@ fn type_with( Thunk::new(ctx.to_normalization_ctx(), e), typ, ), + RetTypeIntermediate(ti) => Typed::from_thunk_and_type( + Thunk::new(ctx.to_normalization_ctx(), e), + ti.typecheck(ctx)?.to_type(), + ), RetTyped(tt) => tt, }) } @@ -493,11 +489,7 @@ fn type_last_layer( } EmptyListLit(t) => { let t = t.to_type(); - Ok(RetType( - TypeIntermediate::ListType(ctx.clone(), t) - .typecheck()? - .to_type(), - )) + Ok(RetTypeIntermediate(TypeIntermediate::ListType(t))) } NEListLit(xs) => { let mut iter = xs.into_iter().enumerate(); @@ -514,28 +506,18 @@ fn type_last_layer( ); } let t = x.get_type()?.into_owned(); - Ok(RetType( - TypeIntermediate::ListType(ctx.clone(), t) - .typecheck()? - .to_type(), - )) + Ok(RetTypeIntermediate(TypeIntermediate::ListType(t))) } SomeLit(x) => { let t = x.get_type()?.into_owned(); - Ok(RetType( - TypeIntermediate::OptionalType(ctx.clone(), t) - .typecheck()? - .to_type(), - )) + Ok(RetTypeIntermediate(TypeIntermediate::OptionalType(t))) } RecordType(kts) => { let kts: BTreeMap<_, _> = kts .into_iter() .map(|(x, t)| Ok((x, t.to_type()))) .collect::>()?; - Ok(RetTyped( - TypeIntermediate::RecordType(ctx.clone(), kts).typecheck()?, - )) + Ok(RetTyped(TypeIntermediate::RecordType(kts).typecheck(ctx)?)) } UnionType(kts) => { let kts: BTreeMap<_, _> = kts @@ -550,20 +532,14 @@ fn type_last_layer( )) }) .collect::>()?; - Ok(RetTyped( - TypeIntermediate::UnionType(ctx.clone(), kts).typecheck()?, - )) + Ok(RetTyped(TypeIntermediate::UnionType(kts).typecheck(ctx)?)) } RecordLit(kvs) => { let kts = kvs .into_iter() .map(|(x, v)| Ok((x, v.get_type()?.into_owned()))) .collect::>()?; - Ok(RetType( - TypeIntermediate::RecordType(ctx.clone(), kts) - .typecheck()? - .to_type(), - )) + Ok(RetTypeIntermediate(TypeIntermediate::RecordType(kts))) } UnionLit(x, v, kvs) => { let mut kts: std::collections::BTreeMap<_, _> = kvs @@ -578,11 +554,7 @@ fn type_last_layer( .collect::>()?; let t = v.get_type()?.into_owned(); kts.insert(x, Some(t)); - Ok(RetType( - TypeIntermediate::UnionType(ctx.clone(), kts) - .typecheck()? - .to_type(), - )) + Ok(RetTypeIntermediate(TypeIntermediate::UnionType(kts))) } Field(r, x) => { match &r.get_type()?.internal_whnf() { @@ -599,15 +571,12 @@ fn type_last_layer( Some(Value::UnionType(kts)) => match kts.get(&x) { // Constructor has type T -> < x: T, ... > Some(Some(t)) => { - Ok(RetType( + Ok(RetTypeIntermediate( TypeIntermediate::Pi( - ctx.clone(), "_".into(), t.to_type(ctx)?, r.clone(), ) - .typecheck()? - .to_type(), )) }, Some(None) => { -- cgit v1.2.3