module Language.Fixpoint.Solver.UniqifyKVars (wfcUniqify) where
import Language.Fixpoint.Types
import Language.Fixpoint.Types.Visitor (mapKVarSubsts)
import qualified Data.HashMap.Strict as M
import Data.Foldable (foldl')
wfcUniqify :: SInfo a -> SInfo a
wfcUniqify fi = updateWfcs $ remakeSubsts fi
remakeSubsts :: SInfo a -> SInfo a
remakeSubsts fi = mapKVarSubsts (remakeSubst fi) fi
remakeSubst :: SInfo a -> KVar -> Subst -> Subst
remakeSubst fi k su = foldl' (updateSubst k) su (kvarDomain fi k)
updateSubst :: KVar -> Subst -> Symbol -> Subst
updateSubst k (Su su) sym
= case M.lookup sym su of
Just z -> Su $ M.delete sym $ M.insert ksym z su
Nothing -> Su $ M.insert ksym (eVar sym) su
where
kx = kv k
ksym = kArgSymbol sym kx
updateWfcs :: SInfo a -> SInfo a
updateWfcs fi = M.foldl' updateWfc fi (ws fi)
updateWfc :: SInfo a -> WfC a -> SInfo a
updateWfc fi w = fi'' { ws = M.insert k w' (ws fi) }
where
w' = updateWfCExpr (subst su) w''
w'' = w { wenv = insertsIBindEnv newIds mempty, wrft = (v', t, k) }
(_, fi'') = newTopBind v' (trueSortedReft t) fi'
(fi', newIds) = foldl' (accumBindsIfValid k) (fi, []) (elemsIBindEnv $ wenv w)
(v, t, k) = wrft w
v' = kArgSymbol v (kv k)
su = mkSubst ((v, EVar v'):[(x, eVar $ kArgSymbol x (kv k)) | x <- kvarDomain fi k])
accumBindsIfValid :: KVar -> (SInfo a, [BindId]) -> BindId -> (SInfo a, [BindId])
accumBindsIfValid k (fi, ids) i = if renamable then accumBinds k (fi, ids) i else (fi, i : ids)
where
(_, sr) = lookupBindEnv i (bs fi)
renamable = isValidInRefinements (sr_sort sr)
accumBinds :: KVar -> (SInfo a, [BindId]) -> BindId -> (SInfo a, [BindId])
accumBinds k (fi, ids) i = (fi', i' : ids)
where
(oldSym, sr) = lookupBindEnv i (bs fi)
newSym = kArgSymbol oldSym (kv k)
(i', fi') = newTopBind newSym sr fi
newTopBind :: Symbol -> SortedReft -> SInfo a -> (BindId, SInfo a)
newTopBind x sr fi = (i', fi {bs = be'})
where
(i', be') = insertBindEnv x (top sr) (bs fi)
isValidInRefinements :: Sort -> Bool
isValidInRefinements FInt = True
isValidInRefinements FReal = True
isValidInRefinements FNum = False
isValidInRefinements FFrac = False
isValidInRefinements (FObj _) = True
isValidInRefinements (FVar _) = True
isValidInRefinements (FFunc _ _) = False
isValidInRefinements (FAbs _ t) = isValidInRefinements t
isValidInRefinements (FTC _) = True
isValidInRefinements (FApp _ _) = True