module Helium.StaticAnalysis.Miscellaneous.TypeConstraints where
import Top.Constraint
import Top.Constraint.Equality hiding ((.==.))
import Top.Constraint.Qualifier
import Top.Constraint.Polymorphism hiding ((.::.))
import Top.Constraint.Information
import Top.Interface.Basic
import Top.Interface.Substitution
import Top.Interface.TypeInference
import Top.Interface.Qualification
import Top.Types
import qualified Data.Map as M
type TypeConstraints info = [TypeConstraint info]
data TypeConstraint info
= TC1 (EqualityConstraint info)
| TC2 (ExtraConstraint info)
| TC3 (PolymorphismConstraint info)
| TCOper String (forall m . HasSubst m info => m ())
instance (HasBasic m info, HasTI m info, HasSubst m info, HasQual m info, PolyTypeConstraintInfo info)
=> Solvable (TypeConstraint info) m where
solveConstraint (TC1 c) = solveConstraint c
solveConstraint (TC2 c) = solveConstraint c
solveConstraint (TC3 c) = solveConstraint c
solveConstraint (TCOper _ f) = f
checkCondition (TC1 c) = checkCondition c
checkCondition (TC2 c) = checkCondition c
checkCondition (TC3 c) = checkCondition c
checkCondition (TCOper _ _) = return True
instance Show info => Show (TypeConstraint info) where
show (TC1 c) = show c
show (TC2 c) = show c
show (TC3 c) = show c
show (TCOper s _) = s
instance Substitutable (TypeConstraint info) where
sub |-> (TC1 c) = TC1 (sub |-> c)
sub |-> (TC2 c) = TC2 (sub |-> c)
sub |-> (TC3 c) = TC3 (sub |-> c)
_ |-> tc = tc
ftv (TC1 c) = ftv c
ftv (TC2 c) = ftv c
ftv (TC3 c) = ftv c
ftv _ = []
polySubst :: M.Map Int (Scheme Predicates) -> TypeConstraint info -> TypeConstraint info
polySubst schemeMap tc =
case tc of
TC3 (Instantiate tp sigma info) -> TC3 (Instantiate tp (f sigma) info)
TC3 (Skolemize tp (monos, sigma) info) -> TC3 (Skolemize tp (monos, f sigma) info)
_ -> tc
where
f :: Sigma Predicates -> Sigma Predicates
f sigma =
case sigma of
SigmaVar i -> maybe sigma SigmaScheme (M.lookup i schemeMap)
_ -> sigma
spreadFunction :: TypeConstraint info -> Maybe Int
spreadFunction tc =
case tc of
TC1 (Equality _ t2 _) -> spreadFromType t2
TC3 (Instantiate tp _ _) -> spreadFromType tp
TC3 (Skolemize tp _ _) -> spreadFromType tp
TC3 (Implicit t1 (_, _) _) -> spreadFromType t1
_ -> Nothing
spreadFromType :: Tp -> Maybe Int
spreadFromType (TVar i) = Just i
spreadFromType _ = Nothing
infix 3 .==., .===., .::., .:::., !::!, !:::!, .<=., .<==., !<=!, !<==!
lift :: Ord k => (a1 -> t1 -> t2 -> a) -> M.Map k a1
-> M.Map k [(t, t1)] -> (t -> t2) -> ([a], M.Map k [(t, t1)])
lift combinator as bs cf =
let constraints = concat (M.elems (M.intersectionWith f as bs))
rest = bs M.\\ as
f a list = [ (a `combinator` b) (cf name) | (name,b) <- list ]
in (constraints, rest)
(.==.) :: Show info => Tp -> Tp -> info -> TypeConstraint info
(t1 .==. t2) info = TC1 (Equality t1 t2 info)
(.===.) :: (Show info, Ord key) => M.Map key Tp -> M.Map key [(key,Tp)] -> (key -> info) -> ([TypeConstraint info], M.Map key [(key,Tp)])
(.===.) = lift (.==.)
(.::.) :: Show info => Tp -> TpScheme -> info -> TypeConstraint info
tp .::. ts = tp .<=. SigmaScheme ts
(.:::.) :: (Show info, Ord key) => M.Map key TpScheme -> M.Map key [(key,Tp)] -> (key -> info) -> ([TypeConstraint info], M.Map key [(key,Tp)])
(.:::.) = lift (flip (.::.))
(!::!) :: Tp -> TpScheme -> Tps -> info -> TypeConstraint info
(tp !::! ts) monos info = TC3 (Skolemize tp (monos, SigmaScheme ts) info)
(!:::!) :: (Show info, Ord key) => M.Map key TpScheme -> M.Map key Tp -> Tps -> (Tps -> key -> key -> info) -> ([TypeConstraint info], M.Map key Tp)
(as !:::! bs) monos info =
let op key tp (cs, fm) =
case M.lookup key as of
Just ts ->
let
key' = head (filter (==key) (M.keys as))
in ((tp !::! ts) monos (info monos key key') : cs, fm)
Nothing -> (cs, M.insert key tp fm)
in M.foldWithKey op ([], M.empty) bs
(.<=.) :: Show info => Tp -> Sigma Predicates -> info -> TypeConstraint info
(tp .<=. ts) info = TC3 (Instantiate tp ts info)
(.<==.) :: (Show info, Ord key) => M.Map key (Sigma Predicates) -> M.Map key [(key,Tp)] -> (key -> info) -> ([TypeConstraint info], M.Map key [(key,Tp)])
(.<==.) = lift (flip (.<=.))
(!<=!) :: Show info => Tps -> Tp -> Tp -> info -> TypeConstraint info
(!<=!) ms t1 t2 info = TC3 (Implicit t1 (ms, t2) info)
(!<==!) :: (Show info, Ord key) => Tps -> M.Map key Tp -> M.Map key [(key,Tp)] -> (key -> info) -> ([TypeConstraint info], M.Map key [(key,Tp)])
(!<==!) ms = lift (ms !<=!)
genConstraints :: Tps -> (key -> info) -> [(Int, (key, Tp))] -> TypeConstraints info
genConstraints monos infoF =
let f (sv, (key, tp)) = TC3 (Generalize sv (monos, tp) (infoF key))
in map f
predicate :: Predicate -> info -> TypeConstraint info
predicate p cinfo = TC2 (Prove p cinfo)