packages feed

data-fix-cse 0.0.1 → 0.0.2

raw patch · 3 files changed

+111/−2 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Fix.Cse: NextFrame :: FrameInfo
+ Data.Fix.Cse: NoFrame :: FrameInfo
+ Data.Fix.Cse: StartFrame :: FrameInfo
+ Data.Fix.Cse: StopFrame :: FrameInfo
+ Data.Fix.Cse: cseFramed :: (Eq (f Int), Ord (f Int), Traversable f) => (f Int -> FrameInfo) -> Fix f -> Dag f
+ Data.Fix.Cse: data FrameInfo
+ Data.Fix.Cse: instance Eq FrameInfo
+ Data.Fix.Cse: instance Ord FrameInfo
+ Data.Fix.Cse: instance Show FrameInfo

Files

data-fix-cse.cabal view
@@ -1,5 +1,5 @@ Name:            data-fix-cse-Version:         0.0.1+Version:         0.0.2 Cabal-Version:   >= 1.6 License:         BSD3 License-file:    LICENSE@@ -35,3 +35,4 @@       Data.Fix.Cse   Other-Modules:         Data.Fix.BiMap+      Data.Fix.BiMapFramed
+ src/Data/Fix/BiMapFramed.hs view
@@ -0,0 +1,70 @@+-- Establishing a bijection between the values of the type a and integers, with+-- the operations to retrieve the value given its key,+-- to find the key for the existing value, and to extend the +-- bijection with a new association.++-- The type 'a' of values should at least permit equality comparison;+-- In the present implementation, we require 'a' to be a member+-- of Ord.++-- There are many ways to implement bi-maps, for example, using hash tables,+-- or maps.+-- Our implementation uses Data.Map and Data.IntMap to record+-- both parts of the association.++module Data.Fix.BiMapFramed (+	      BiMap, empty, getDag,+	      lookup_key, +	      lookup_val,+	      startFrame, stopFrame, nextFrame,   +	      insert,+	      size,+	     )+    where++import Data.Maybe+import qualified Data.Map    as M+import qualified Data.IntMap as IM++data BiMap a = BiMap [M.Map a Int] (IM.IntMap a)++startFrame :: BiMap a -> BiMap a+startFrame (BiMap ms im) = BiMap (M.empty : ms) im++stopFrame :: BiMap a -> BiMap a+stopFrame (BiMap ms im) = BiMap (if (null ms) then [M.empty] else tail ms) im++nextFrame :: BiMap a -> BiMap a+nextFrame = startFrame . stopFrame++getDag :: BiMap a -> IM.IntMap a+getDag (BiMap _ a) = a++lookup_key :: Ord a => a -> BiMap a -> Maybe Int+lookup_key e (BiMap ms _) = case dropWhile isNothing $ fmap (M.lookup e) ms of+	Just a : [] -> Just a+	_           -> Nothing++-- Find a value for a key+lookup_val :: Int -> BiMap a -> a+lookup_val k (BiMap _ m) = m IM.! k++-- Insert the value and return the corresponding key+-- and the new map+-- Alas, Map interface does not have an operation to insert and find the index +-- at the same time (although such an operation is easily possible)+insert :: Ord a => a -> BiMap a -> (Int, BiMap a)+insert v (BiMap (m:ms) im) = (k, BiMap (m':ms) im')+ where m'  = M.insert v k m+       im' = IM.insert k v im+       k   = IM.size im++empty :: BiMap a+empty = BiMap [M.empty] (IM.empty)++instance Show a => Show (BiMap a) where+    show (BiMap _ m) =  "BiMap" ++ show (IM.toList m)++size :: BiMap a -> Int+size (BiMap _ m) = IM.size m+
src/Data/Fix/Cse.hs view
@@ -10,7 +10,16 @@     -- * Explicit sharing     letCse, Let(..),     letCata, letCataM,-    letWrapper+    letWrapper,++    -- * Framed sharing+    -- | If your EDSL contains imperative if-the-else blocks+    -- we need to use special version of the CSE. It allocates+    -- frames per each if- or else block. So that variables+    -- from different if-the-else branches don't get messed up.+    -- We need to allocate a new frame for each branch.+    -- We can do it with special structure @FrameInfo@.    +    FrameInfo(..), cseFramed ) where  import Control.Applicative hiding (empty)@@ -22,6 +31,7 @@ import Control.Monad.Trans.Class(lift)  import Data.Fix.BiMap+import qualified Data.Fix.BiMapFramed as F  type VarName = Int @@ -102,5 +112,33 @@   m <- get   case lookup_key e m of     Nothing -> let (k,m') = insert e m+               in  put m' >> return k+    Just k  -> return k+++-- | Marker type for creation frames of variables.+-- Start new frame when if-block starts, create next frame+-- when you go into the next branch of the same block (with else ir elif),+-- stop frame when leaving the if-then-else block. Use no frame for all +-- other expressions.+data FrameInfo = NoFrame | StartFrame | StopFrame | NextFrame+  deriving (Show, Eq, Ord)++-- | Performs common subexpression elimination with implicit sharing using information of frames.  +-- It doesn't share the variables in different branches of imperative if-then-else block.+cseFramed :: (Eq (f Int), Ord (f Int), Traversable f) => (f Int -> FrameInfo) -> Fix f -> Dag f+cseFramed getFrameInfo x = F.getDag $ execState (cataM (hashconsFramed getFrameInfo) x) F.empty++hashconsFramed :: (Ord a) => (a -> FrameInfo) -> a -> State (F.BiMap a) Int+hashconsFramed getFrameInfo e = do+  m' <- get+  let m = case getFrameInfo e of+        NoFrame    -> m'+        StartFrame -> F.startFrame m'+        StopFrame  -> F.stopFrame m'+        NextFrame  -> F.nextFrame m'      ++  case F.lookup_key e m of+    Nothing -> let (k,m') = F.insert e m                in  put m' >> return k     Just k  -> return k