[add Util.Once and use it to ensure case constraints are not added multiple times
John Meacham <john@repetae.net>**20050923015802] adddir ./Util
addfile ./Util/Once.hs
hunk ./Grin/PointsToAnalysis.hs 28
+import Util.Once
+
hunk ./Grin/PointsToAnalysis.hs 510
-                conditionalRule (\x -> not $ or [ Set.member a (getNodes x) | (a,_) <- vs]) p' $ do self `isSuperSetOf` e'  -- TODO, should only fire once
+                once <- newOnce
+                conditionalRule (\x -> not $ or [ Set.member a (getNodes x) | (a,_) <- vs]) p' $ do runOnce once (self `isSuperSetOf` e')
hunk ./Main.hs 105
+-- | this is called on parsed, typechecked haskell code to convert it to the internal representation
+
hunk ./Util/Once.hs 1
+
+-- | a simple type that only lets an IO action happen once, caching its result.
+
+module Util.Once(Once, newOnce, runOnce) where
+
+import Data.IORef
+import Data.Dynamic
+
+newtype Once a = Once (IORef (Maybe a))
+    deriving(Typeable)
+
+
+-- | create a new Once object
+newOnce :: IO (Once a)
+newOnce = do
+    ref <- newIORef Nothing
+    return (Once ref)
+
+-- | execute the action at most once, always returning the same result
+runOnce :: Once a -> IO a -> IO a
+runOnce (Once ref) action = do
+    b <- readIORef ref
+    case b of
+        Just x -> return x
+        Nothing -> do
+            r <- action
+            writeIORef ref (Just r)
+            return r
+