#![allow(non_snake_case)] use std::borrow::Borrow; use std::borrow::Cow; use std::fmt; use std::marker::PhantomData; use crate::expr::*; use crate::traits::DynamicType; use dhall_core; use dhall_core::context::Context; use dhall_core::*; use dhall_generator as dhall; use self::TypeMessage::*; impl<'a> Resolved<'a> { pub fn typecheck(self) -> Result, TypeError> { type_of(self.0.unnote()) } pub fn typecheck_with( self, ty: &Type, ) -> Result, TypeError> { let expr: SubExpr<_, _> = self.0.unnote(); let ty: SubExpr<_, _> = ty.clone().unnote().embed()?; type_of(dhall::subexpr!(expr: ty)) } /// Pretends this expression has been typechecked. Use with care. #[allow(dead_code)] pub fn skip_typecheck(self) -> Typed<'a> { Typed(self.0.unnote(), None, PhantomData) } } impl<'a> Typed<'a> { fn get_type_move(self) -> Result, TypeError> { let (expr, ty) = (self.0, self.1); ty.ok_or_else(|| { TypeError::new(&Context::new(), expr, TypeMessage::Untyped) }) } } impl<'a> Normalized<'a> { // Expose the outermost constructor fn unroll_ref(&self) -> &Expr { self.as_expr().as_ref() } fn shift0(&self, delta: isize, label: &Label) -> Self { // shift the type too ? Normalized(shift0(delta, label, &self.0), self.1.clone(), self.2) } } impl Normalized<'static> { fn embed(self) -> SubExpr> { rc(ExprF::Embed(self)) } } impl<'a> Type<'a> { pub(crate) fn as_normalized( &self, ) -> Result>, TypeError> { match &self.0 { TypeInternal::Expr(e) => Ok(Cow::Borrowed(e)), TypeInternal::Const(c) => Ok(Cow::Owned(const_to_normalized(*c))), TypeInternal::SuperType => Err(TypeError::new( &Context::new(), rc(ExprF::Const(Const::Sort)), TypeMessage::Untyped, )), } } pub(crate) fn into_normalized(self) -> Result, TypeError> { match self.0 { TypeInternal::Expr(e) => Ok(*e), TypeInternal::Const(c) => Ok(const_to_normalized(c)), TypeInternal::SuperType => Err(TypeError::new( &Context::new(), rc(ExprF::Const(Const::Sort)), TypeMessage::Untyped, )), } } // Expose the outermost constructor fn unroll_ref(&self) -> Result>, TypeError> { match self.as_normalized()? { Cow::Borrowed(e) => Ok(Cow::Borrowed(e.unroll_ref())), Cow::Owned(e) => Ok(Cow::Owned(e.into_expr().unroll())), } } fn shift0(&self, delta: isize, label: &Label) -> Self { use TypeInternal::*; Type(match &self.0 { Expr(e) => Expr(Box::new(e.shift0(delta, label))), Const(c) => Const(*c), SuperType => SuperType, }) } fn const_sort() -> Self { Type(TypeInternal::Const(Const::Sort)) } fn const_kind() -> Self { Type(TypeInternal::Const(Const::Kind)) } pub(crate) fn const_type() -> Self { Type(TypeInternal::Const(Const::Type)) } } impl Type<'static> { fn embed(self) -> Result>, TypeError> { Ok(self.into_normalized()?.embed()) } } fn function_check(a: Const, b: Const) -> Result { use dhall_core::Const::*; match (a, b) { (_, Type) => Ok(Type), (Kind, Kind) => Ok(Kind), (Sort, Sort) => Ok(Sort), (Sort, Kind) => Ok(Sort), _ => Err(()), } } fn match_vars(vl: &V