module Language.Nix.Binding ( Binding, binding, localName, reference ) where
import Control.DeepSeq
import Control.Lens
import Data.Maybe
import Data.String
import Distribution.Compat.ReadP as ReadP
import Distribution.Text
import GHC.Generics ( Generic )
import Language.Nix.Identifier
import Language.Nix.Path
import Prelude.Compat
import Test.QuickCheck
import Text.PrettyPrint as PP
declareLenses [d| data Binding = Bind { localName :: Identifier, reference :: Path }
deriving (Show, Eq, Ord, Generic)
|]
binding :: Iso' Binding (Identifier,Path)
binding = iso (\(Bind l r) -> (l,r)) (uncurry Bind)
instance NFData Binding where
rnf (Bind l r) = l `deepseq` rnf r
instance Arbitrary Binding where
arbitrary = review binding <$> arbitrary
instance Text Binding where
disp b = case (init ps, last ps) of
([], i') -> if i == i'
then text "inherit" <+> disp i'
else disp i <+> equals <+> disp p
(p', i') -> if i == i'
then text "inherit" <+> parens (disp (path # p')) <+> disp i'
else disp i <+> equals <+> disp p
where
(i, p) = view binding b
ps = view path p
parse = parseAssignment +++ parseInherit
instance IsString Binding where
fromString s = fromMaybe (error ("invalid Nix binding: " ++ s)) (simpleParse s)
parseAssignment :: ReadP r Binding
parseAssignment = do l <- skipSpaces >> parse
_ <- skipSpaces >> ReadP.char '='
r <- skipSpaces >> parse
return (binding # (l,r))
parseInherit :: ReadP r Binding
parseInherit = do _ <- skipSpaces >> ReadP.string "inherit"
p <- option [] $ between (skipSpaces >> ReadP.char '(')
(skipSpaces >> ReadP.char ')')
(skipSpaces >> view path <$> parse)
i <- skipSpaces >> parse
return (binding # (i, path # (p ++ [i])))