module Helium.StaticAnalysis.Inferencers.BindingGroupAnalysis where
import qualified Data.Graph as G
import qualified Data.Tree as G
import Helium.Syntax.UHA_Syntax
import Helium.StaticAnalysis.Miscellaneous.TypeConstraints
import Helium.StaticAnalysis.Miscellaneous.ConstraintInfo
import Top.Types
import Top.Ordering.Tree
import qualified Data.Map as M
type Assumptions = M.Map Name [(Name,Tp)]
type PatternAssumptions = M.Map Name Tp
type Monos = Tps
noAssumptions :: M.Map Name a
noAssumptions = M.empty
listToAssumptions :: [(Name, Tp)] -> Assumptions
listToAssumptions list =
foldr combine noAssumptions [ M.fromList [(n, [tuple])] | tuple@(n, _) <- list ]
combine :: Assumptions -> Assumptions -> Assumptions
combine = M.unionWith (++)
single :: Name -> Tp -> Assumptions
single n t = M.singleton n [(n,t)]
type BindingGroups = [BindingGroup]
type BindingGroup = (PatternAssumptions, Assumptions, ConstraintSets)
type InheritedBDG = [(Names, (Monos, Int))]
emptyBindingGroup :: BindingGroup
emptyBindingGroup =
(noAssumptions, noAssumptions, [])
combineBindingGroup :: BindingGroup -> BindingGroup -> BindingGroup
combineBindingGroup (e1,a1,c1) (e2,a2,c2) =
(e1 `M.union` e2, a1 `combine` a2, c1++c2)
concatBindingGroups :: BindingGroups -> BindingGroup
concatBindingGroups = foldr combineBindingGroup emptyBindingGroup
type InputBDG = (Bool, Int, Int, Monos, M.Map Name TpScheme, Maybe (Assumptions, ConstraintSets), Int)
type OutputBDG = (Assumptions, ConstraintSet, InheritedBDG, Int, Int, M.Map Name (Sigma Predicates))
performBindingGroup :: InputBDG -> BindingGroups -> OutputBDG
performBindingGroup (topLevel, currentChunk, uniqueChunk, monoTypes, typeSignatures, chunkContext, unique) groups =
variableDependencies
where
bindingGroupAnalysis :: BindingGroups -> BindingGroups
bindingGroupAnalysis cs =
let explicits = M.keys typeSignatures
indexMap = concat (zipWith f cs [0..])
f (env,_,_) i = [ (n,i) | n <- M.keys env, n `notElem` explicits ]
edges = concat (zipWith f' cs [0..])
f' (_,ass,_) i = [ (i,j)| n <- M.keys ass, (n',j) <- indexMap, n==n' ]
list = topSort (length cs1) edges
in map (concatBindingGroups . map (cs !!)) list
chunkedBindingGroups :: [(Int, BindingGroup)]
chunkedBindingGroups =
zip [uniqueChunk..] (bindingGroupAnalysis groups) ++
case chunkContext of
Nothing -> []
Just (a, c) -> [(currentChunk, (M.empty, a, c))]
variableDependencies :: OutputBDG
variableDependencies =
let (aset, cset, mt, newUnique, fm) = foldr op initial chunkedBindingGroups
in (aset, cset, mt, uniqueChunk + length groups, newUnique, fm)
where
initial = (noAssumptions, emptyTree, [], unique, M.empty)
op (cnr, (e, a, c)) (aset, cset, mt, un, fm) =
let (cset1,e' ) = (typeSignatures !:::! e) monoTypes cinfoBindingGroupExplicitTypedBinding
(cset2,a' ) = (typeSignatures .:::. a) (cinfoBindingGroupExplicit monoTypes (M.keys e))
(cset3,a'' ) = (e' .===. a') cinfoSameBindingGroup
implicits = zip [un..] (M.assocs e')
implicitsFM = M.fromList [ (name, SigmaVar sv) | (sv, (name, _)) <- implicits ]
cset4 = genConstraints monoTypes cinfoGeneralize implicits
(cset5, aset') = (implicitsFM .<==. aset) cinfoBindingGroupImplicit
monomorphic = not topLevel
constraintTree =
StrictOrder
( (if monomorphic then id else Chunk cnr)
$ StrictOrder
( (cset1 ++ cset2 ++ cset3) .>>. Node (reverse c) )
(listTree cset4))
(cset5 .>>. cset)
in
( a'' `combine` aset'
, constraintTree
, (M.keys e, (M.elems e', if monomorphic then currentChunk else cnr)) : mt
, un + M.size e'
, implicitsFM `M.union` fm
)
findMono :: Name -> InheritedBDG -> Monos
findMono n = let p = elem n . fst
in fst . snd . head . filter p
getMonos :: TypeConstraints info -> Monos
getMonos tcs = [ TVar i | tc <- tcs, i <- ftv tc ]
findCurrentChunk :: Name -> InheritedBDG -> Int
findCurrentChunk n = let p = elem n . fst
in snd . snd . head . filter p
topSort :: G.Vertex -> [G.Edge] -> [[G.Vertex]]
topSort n = map G.flatten . G.scc . G.buildG (0, n)