module Disco.Exhaustiveness.TypeInfo where
import Control.Monad (replicateM)
import Data.Function (on)
import Data.List ((\\))
import qualified Data.Map as M
import Disco.AST.Typed (ATerm)
import Disco.Effects.Fresh (Fresh, fresh)
import qualified Disco.Types as Ty
import Polysemy
import Unbound.Generics.LocallyNameless (Name, s2n)
newtype TypedVar = TypedVar (Name ATerm, Ty.Type)
deriving (Int -> TypedVar -> ShowS
[TypedVar] -> ShowS
TypedVar -> String
(Int -> TypedVar -> ShowS)
-> (TypedVar -> String) -> ([TypedVar] -> ShowS) -> Show TypedVar
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TypedVar -> ShowS
showsPrec :: Int -> TypedVar -> ShowS
$cshow :: TypedVar -> String
show :: TypedVar -> String
$cshowList :: [TypedVar] -> ShowS
showList :: [TypedVar] -> ShowS
Show, Eq TypedVar
Eq TypedVar =>
(TypedVar -> TypedVar -> Ordering)
-> (TypedVar -> TypedVar -> Bool)
-> (TypedVar -> TypedVar -> Bool)
-> (TypedVar -> TypedVar -> Bool)
-> (TypedVar -> TypedVar -> Bool)
-> (TypedVar -> TypedVar -> TypedVar)
-> (TypedVar -> TypedVar -> TypedVar)
-> Ord TypedVar
TypedVar -> TypedVar -> Bool
TypedVar -> TypedVar -> Ordering
TypedVar -> TypedVar -> TypedVar
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: TypedVar -> TypedVar -> Ordering
compare :: TypedVar -> TypedVar -> Ordering
$c< :: TypedVar -> TypedVar -> Bool
< :: TypedVar -> TypedVar -> Bool
$c<= :: TypedVar -> TypedVar -> Bool
<= :: TypedVar -> TypedVar -> Bool
$c> :: TypedVar -> TypedVar -> Bool
> :: TypedVar -> TypedVar -> Bool
$c>= :: TypedVar -> TypedVar -> Bool
>= :: TypedVar -> TypedVar -> Bool
$cmax :: TypedVar -> TypedVar -> TypedVar
max :: TypedVar -> TypedVar -> TypedVar
$cmin :: TypedVar -> TypedVar -> TypedVar
min :: TypedVar -> TypedVar -> TypedVar
Ord)
instance Eq TypedVar where
TypedVar (Name ATerm
n1, Type
_) == :: TypedVar -> TypedVar -> Bool
== TypedVar (Name ATerm
n2, Type
_) = Name ATerm
n1 Name ATerm -> Name ATerm -> Bool
forall a. Eq a => a -> a -> Bool
== Name ATerm
n2
getType :: TypedVar -> Ty.Type
getType :: TypedVar -> Type
getType (TypedVar (Name ATerm
_, Type
t)) = Type
t
data DataCon = DataCon
{ DataCon -> Ident
dcIdent :: Ident
, DataCon -> [Type]
dcTypes :: [Ty.Type]
}
deriving (Eq DataCon
Eq DataCon =>
(DataCon -> DataCon -> Ordering)
-> (DataCon -> DataCon -> Bool)
-> (DataCon -> DataCon -> Bool)
-> (DataCon -> DataCon -> Bool)
-> (DataCon -> DataCon -> Bool)
-> (DataCon -> DataCon -> DataCon)
-> (DataCon -> DataCon -> DataCon)
-> Ord DataCon
DataCon -> DataCon -> Bool
DataCon -> DataCon -> Ordering
DataCon -> DataCon -> DataCon
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: DataCon -> DataCon -> Ordering
compare :: DataCon -> DataCon -> Ordering
$c< :: DataCon -> DataCon -> Bool
< :: DataCon -> DataCon -> Bool
$c<= :: DataCon -> DataCon -> Bool
<= :: DataCon -> DataCon -> Bool
$c> :: DataCon -> DataCon -> Bool
> :: DataCon -> DataCon -> Bool
$c>= :: DataCon -> DataCon -> Bool
>= :: DataCon -> DataCon -> Bool
$cmax :: DataCon -> DataCon -> DataCon
max :: DataCon -> DataCon -> DataCon
$cmin :: DataCon -> DataCon -> DataCon
min :: DataCon -> DataCon -> DataCon
Ord, Int -> DataCon -> ShowS
[DataCon] -> ShowS
DataCon -> String
(Int -> DataCon -> ShowS)
-> (DataCon -> String) -> ([DataCon] -> ShowS) -> Show DataCon
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DataCon -> ShowS
showsPrec :: Int -> DataCon -> ShowS
$cshow :: DataCon -> String
show :: DataCon -> String
$cshowList :: [DataCon] -> ShowS
showList :: [DataCon] -> ShowS
Show)
instance Eq DataCon where
== :: DataCon -> DataCon -> Bool
(==) = Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Ident -> Ident -> Bool)
-> (DataCon -> Ident) -> DataCon -> DataCon -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` DataCon -> Ident
dcIdent
data Ident where
KUnit :: Ident
KBool :: Bool -> Ident
KNat :: Integer -> Ident
KInt :: Integer -> Ident
KPair :: Ident
KCons :: Ident
KNil :: Ident
KChar :: Char -> Ident
KLeft :: Ident
KRight :: Ident
KUnknown :: Ident
deriving (Int -> Ident -> ShowS
[Ident] -> ShowS
Ident -> String
(Int -> Ident -> ShowS)
-> (Ident -> String) -> ([Ident] -> ShowS) -> Show Ident
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Ident -> ShowS
showsPrec :: Int -> Ident -> ShowS
$cshow :: Ident -> String
show :: Ident -> String
$cshowList :: [Ident] -> ShowS
showList :: [Ident] -> ShowS
Show, Ident -> Ident -> Bool
(Ident -> Ident -> Bool) -> (Ident -> Ident -> Bool) -> Eq Ident
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Ident -> Ident -> Bool
== :: Ident -> Ident -> Bool
$c/= :: Ident -> Ident -> Bool
/= :: Ident -> Ident -> Bool
Eq, Eq Ident
Eq Ident =>
(Ident -> Ident -> Ordering)
-> (Ident -> Ident -> Bool)
-> (Ident -> Ident -> Bool)
-> (Ident -> Ident -> Bool)
-> (Ident -> Ident -> Bool)
-> (Ident -> Ident -> Ident)
-> (Ident -> Ident -> Ident)
-> Ord Ident
Ident -> Ident -> Bool
Ident -> Ident -> Ordering
Ident -> Ident -> Ident
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Ident -> Ident -> Ordering
compare :: Ident -> Ident -> Ordering
$c< :: Ident -> Ident -> Bool
< :: Ident -> Ident -> Bool
$c<= :: Ident -> Ident -> Bool
<= :: Ident -> Ident -> Bool
$c> :: Ident -> Ident -> Bool
> :: Ident -> Ident -> Bool
$c>= :: Ident -> Ident -> Bool
>= :: Ident -> Ident -> Bool
$cmax :: Ident -> Ident -> Ident
max :: Ident -> Ident -> Ident
$cmin :: Ident -> Ident -> Ident
min :: Ident -> Ident -> Ident
Ord)
data Constructors where
Finite :: [DataCon] -> Constructors
Infinite :: [DataCon] -> Constructors
unknown :: DataCon
unknown :: DataCon
unknown = DataCon {dcIdent :: Ident
dcIdent = Ident
KUnknown, dcTypes :: [Type]
dcTypes = []}
unit :: DataCon
unit :: DataCon
unit = DataCon {dcIdent :: Ident
dcIdent = Ident
KUnit, dcTypes :: [Type]
dcTypes = []}
bool :: Bool -> DataCon
bool :: Bool -> DataCon
bool Bool
b = DataCon {dcIdent :: Ident
dcIdent = Bool -> Ident
KBool Bool
b, dcTypes :: [Type]
dcTypes = []}
natural :: Integer -> DataCon
natural :: Integer -> DataCon
natural Integer
n = DataCon {dcIdent :: Ident
dcIdent = Integer -> Ident
KNat Integer
n, dcTypes :: [Type]
dcTypes = []}
integer :: Integer -> DataCon
integer :: Integer -> DataCon
integer Integer
z = DataCon {dcIdent :: Ident
dcIdent = Integer -> Ident
KInt Integer
z, dcTypes :: [Type]
dcTypes = []}
char :: Char -> DataCon
char :: Char -> DataCon
char Char
c = DataCon {dcIdent :: Ident
dcIdent = Char -> Ident
KChar Char
c, dcTypes :: [Type]
dcTypes = []}
cons :: Ty.Type -> Ty.Type -> DataCon
cons :: Type -> Type -> DataCon
cons Type
tHead Type
tTail = DataCon {dcIdent :: Ident
dcIdent = Ident
KCons, dcTypes :: [Type]
dcTypes = [Type
tHead, Type
tTail]}
nil :: DataCon
nil :: DataCon
nil = DataCon {dcIdent :: Ident
dcIdent = Ident
KNil, dcTypes :: [Type]
dcTypes = []}
pair :: Ty.Type -> Ty.Type -> DataCon
pair :: Type -> Type -> DataCon
pair Type
a Type
b = DataCon {dcIdent :: Ident
dcIdent = Ident
KPair, dcTypes :: [Type]
dcTypes = [Type
a, Type
b]}
left :: Ty.Type -> DataCon
left :: Type -> DataCon
left Type
tl = DataCon {dcIdent :: Ident
dcIdent = Ident
KLeft, dcTypes :: [Type]
dcTypes = [Type
tl]}
right :: Ty.Type -> DataCon
right :: Type -> DataCon
right Type
tr = DataCon {dcIdent :: Ident
dcIdent = Ident
KRight, dcTypes :: [Type]
dcTypes = [Type
tr]}
tyDataCons :: Ty.Type -> Ty.TyDefCtx -> Constructors
tyDataCons :: Type -> TyDefCtx -> Constructors
tyDataCons Type
ty TyDefCtx
ctx = Type -> Constructors
tyDataConsHelper (Type -> Constructors) -> Type -> Constructors
forall a b. (a -> b) -> a -> b
$ Type -> TyDefCtx -> Type
resolveAlias Type
ty TyDefCtx
ctx
resolveAlias :: Ty.Type -> Ty.TyDefCtx -> Ty.Type
resolveAlias :: Type -> TyDefCtx -> Type
resolveAlias (Ty.TyUser String
name [Type]
args) TyDefCtx
ctx = case String -> TyDefCtx -> Maybe TyDefBody
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup String
name TyDefCtx
ctx of
Maybe TyDefBody
Nothing -> String -> Type
forall a. HasCallStack => String -> a
error (String -> Type) -> String -> Type
forall a b. (a -> b) -> a -> b
$ TyDefCtx -> String
forall a. Show a => a -> String
show TyDefCtx
ctx String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"\nType definition not found for: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ShowS
forall a. Show a => a -> String
show String
name
Just (Ty.TyDefBody [String]
_argNames [Type] -> Type
typeCon) -> Type -> TyDefCtx -> Type
resolveAlias ([Type] -> Type
typeCon [Type]
args) TyDefCtx
ctx
resolveAlias Type
t TyDefCtx
_ = Type
t
tyDataConsHelper :: Ty.Type -> Constructors
tyDataConsHelper :: Type -> Constructors
tyDataConsHelper (Type
a Ty.:*: Type
b) = [DataCon] -> Constructors
Finite [Type -> Type -> DataCon
pair Type
a Type
b]
tyDataConsHelper (Type
l Ty.:+: Type
r) = [DataCon] -> Constructors
Finite [Type -> DataCon
left Type
l, Type -> DataCon
right Type
r]
tyDataConsHelper t :: Type
t@(Ty.TyList Type
a) = [DataCon] -> Constructors
Finite [DataCon
nil, Type -> Type -> DataCon
cons Type
a Type
t]
tyDataConsHelper Type
Ty.TyVoid = [DataCon] -> Constructors
Finite []
tyDataConsHelper Type
Ty.TyUnit = [DataCon] -> Constructors
Finite [DataCon
unit]
tyDataConsHelper Type
Ty.TyBool = [DataCon] -> Constructors
Finite [Bool -> DataCon
bool Bool
True, Bool -> DataCon
bool Bool
False]
tyDataConsHelper Type
Ty.TyN = [DataCon] -> Constructors
Infinite ([DataCon] -> Constructors) -> [DataCon] -> Constructors
forall a b. (a -> b) -> a -> b
$ (Integer -> DataCon) -> [Integer] -> [DataCon]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> DataCon
natural [Integer
0, Integer
1 ..]
tyDataConsHelper Type
Ty.TyZ = [DataCon] -> Constructors
Infinite ([DataCon] -> Constructors) -> [DataCon] -> Constructors
forall a b. (a -> b) -> a -> b
$ (Integer -> DataCon) -> [Integer] -> [DataCon]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> DataCon
integer ([Integer] -> [DataCon]) -> [Integer] -> [DataCon]
forall a b. (a -> b) -> a -> b
$ Integer
0 Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: [Integer
y | Integer
x <- [Integer
1 ..], Integer
y <- [Integer
x, -Integer
x]]
tyDataConsHelper Type
Ty.TyF = [DataCon] -> Constructors
Infinite []
tyDataConsHelper Type
Ty.TyQ = [DataCon] -> Constructors
Infinite []
tyDataConsHelper Type
Ty.TyC =
[DataCon] -> Constructors
Infinite ([DataCon] -> Constructors) -> [DataCon] -> Constructors
forall a b. (a -> b) -> a -> b
$
(Char -> DataCon) -> String -> [DataCon]
forall a b. (a -> b) -> [a] -> [b]
map Char -> DataCon
char (String -> [DataCon]) -> String -> [DataCon]
forall a b. (a -> b) -> a -> b
$
String
alphanum String -> ShowS
forall a. [a] -> [a] -> [a]
++ (String
allUnicodeNicelyOrdered String -> ShowS
forall a. Eq a => [a] -> [a] -> [a]
\\ String
alphanum)
where
allUnicodeNicelyOrdered :: String
allUnicodeNicelyOrdered = [(Int -> Char
forall a. Enum a => Int -> a
toEnum Int
32) .. (Int -> Char
forall a. Enum a => Int -> a
toEnum Int
126)] String -> ShowS
forall a. [a] -> [a] -> [a]
++ [(Int -> Char
forall a. Enum a => Int -> a
toEnum Int
161) .. Char
forall a. Bounded a => a
maxBound] String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
forall a. Bounded a => a
minBound .. (Int -> Char
forall a. Enum a => Int -> a
toEnum Int
31)] String -> ShowS
forall a. [a] -> [a] -> [a]
++ [(Int -> Char
forall a. Enum a => Int -> a
toEnum Int
127) .. (Int -> Char
forall a. Enum a => Int -> a
toEnum Int
160)]
alphanum :: String
alphanum = [Char
'a' .. Char
'z'] String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
'A' .. Char
'Z'] String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
'0' .. Char
'9']
tyDataConsHelper Type
_ = [DataCon] -> Constructors
Infinite [DataCon
unknown]
newName :: (Member Fresh r) => Sem r (Name ATerm)
newName :: forall (r :: EffectRow). Member Fresh r => Sem r (Name ATerm)
newName = Name ATerm -> Sem r (Name ATerm)
forall (r :: EffectRow) x.
Member Fresh r =>
Name x -> Sem r (Name x)
fresh (Name ATerm -> Sem r (Name ATerm))
-> Name ATerm -> Sem r (Name ATerm)
forall a b. (a -> b) -> a -> b
$ String -> Name ATerm
forall a. String -> Name a
s2n String
""
newVar :: (Member Fresh r) => Ty.Type -> Sem r TypedVar
newVar :: forall (r :: EffectRow). Member Fresh r => Type -> Sem r TypedVar
newVar Type
types = do
Name ATerm
names <- Sem r (Name ATerm)
forall (r :: EffectRow). Member Fresh r => Sem r (Name ATerm)
newName
TypedVar -> Sem r TypedVar
forall a. a -> Sem r a
forall (m :: * -> *) a. Monad m => a -> m a
return (TypedVar -> Sem r TypedVar) -> TypedVar -> Sem r TypedVar
forall a b. (a -> b) -> a -> b
$ (Name ATerm, Type) -> TypedVar
TypedVar (Name ATerm
names, Type
types)
newNames :: (Member Fresh r) => Int -> Sem r [Name ATerm]
newNames :: forall (r :: EffectRow).
Member Fresh r =>
Int -> Sem r [Name ATerm]
newNames Int
i = Int -> Sem r (Name ATerm) -> Sem r [Name ATerm]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
i Sem r (Name ATerm)
forall (r :: EffectRow). Member Fresh r => Sem r (Name ATerm)
newName
newVars :: (Member Fresh r) => [Ty.Type] -> Sem r [TypedVar]
newVars :: forall (r :: EffectRow).
Member Fresh r =>
[Type] -> Sem r [TypedVar]
newVars [Type]
types = do
[Name ATerm]
names <- Int -> Sem r [Name ATerm]
forall (r :: EffectRow).
Member Fresh r =>
Int -> Sem r [Name ATerm]
newNames ([Type] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type]
types)
[TypedVar] -> Sem r [TypedVar]
forall a. a -> Sem r a
forall (m :: * -> *) a. Monad m => a -> m a
return ([TypedVar] -> Sem r [TypedVar]) -> [TypedVar] -> Sem r [TypedVar]
forall a b. (a -> b) -> a -> b
$ (Name ATerm -> Type -> TypedVar)
-> [Name ATerm] -> [Type] -> [TypedVar]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (((Name ATerm, Type) -> TypedVar) -> Name ATerm -> Type -> TypedVar
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (Name ATerm, Type) -> TypedVar
TypedVar) [Name ATerm]
names [Type]
types