lhc-0.8: src/Grin/HPT/Solve.hs
{-# LANGUAGE OverloadedStrings #-}
module Grin.HPT.Solve
( HeapAnalysis(..)
, solve
) where
import Grin.Types
import qualified Data.Map as Map
import Control.Monad.Reader
import Control.Monad.Writer
--import System.IO
--import System.IO.Unsafe
import Grin.HPT.Environment
data HeapAnalysis
= HeapAnalysis (Map.Map Lhs Rhs)
type M a = ReaderT Equations (Writer (Endo Equations)) a
solve :: Equations -> (Int, HeapAnalysis)
solve eqs
= let iterate ls
= forM_ ls $ \(lhs,rhs) ->
do reducedRhs <- reduceEqs rhs
addReduced lhs reducedRhs
loop iter prev
= case {-traceOut ("\nIteration: " ++ show iter ++ "\n") $-} (execWriter (runReaderT (iterate (Map.toList eqs)) prev)) of
newDefs ->
let next = (Map.unionWith mappend prev (appEndo newDefs Map.empty))
in if prev == next then (iter, HeapAnalysis next) else loop (iter+1) next
in loop 1 (Map.map (const mempty) eqs)
--traceOut str v = unsafePerformIO (putStr str) `seq` v
isSubsetOf :: (Monoid a, Eq a) => a -> a -> Bool
a `isSubsetOf` b = b == (a `mappend` b)
addReduced :: Lhs -> Rhs -> M ()
addReduced lhs rhs
= do orig <- lookupEq lhs
{-let isNew = not (rhs `isSubsetOf` orig)
tag = if isNew then "+" else "-"
traceOut tag $-}
unless (rhs `isSubsetOf` orig) $ tell $ Endo $ Map.insertWith mappend lhs rhs
reduceEqs :: Rhs -> M Rhs
reduceEqs (Rhs rhs) = do rhs' <- mapM reduceEq rhs
return $ mconcat rhs'
reduceEq :: RhsValue -> M Rhs
reduceEq Base = return $ singleton Base
reduceEq (Heap hp) = return $ singleton $ Heap hp
reduceEq (Ident i) = lookupEq (VarEntry i)
reduceEq (Extract eq tag n)
= do Rhs eqs' <- lookupEq (VarEntry eq)
reduceEqs (mconcat [ args `nth` n | Tag t _ _ args <- eqs', t == tag ])
where nth [] n = mempty --error $ "reduceEq: ExtractVector: " ++ show (eqs, tag, n)
nth (x:xs) 0 = x
nth (x:xs) n = nth xs (n-1)
reduceEq (ExtractVector eq n)
= do Rhs eqs' <- lookupEq (VarEntry eq)
reduceEqs (mconcat [ args `nth` n | VectorTag args <- eqs' ])
where nth [] n = error $ "reduceEq: ExtractVector: " ++ show (eq, n)
nth (x:xs) 0 = x
nth (x:xs) n = nth xs (n-1)
{-
reduceEq (Tag fn FunctionNode 0 args)
= do args' <- mapM reduceEqs args
rets <- lookupEq (VarEntry fn)
return $ singleton (Tag fn FunctionNode 0 args') `mappend` rets
-}
reduceEq (Tag t nt missing args)
= do --args' <- mapM reduceEqs args
return $ singleton (Tag t nt missing args)
reduceEq (VectorTag args)
= do args' <- mapM reduceEqs args
return $ singleton (VectorTag args')
reduceEq (Eval i)
= do Rhs vals <- lookupEq (VarEntry i)
let f (Heap hp) = do Rhs rhs <- lookupEq (HeapEntry hp)
let worker (Tag fn FunctionNode 0 _) = lookupEq (VarEntry fn)
worker other = return $ singleton other
rets <- liftM mconcat $ mapM worker rhs
addReduced (HeapEntry hp) rets
return rets
f t = error $ "reduceEq: eval: " ++ show (t,i,vals)
liftM mconcat $ mapM f vals
reduceEq (Fetch i)
= do Rhs vals <- lookupEq (VarEntry i)
let f (Heap hp) = lookupEq (HeapEntry hp)
f Base = return mempty
f t = error $ "reduceEq: fetch: " ++ show (t,i,vals)
liftM mconcat $ mapM f vals
reduceEq (Apply a b)
= do Rhs vals <- lookupEq (VarEntry a)
let f (Tag func FunctionNode 1 args)
= reduceEq (Ident func)
f (Tag conc nt n args)
| n == 0 = return mempty
| otherwise = return $ singleton (Tag conc nt (n-1) (args ++ [singleton (Ident b)]))
f t = error $ "reduceEq: apply: " ++ show t
liftM mconcat $ mapM f vals
reduceEq (PartialApply a b)
= do Rhs vals <- lookupEq (VarEntry a)
let f (Tag tag nt n args)
| n == 0 = return mempty
| otherwise = return $ singleton (Tag tag nt (n-1) (args ++ [singleton (Ident b)]))
f t = error $ "reduceEq: apply: " ++ show t
liftM mconcat $ mapM f vals
reduceEq (Update hp val)
= do Rhs hps <- lookupEq (VarEntry hp)
valRhs <- lookupEq (VarEntry val)
forM_ hps $ \(Heap hp) -> addReduced (HeapEntry hp) valRhs
return mempty
lookupEq :: Lhs -> M Rhs
lookupEq lhs
= asks $ \eqs -> Map.findWithDefault mempty lhs eqs