module Swarm.Language.Kindcheck (
KindError (..),
checkPolytypeKind,
checkKind,
) where
import Control.Algebra (Has)
import Control.Effect.Reader (Reader, ask)
import Control.Effect.Throw (Throw, throwError)
import Control.Monad.Extra (unlessM)
import Data.Fix (Fix (..))
import Swarm.Language.Types
data KindError
=
ArityMismatch TyCon Int [Type]
|
UndefinedTyCon TyCon Type
|
TrivialRecTy Var Type
|
VacuousRecTy Var Type
deriving (KindError -> KindError -> Bool
(KindError -> KindError -> Bool)
-> (KindError -> KindError -> Bool) -> Eq KindError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: KindError -> KindError -> Bool
== :: KindError -> KindError -> Bool
$c/= :: KindError -> KindError -> Bool
/= :: KindError -> KindError -> Bool
Eq, Int -> KindError -> ShowS
[KindError] -> ShowS
KindError -> String
(Int -> KindError -> ShowS)
-> (KindError -> String)
-> ([KindError] -> ShowS)
-> Show KindError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> KindError -> ShowS
showsPrec :: Int -> KindError -> ShowS
$cshow :: KindError -> String
show :: KindError -> String
$cshowList :: [KindError] -> ShowS
showList :: [KindError] -> ShowS
Show)
checkPolytypeKind :: (Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) => Polytype -> m TydefInfo
checkPolytypeKind :: forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) =>
Polytype -> m TydefInfo
checkPolytypeKind pty :: Polytype
pty@(Forall [Var]
xs Type
t) = Polytype -> Arity -> TydefInfo
TydefInfo Polytype
pty (Int -> Arity
Arity (Int -> Arity) -> Int -> Arity
forall a b. (a -> b) -> a -> b
$ [Var] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Var]
xs) TydefInfo -> m () -> m TydefInfo
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Type -> m ()
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) =>
Type -> m ()
checkKind Type
t
checkKind :: (Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) => Type -> m ()
checkKind :: forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) =>
Type -> m ()
checkKind ty :: Type
ty@(Fix TypeF Type
tyF) = case TypeF Type
tyF of
TyConF TyCon
c [Type]
tys -> do
TDCtx
tdCtx <- m TDCtx
forall r (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader r) sig m =>
m r
ask
case Arity -> Int
getArity (Arity -> Int) -> Maybe Arity -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TDCtx -> TyCon -> Maybe Arity
tcArity TDCtx
tdCtx TyCon
c of
Maybe Int
Nothing -> KindError -> m ()
forall e (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Throw e) sig m =>
e -> m a
throwError (KindError -> m ()) -> KindError -> m ()
forall a b. (a -> b) -> a -> b
$ TyCon -> Type -> KindError
UndefinedTyCon TyCon
c Type
ty
Just Int
a -> case Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ([Type] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
tys) Int
a of
Ordering
EQ -> (Type -> m ()) -> [Type] -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Type -> m ()
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) =>
Type -> m ()
checkKind [Type]
tys
Ordering
_ -> KindError -> m ()
forall e (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Throw e) sig m =>
e -> m a
throwError (KindError -> m ()) -> KindError -> m ()
forall a b. (a -> b) -> a -> b
$ TyCon -> Int -> [Type] -> KindError
ArityMismatch TyCon
c Int
a [Type]
tys
TyVarF Var
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
TyRcdF Map Var Type
m -> (Type -> m ()) -> Map Var Type -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Type -> m ()
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) =>
Type -> m ()
checkKind Map Var Type
m
TyRecF Var
x Type
t -> do
Type -> m ()
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) =>
Type -> m ()
checkKind (TypeF Type -> Type -> Nat -> Type
forall t. SubstRec t => TypeF t -> t -> Nat -> t
substRec (Var -> TypeF Type
forall t. Var -> TypeF t
TyVarF Var
x) Type
t Nat
NZ)
Var -> Type -> m ()
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) =>
Var -> Type -> m ()
checkRecTy Var
x Type
t
TyRecVarF Nat
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkRecTy :: (Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) => Var -> Type -> m ()
checkRecTy :: forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Has (Reader TDCtx) sig m, Has (Throw KindError) sig m) =>
Var -> Type -> m ()
checkRecTy Var
x Type
ty = do
m Bool -> m () -> m ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM (Nat -> Type -> m Bool
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
containsVar Nat
NZ Type
ty) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ KindError -> m ()
forall e (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Throw e) sig m =>
e -> m a
throwError (Var -> Type -> KindError
TrivialRecTy Var
x Type
ty)
m Bool -> m () -> m ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM (Nat -> Type -> m Bool
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
nonVacuous Nat
NZ Type
ty) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ KindError -> m ()
forall e (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Has (Throw e) sig m =>
e -> m a
throwError (Var -> Type -> KindError
VacuousRecTy Var
x Type
ty)
containsVar :: Has (Reader TDCtx) sig m => Nat -> Type -> m Bool
containsVar :: forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
containsVar Nat
i (Fix TypeF Type
tyF) = case TypeF Type
tyF of
TyRecVarF Nat
j -> Bool -> m Bool
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Nat
i Nat -> Nat -> Bool
forall a. Eq a => a -> a -> Bool
== Nat
j)
TyVarF {} -> Bool -> m Bool
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
False
TyConF (TCUser Var
u) [Type]
tys -> do
Type
ty' <- Var -> [Type] -> m Type
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) t.
(Has (Reader TDCtx) sig m, Typical t) =>
Var -> [t] -> m t
expandTydef Var
u [Type]
tys
Nat -> Type -> m Bool
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
containsVar Nat
i Type
ty'
TyConF TyCon
_ [Type]
tys -> [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> m [Bool] -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Type -> m Bool) -> [Type] -> m [Bool]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (Nat -> Type -> m Bool
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
containsVar Nat
i) [Type]
tys
TyRcdF Map Var Type
m -> Map Var Bool -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or (Map Var Bool -> Bool) -> m (Map Var Bool) -> m Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Type -> m Bool) -> Map Var Type -> m (Map Var Bool)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Map Var a -> m (Map Var b)
mapM (Nat -> Type -> m Bool
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
containsVar Nat
i) Map Var Type
m
TyRecF Var
_ Type
ty -> Nat -> Type -> m Bool
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
containsVar (Nat -> Nat
NS Nat
i) Type
ty
nonVacuous :: (Has (Reader TDCtx) sig m) => Nat -> Type -> m Bool
nonVacuous :: forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
nonVacuous Nat
i (Fix TypeF Type
tyF) = case TypeF Type
tyF of
TyRecVarF Nat
j -> Bool -> m Bool
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Nat
i Nat -> Nat -> Bool
forall a. Eq a => a -> a -> Bool
/= Nat
j)
TyConF (TCUser Var
u) [Type]
tys -> do
Type
ty' <- Var -> [Type] -> m Type
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) t.
(Has (Reader TDCtx) sig m, Typical t) =>
Var -> [t] -> m t
expandTydef Var
u [Type]
tys
Nat -> Type -> m Bool
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
nonVacuous Nat
i Type
ty'
TyRecF Var
_ Type
ty -> Nat -> Type -> m Bool
forall (sig :: (* -> *) -> * -> *) (m :: * -> *).
Has (Reader TDCtx) sig m =>
Nat -> Type -> m Bool
nonVacuous (Nat -> Nat
NS Nat
i) Type
ty
TyConF {} -> Bool -> m Bool
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
TyRcdF {} -> Bool -> m Bool
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
TyVarF {} -> Bool -> m Bool
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True