packages feed

rock 0.1.0.1 → 0.2.0.0

raw patch · 7 files changed

+63/−81 lines, 7 filesdep +containersPVP ok

version bump matches the API change (PVP)

Dependencies added: containers

API changes (from Hackage documentation)

- Rock.HashTag: class HashTag k
- Rock.HashTag: hashTagged :: HashTag k => k a -> a -> Int
- Rock.Hashed: data Hashed a
- Rock.Hashed: hashed :: HashTag f => f a -> a -> Hashed a
- Rock.Hashed: instance Data.Functor.Classes.Show1 Rock.Hashed.Hashed
- Rock.Hashed: instance Data.Hashable.Class.Hashable (Rock.Hashed.Hashed a)
- Rock.Hashed: instance GHC.Classes.Eq a => GHC.Classes.Eq (Rock.Hashed.Hashed a)
- Rock.Hashed: instance GHC.Classes.Ord a => GHC.Classes.Ord (Rock.Hashed.Hashed a)
- Rock.Hashed: instance GHC.Show.Show a => GHC.Show.Show (Rock.Hashed.Hashed a)
- Rock.Hashed: unhashed :: Hashed a -> a
- Rock.Traces: instance (GHC.Show.Show a, Data.Dependent.Sum.ShowTag f Rock.Hashed.Hashed) => GHC.Show.Show (Rock.Traces.ValueDeps f a)
- Rock.Traces: instance Data.Dependent.Sum.ShowTag f Rock.Hashed.Hashed => Data.Functor.Classes.Show1 (Rock.Traces.ValueDeps f)
+ Rock.Core: invalidateReverseDependencies :: GCompare f => f a -> ReverseDependencies f -> DMap f g -> (ReverseDependencies f, DMap f g)
+ Rock.Core: trackReverseDependencies :: GCompare f => MVar (ReverseDependencies f) -> Rules f -> Rules f
+ Rock.Core: type ReverseDependencies f = Map (Some f) (Set (Some f))
+ Rock.Traces: instance (Data.Dependent.Sum.ShowTag f Data.Functor.Identity.Identity, GHC.Show.Show a) => GHC.Show.Show (Rock.Traces.ValueDeps f a)
+ Rock.Traces: instance Data.Dependent.Sum.ShowTag f Data.Functor.Identity.Identity => Data.Functor.Classes.Show1 (Rock.Traces.ValueDeps f)
- Rock.Core: verifyTraces :: (GCompare f, HashTag f) => MVar (Traces f) -> GenRules (Writer TaskKind f) f -> Rules f
+ Rock.Core: verifyTraces :: (EqTag f Identity, GCompare f) => MVar (Traces f) -> GenRules (Writer TaskKind f) f -> Rules f
- Rock.Traces: ValueDeps :: !Hashed a -> !DMap f Hashed -> ValueDeps f a
+ Rock.Traces: ValueDeps :: !a -> !DMap f Identity -> ValueDeps f a
- Rock.Traces: [dependencies] :: ValueDeps f a -> !DMap f Hashed
+ Rock.Traces: [dependencies] :: ValueDeps f a -> !DMap f Identity
- Rock.Traces: [value] :: ValueDeps f a -> !Hashed a
+ Rock.Traces: [value] :: ValueDeps f a -> !a
- Rock.Traces: record :: (GCompare f, HashTag f) => f a -> a -> DMap f Identity -> Traces f -> Traces f
+ Rock.Traces: record :: GCompare f => f a -> a -> DMap f Identity -> Traces f -> Traces f
- Rock.Traces: verifyDependencies :: Monad m => (forall a'. f a' -> m (Hashed a')) -> ValueDeps f a -> m (Maybe a)
+ Rock.Traces: verifyDependencies :: (Monad m, EqTag f Identity) => (forall a'. f a' -> m a') -> ValueDeps f a -> m (Maybe a)

Files

CHANGELOG.md view
@@ -1,9 +1,14 @@ # Unreleased -# 0.1.0.0+# 0.2.0.0 -- Initial release+- Stop using hashes when verifying traces (gets rid of the `Rock.HashTag` and `Rock.Hashed` modules)+- Add reverse dependency tracking  # 0.1.0.1  - Fix base-4.12 compatibility++# 0.1.0.0++- Initial release
rock.cabal view
@@ -1,5 +1,5 @@ name:                rock-version:             0.1.0.1+version:             0.2.0.0 synopsis:            A build system for incremental, parallel, and demand-driven computations description:         See <https://www.github.com/ollef/rock> for more                      information and@@ -33,10 +33,9 @@   exposed-modules:                        Rock                        Rock.Core-                       Rock.HashTag-                       Rock.Hashed                        Rock.Traces   build-depends:       base >= 4.7 && < 5+                     , containers                      , dependent-map                      , dependent-sum                      , deriving-compat
src/Rock.hs view
@@ -1,9 +1,7 @@ module Rock   ( module Rock.Core-  , module Rock.HashTag   , Traces   ) where  import Rock.Core-import Rock.HashTag import Rock.Traces
src/Rock/Core.hs view
@@ -1,11 +1,11 @@ {-# language CPP #-} {-# language DefaultSignatures #-} {-# language DeriveFunctor #-}+{-# language FlexibleContexts #-} {-# language FlexibleInstances #-} {-# language FunctionalDependencies #-} {-# language GADTs #-} {-# language GeneralizedNewtypeDeriving #-}-{-# language MultiParamTypeClasses #-} {-# language RankNTypes #-} {-# language ScopedTypeVariables #-} {-# language UndecidableInstances #-}@@ -28,10 +28,12 @@ import qualified Control.Monad.Writer.Strict as Strict import Data.Dependent.Map(DMap, GCompare) import qualified Data.Dependent.Map as DMap+import Data.Dependent.Sum import Data.GADT.Compare+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Some -import Rock.Hashed-import Rock.HashTag import Rock.Traces(Traces) import qualified Rock.Traces as Traces @@ -276,9 +278,9 @@ -- were then. -- -- If all dependencies of a 'NonInput' query are the same, reuse the old result.--- The 'DMap' _can_ be reused if there are changes to 'Input' queries.+-- 'Input' queries are not reused. verifyTraces-  :: (GCompare f, HashTag f)+  :: (EqTag f Identity, GCompare f)   => MVar (Traces f)   -> GenRules (Writer TaskKind f) f   -> Rules f@@ -287,7 +289,7 @@   maybeValue <- case DMap.lookup key traces of     Nothing -> return Nothing     Just oldValueDeps ->-      Traces.verifyDependencies fetchHashed oldValueDeps+      Traces.verifyDependencies fetch oldValueDeps   case maybeValue of     Nothing -> do       ((value, taskKind), deps) <- track $ rules $ Writer key@@ -300,9 +302,6 @@             . Traces.record key value deps       return value     Just value -> return value-  where-    fetchHashed :: HashTag f => f a -> Task f (Hashed a)-    fetchHashed key' = hashed key' <$> fetch key'  data TaskKind   = Input -- ^ Used for tasks whose results can change independently of their fetched dependencies, i.e. inputs.@@ -348,3 +347,36 @@   result <- rules key   after key result   return result++type ReverseDependencies f = Map (Some f) (Set (Some f))++-- | Write reverse dependencies to the 'MVar'.+trackReverseDependencies+  :: GCompare f+  => MVar (ReverseDependencies f)+  -> Rules f+  -> Rules f+trackReverseDependencies reverseDepsVar rules key = do+  (res, deps) <- track $ rules key+  unless (DMap.null deps) $ do+    let newReverseDeps = Map.fromListWith (<>)+          [ (This depKey, Set.singleton $ This key)+          | depKey DMap.:=> _ <- DMap.toList deps+          ]+    liftIO $ modifyMVar_ reverseDepsVar $ pure . Map.unionWith (<>) newReverseDeps+  pure res++-- | @'invalidateReverseDependencies' key@ removes all keys reachable, by+-- reverse dependency, from @key@ from the input 'DMap'. It also returns the+-- reverse dependency map with those same keys removed.+invalidateReverseDependencies+  :: GCompare f+  => f a+  -> ReverseDependencies f+  -> DMap f g+  -> (ReverseDependencies f, DMap f g)+invalidateReverseDependencies key reverseDeps m =+  foldl'+    (\(reverseDeps', m') (This key') -> invalidateReverseDependencies key' reverseDeps' m')+    (Map.delete (This key) reverseDeps, DMap.delete key m)+    (Set.toList $ Map.findWithDefault mempty (This key) reverseDeps)
− src/Rock/HashTag.hs
@@ -1,19 +0,0 @@-module Rock.HashTag where--import Protolude---- | Hash the result of a @k@ query.------ A typical implementation looks like:------ @--- data Query a where---   ReadFile :: 'FilePath' -> Query 'Text'------ instance 'HashTag' Query where---   'hashTagged' query =---     case query of---       ReadFile {} -> 'hash'--- @-class HashTag k where-  hashTagged :: k a -> a -> Int
− src/Rock/Hashed.hs
@@ -1,30 +0,0 @@-module Rock.Hashed(Hashed, hashed, unhashed) where--import Protolude--import Data.Functor.Classes-import Text.Show--import Rock.HashTag--data Hashed a = Hashed !a !Int-  deriving (Show)--instance Eq a => Eq (Hashed a) where-  Hashed v1 h1 == Hashed v2 h2 = h1 == h2 && v1 == v2--instance Ord a => Ord (Hashed a) where-  compare (Hashed v1 _) (Hashed v2 _) = compare v1 v2--instance Show1 Hashed where-  liftShowsPrec showa _ d (Hashed a _) = showParen (d > 10)-    $ showString "Hashed " . showa 11 a--instance Hashable (Hashed a) where-  hashWithSalt s (Hashed _ h) = hashWithSalt s h--unhashed :: Hashed a -> a-unhashed (Hashed x _) = x--hashed :: HashTag f => f a -> a -> Hashed a-hashed k v = Hashed v $ hashTagged k v
src/Rock/Traces.hs view
@@ -1,3 +1,4 @@+{-# language FlexibleContexts #-} {-# language RankNTypes #-} {-# language StandaloneDeriving #-} {-# language TemplateHaskell #-}@@ -12,34 +13,31 @@ import Data.Functor.Classes import Text.Show.Deriving -import Rock.HashTag-import Rock.Hashed- data ValueDeps f a = ValueDeps-  { value :: !(Hashed a)-  , dependencies :: !(DMap f Hashed)+  { value :: !a+  , dependencies :: !(DMap f Identity)   }  return [] -deriving instance (Show a, ShowTag f Hashed) => Show (ValueDeps f a)+deriving instance (ShowTag f Identity, Show a) => Show (ValueDeps f a) -instance ShowTag f Hashed => Show1 (ValueDeps f) where+instance ShowTag f Identity => Show1 (ValueDeps f) where   liftShowsPrec = $(makeLiftShowsPrec ''ValueDeps)  type Traces f = DMap f (ValueDeps f)  verifyDependencies-  :: Monad m-  => (forall a'. f a' -> m (Hashed a'))+  :: (Monad m, EqTag f Identity)+  => (forall a'. f a' -> m a')   -> ValueDeps f a   -> m (Maybe a)-verifyDependencies fetchHash (ValueDeps hashedValue deps) = do+verifyDependencies fetch (ValueDeps value_ deps) = do   upToDate <- allM (DMap.toList deps) $ \(depKey :=> depValue) -> do-    depValue' <- fetchHash depKey-    return $ hash depValue == hash depValue'+    depValue' <- fetch depKey+    return $ eqTagged depKey depKey depValue $ Identity depValue'   return $ if upToDate-    then Just $ unhashed hashedValue+    then Just value_     else Nothing   where     allM :: Monad m => [a] -> (a -> m Bool) -> m Bool@@ -52,7 +50,7 @@         return False  record-  :: (GCompare f, HashTag f)+  :: GCompare f   => f a   -> a   -> DMap f Identity@@ -60,5 +58,4 @@   -> Traces f record k v deps   = DMap.insert k-  $ ValueDeps (hashed k v)-  $ DMap.mapWithKey (\k' (Identity v') -> hashed k' v') deps+  $ ValueDeps v deps