module Top.Implementation.FastSubstitution where
import Top.Types
import Top.Implementation.General
import Top.Util.Embedding
import Top.Monad.Select
import Top.Interface.TypeInference
import Top.Interface.Basic
import Top.Interface.Substitution
import qualified Data.Map as M
import Data.Maybe
import Utils (internalError)
newtype GreedyState info = GreedyState { unGS :: FixpointSubstitution }
instance SolveState (GreedyState info) where
stateName _ = "Greedy Substitution State"
instance Show (GreedyState info) where
show gs = let FixpointSubstitution hs = unGS gs in show hs
instance Empty (GreedyState info) where
empty = GreedyState (FixpointSubstitution M.empty)
instance Embedded ClassSubst (GreedyState info) (GreedyState info) where embedding = idE
instance Embedded ClassSubst (Simple (GreedyState info) m b) (GreedyState info) where embedding = fromFstSimpleE embedding
instance ( MonadState s m
, HasBasic m info
, HasTI m info
, Embedded ClassSubst s (GreedyState info)
) =>
HasSubst (Select (GreedyState info) m) info where
makeSubstConsistent = return ()
findSubstForVar i = gets (lookupInt i . unGS)
fixpointSubst = gets unGS
unifyTerms info t1 t2 =
do t1' <- applySubst t1
t2' <- applySubst t2
synonyms <- select getTypeSynonyms
case mguWithTypeSynonyms synonyms t1' t2' of
Left _ -> select (addLabeledError unificationErrorLabel info)
Right (used,sub) ->
let mutp = equalUnderTypeSynonyms synonyms (sub |-> t1') (sub |-> t2')
utp = fromMaybe err mutp
err = internalError "Top.Solvers.GreedySubst" "greedyState" "types not unifiable"
f (FixpointSubstitution fm) =
FixpointSubstitution (M.fromList [ (i, lookupInt i sub) | i <- dom sub ] `M.union` fm)
g = writeExpandedType synonyms t2 utp
. writeExpandedType synonyms t1 utp
h = if used then g . f else f
in modify (GreedyState . h . unGS)
writeExpandedType :: OrderedTypeSynonyms -> Tp -> Tp -> FixpointSubstitution -> FixpointSubstitution
writeExpandedType synonyms = writeTypeType where
writeTypeType :: Tp -> Tp -> FixpointSubstitution -> FixpointSubstitution
writeTypeType atp utp original =
case (leftSpine atp,leftSpine utp) of
((TVar i,[]),_) ->
writeIntType i utp original
((TCon s,as),(TCon t,bs))
| s == t && not (isPhantomTypeSynonym synonyms s) ->
foldr (uncurry writeTypeType) original (zip as bs)
((TCon _, _),_) ->
case expandTypeConstructorOneStep (snd synonyms) atp of
Just atp' -> writeTypeType atp' utp original
Nothing -> internalError "Top.Solvers.GreedySubst" "writeTypeType" ("inconsistent types(1)" ++ show (atp, utp))
_ -> internalError "Top.Solvers.GreedySubst" "writeTypeType" ("inconsistent types(2)" ++ show (atp, utp))
writeIntType :: Int -> Tp -> FixpointSubstitution -> FixpointSubstitution
writeIntType i utp original@(FixpointSubstitution fm) =
case M.lookup i fm of
Nothing ->
case utp of
TVar j | i == j -> original
_ -> FixpointSubstitution (M.insert i utp fm)
Just atp ->
case (leftSpine atp,leftSpine utp) of
((TVar j,[]),_) -> writeIntType j utp original
((TCon s,as),(TCon t,bs)) | s == t -> foldr (uncurry writeTypeType) original (zip as bs)
((TCon _, _), _) -> case expandTypeConstructorOneStep (snd synonyms) atp of
Just atp' -> writeIntType i utp (FixpointSubstitution (M.insert i atp' fm))
Nothing ->
case expandTypeConstructorOneStep (snd synonyms) utp of
Just utp' ->
writeIntType i atp (FixpointSubstitution (M.insert i utp' fm))
Nothing ->
internalError "Top.Solvers.GreedySubst" "writeIntType" ("inconsistent types(1)" ++ show (i, utp, atp))
_ -> internalError "Top.Solvers.GreedySubst" "writeIntType" "inconsistent types(2)"