|
| 1 | +{-# LANGUAGE FlexibleContexts, TypeFamilies, ScopedTypeVariables #-} |
| 2 | + |
| 3 | +{-| A simplified version of pmcheck's inhabited type checker. This determines |
| 4 | +if a type is: |
| 5 | + - Trivially inhabitable (i.e. has an inhabitable constructor), |
| 6 | + - Uninhabitable (all constructors are uninhabitable), or |
| 7 | + - Unknown (relies on additional information, such as constraints or type variables) |
| 8 | +-} |
| 9 | +module Types.Inhabited (inhabited) where |
| 10 | + |
| 11 | +import Control.Lens |
| 12 | + |
| 13 | +import Syntax.Var |
| 14 | +import Syntax.Type |
| 15 | +import Syntax.Types |
| 16 | +import Syntax.Toplevel |
| 17 | + |
| 18 | +inhabited :: forall p. Var p ~ VarResolved |
| 19 | + => Env -> Var p -> [Constructor p] -> Inhabited |
| 20 | +inhabited env tyName = goCtors where |
| 21 | + goCtors :: [Constructor p] -> Inhabited |
| 22 | + goCtors [] = Uninhabited |
| 23 | + goCtors (UnitCon{}:_) = Inhabited |
| 24 | + goCtors (ArgCon _ _ t _:cs) = orInhabited (goType t) (goCtors cs) |
| 25 | + goCtors (GadtCon{}:cs) = |
| 26 | + -- :( I cannot think of a way to do this sensibly, so we let the verifier |
| 27 | + -- check this for us. |
| 28 | + orInhabited Unknown (goCtors cs) |
| 29 | + |
| 30 | + goTypes :: [Type p] -> Inhabited |
| 31 | + goTypes [] = Inhabited |
| 32 | + goTypes (t:ts) = |
| 33 | + case goType t of |
| 34 | + Inhabited -> goTypes ts |
| 35 | + x -> x |
| 36 | + |
| 37 | + goType :: Type p -> Inhabited |
| 38 | + -- We can't know if a type variable is inhabited or not! |
| 39 | + goType TyVar{} = Unknown |
| 40 | + |
| 41 | + goType (TyApp t _) = goType t |
| 42 | + goType (TyCon v _) |
| 43 | + | v == tyName = Unknown |
| 44 | + | otherwise = case env ^. types . at v of |
| 45 | + Nothing -> Inhabited -- Abstract types are considered inhabited. |
| 46 | + Just t -> t ^. tdInhabited |
| 47 | + |
| 48 | + -- We don't really have the concept of uninhabited types, so we assume |
| 49 | + -- type names are. |
| 50 | + goType TyPromotedCon{} = Inhabited |
| 51 | + -- For now, we'll just assume all Pi types are inhabited. Thankfully, |
| 52 | + -- they all are. |
| 53 | + goType TyPi{} = Inhabited |
| 54 | + -- All the boring types: just determine if the children are inhabited |
| 55 | + goType (TyRows f fs) = goTypes (f:map snd fs) |
| 56 | + goType (TyExactRows fs) = goTypes (snd <$> fs) |
| 57 | + goType (TyTuple l r) = goTypes [l, r] |
| 58 | + goType (TyOperator l v r) = goType (TyApp (TyApp v l) r) |
| 59 | + goType (TyWildcard t) = maybe Unknown goType t |
| 60 | + goType (TyParens t) = goType t |
| 61 | + |
| 62 | + goType TySkol{} = Inhabited |
| 63 | + goType (TyWithConstraints _ t) = goType t |
| 64 | + goType TyType = Inhabited |
| 65 | + goType TyLit{} = Inhabited |
| 66 | + goType TyTupleL{} = Inhabited |
| 67 | + |
| 68 | +orInhabited :: Inhabited -> Inhabited -> Inhabited |
| 69 | +orInhabited Inhabited _ = Inhabited |
| 70 | +orInhabited Uninhabited x = x |
| 71 | +orInhabited Unknown Inhabited = Inhabited |
| 72 | +orInhabited Unknown _ = Unknown |
0 commit comments