From db3ca819283f9bd99d197de464717f0b58b52fe4 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 2 May 2019 17:07:11 +0200 Subject: Instead of possibly nonexistent Type, treat Sort specially --- dhall/src/expr.rs | 158 +++++++++++++++++----- dhall/src/normalize.rs | 50 +++---- dhall/src/tests.rs | 9 +- dhall/src/traits/deserialize.rs | 2 +- dhall/src/traits/dynamic_type.rs | 24 +--- dhall/src/traits/static_type.rs | 8 +- dhall/src/typecheck.rs | 273 +++++++++++++++++---------------------- 7 files changed, 282 insertions(+), 242 deletions(-) diff --git a/dhall/src/expr.rs b/dhall/src/expr.rs index a753ffd..4d55f4a 100644 --- a/dhall/src/expr.rs +++ b/dhall/src/expr.rs @@ -1,4 +1,5 @@ use crate::imports::ImportRoot; +use crate::normalize::{Thunk, Value}; use dhall_core::*; use std::marker::PhantomData; @@ -36,23 +37,23 @@ pub(crate) struct Resolved<'a>( ); derive_other_traits!(Resolved); +pub(crate) use self::typed::TypedInternal; + #[derive(Debug, Clone)] pub(crate) struct Typed<'a>( - pub(crate) crate::normalize::Thunk, - pub(crate) Option>, + pub(crate) TypedInternal, pub(crate) PhantomData<&'a ()>, ); #[derive(Debug, Clone)] pub(crate) struct Normalized<'a>( - pub(crate) crate::normalize::Thunk, - pub(crate) Option>, + pub(crate) TypedInternal, pub(crate) PhantomData<&'a ()>, ); impl<'a> std::cmp::PartialEq for Normalized<'a> { fn eq(&self, other: &Self) -> bool { - self.0.normalize_to_expr() == other.0.normalize_to_expr() + self.to_expr() == other.to_expr() } } @@ -60,7 +61,110 @@ impl<'a> std::cmp::Eq for Normalized<'a> {} impl<'a> std::fmt::Display for Normalized<'a> { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { - self.0.normalize_to_expr().fmt(f) + self.to_expr().fmt(f) + } +} + +mod typed { + use super::{Type, Typed}; + use crate::normalize::{Thunk, Value}; + use crate::typecheck::{ + TypeError, TypeInternal, TypeMessage, TypecheckContext, + }; + use dhall_core::{Const, Label, SubExpr, V, X}; + use std::borrow::Cow; + use std::marker::PhantomData; + + #[derive(Debug, Clone)] + pub(crate) enum TypedInternal { + // The `Sort` higher-kinded type doesn't have a type + Sort, + // Any other value, along with its type + Value(Thunk, Option>), + } + + impl TypedInternal { + pub(crate) fn from_thunk_and_type(th: Thunk, t: Type<'static>) -> Self { + TypedInternal::Value(th, Some(t)) + } + + pub(crate) fn from_thunk_untyped(th: Thunk) -> Self { + TypedInternal::Value(th, None) + } + + // TODO: Avoid cloning if possible + pub(crate) fn to_value(&self) -> Value { + match self { + TypedInternal::Value(th, _) => th.normalize_whnf().clone(), + TypedInternal::Sort => Value::Const(Const::Sort), + } + } + + pub(crate) fn to_expr(&self) -> SubExpr { + self.to_value().normalize_to_expr() + } + + pub(crate) fn to_thunk(&self) -> Thunk { + match self { + TypedInternal::Value(th, _) => th.clone(), + TypedInternal::Sort => { + Thunk::from_whnf(Value::Const(Const::Sort)) + } + } + } + + pub(crate) fn to_type(&self) -> Type<'static> { + match self { + TypedInternal::Sort => Type(TypeInternal::Const(Const::Sort)), + TypedInternal::Value(th, _) => match &*th.normalize_whnf() { + Value::Const(c) => Type(TypeInternal::Const(*c)), + _ => Type(TypeInternal::Typed(Box::new(Typed( + self.clone(), + PhantomData, + )))), + }, + } + } + + pub(crate) fn get_type( + &self, + ) -> Result>, TypeError> { + match self { + TypedInternal::Value(_, Some(t)) => Ok(Cow::Borrowed(t)), + TypedInternal::Value(_, None) => Err(TypeError::new( + &TypecheckContext::new(), + TypeMessage::Untyped, + )), + TypedInternal::Sort => Err(TypeError::new( + &TypecheckContext::new(), + TypeMessage::Sort, + )), + } + } + + pub(crate) fn shift(&self, delta: isize, var: &V