{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE UndecidableInstances #-}
module Language.Ninja.AST.Rule
( Rule, makeRule
, ruleBind
, RuleConstraint
) where
import qualified Control.Lens as Lens
import Flow ((|>))
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM
import Data.Text (Text)
import Control.DeepSeq (NFData)
import Data.Hashable (Hashable)
import GHC.Generics (Generic)
import qualified Test.QuickCheck as QC
import qualified Test.SmallCheck.Series as SC
import GHC.Exts (Constraint)
import Data.Aeson ((.:), (.=))
import qualified Data.Aeson as Aeson
import qualified Language.Ninja.AST.Expr as AST
import qualified Language.Ninja.Misc as Misc
data Rule ann
= MkRule
{ _ruleAnn :: !ann
, _ruleBind :: !(HashMap Text (AST.Expr ann))
}
deriving (Eq, Show, Generic, Functor, Foldable, Traversable)
{-# INLINE makeRule #-}
makeRule :: (Monoid ann) => Rule ann
makeRule = MkRule
{ _ruleAnn = mempty
, _ruleBind = mempty
}
{-# INLINE ruleBind #-}
ruleBind :: Lens.Lens' (Rule ann) (HashMap Text (AST.Expr ann))
ruleBind = Lens.lens _ruleBind
$ \(MkRule {..}) x -> MkRule { _ruleBind = x, .. }
instance Misc.Annotated Rule where
annotation' f = Lens.lens _ruleAnn
$ \(MkRule {..}) x ->
MkRule { _ruleAnn = x
, _ruleBind = HM.map (fmap f) _ruleBind
, .. }
instance (Aeson.ToJSON ann) => Aeson.ToJSON (Rule ann) where
toJSON (MkRule {..})
= [ "ann" .= _ruleAnn
, "bind" .= _ruleBind
] |> Aeson.object
instance (Aeson.FromJSON ann) => Aeson.FromJSON (Rule ann) where
parseJSON = (Aeson.withObject "Rule" $ \o -> do
_ruleAnn <- (o .: "ann") >>= pure
_ruleBind <- (o .: "bind") >>= pure
pure (MkRule {..}))
instance ( QC.Arbitrary ann, RuleConstraint QC.Arbitrary ann
) => QC.Arbitrary (Rule ann) where
arbitrary = MkRule <$> QC.arbitrary <*> QC.arbitrary
instance (Hashable ann) => Hashable (Rule ann)
instance (NFData ann) => NFData (Rule ann)
instance ( Monad m, RuleConstraint (SC.Serial m) ann
) => SC.Serial m (Rule ann)
instance ( Monad m, RuleConstraint (SC.CoSerial m) ann
) => SC.CoSerial m (Rule ann)
type RuleConstraint (c :: * -> Constraint) (ann :: *)
= ( c (HashMap Text (AST.Expr ann))
, c ann
)