Work from mightybyte: Minimize deps required, for building with GHCJS

This commit is contained in:
John Wiegley 2018-05-08 16:40:56 -07:00
parent 4c0d79e769
commit ba0dc19d2d
No known key found for this signature in database
GPG Key ID: C144D8F4F19FE630
14 changed files with 524 additions and 246 deletions

View File

@ -5,43 +5,49 @@
, doStrict ? false
, rev ? "255a833e841628c0b834575664eae373e28cdc27"
, sha256 ? "022xm1pf4fpjjy69g7qz6rpqnwpjcy1l0vj49m8xmgn553cs42ch"
# , nixpkgs ? import ((import <nixpkgs> {}).fetchFromGitHub {
# owner = "NixOS"; repo = "nixpkgs"; inherit rev sha256; }) {
, nixpkgs ? import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
inherit sha256; }) {
config.allowUnfree = true;
config.allowBroken = false;
}
# , nixpkgs ? import ((import <nixpkgs> {}).fetchFromGitHub {
# owner = "NixOS"; repo = "nixpkgs"; inherit rev sha256; }) {
}:
let inherit (nixpkgs) pkgs;
haskellPackages = pkgs.haskell.packages.${compiler}.override {
overrides = with pkgs.haskell.lib; self: super: rec {
serialise = dontCheck super.serialise;
overrides = with pkgs.haskell.lib; self: super:
if compiler == "ghcjs" then {} else
{
cryptohash-md5 = doJailbreak super.cryptohash-md5;
cryptohash-sha1 = doJailbreak super.cryptohash-sha1;
cryptohash-sha256 = doJailbreak super.cryptohash-sha256;
cryptohash-sha512 = doJailbreak super.cryptohash-sha512;
serialise = dontCheck super.serialise;
compact =
if compiler == "ghc842"
then doJailbreak super.compact
else super.compact;
compact =
if compiler == "ghc842"
then doJailbreak super.compact
else super.compact;
ghc-datasize =
if doProfiling
then null
else pkgs.haskell.lib.overrideCabal super.ghc-datasize (attrs: {
enableLibraryProfiling = false;
enableExecutableProfiling = false;
});
ghc-datasize =
if doProfiling
then null
else pkgs.haskell.lib.overrideCabal super.ghc-datasize (attrs: {
enableLibraryProfiling = false;
enableExecutableProfiling = false;
});
ghc-heap-view =
if doProfiling
then null
else pkgs.haskell.lib.overrideCabal super.ghc-heap-view (attrs: {
enableLibraryProfiling = false;
enableExecutableProfiling = false;
});
};
ghc-heap-view =
if doProfiling
then null
else pkgs.haskell.lib.overrideCabal super.ghc-heap-view (attrs: {
enableLibraryProfiling = false;
enableExecutableProfiling = false;
});
};
};
in haskellPackages.developPackage {
@ -52,11 +58,8 @@ in haskellPackages.developPackage {
modifier = drv: pkgs.haskell.lib.overrideCabal drv (attrs: {
testHaskellDepends = attrs.testHaskellDepends ++
[
pkgs.nix
haskellPackages.hpack
# haskellPackages.cabal-install
];
[ pkgs.nix
haskellPackages.hpack ];
enableLibraryProfiling = doProfiling;
enableExecutableProfiling = doProfiling;

View File

@ -2,7 +2,7 @@
--
-- see: https://github.com/sol/hpack
--
-- hash: 5dd7aaae46b28fedd3791ab641dc5093bf7e2bca549578aea96ec23ed791ed22
-- hash: 98a178891c03317cef1e5f7a984b3d7156bb38b0ca183bea91bab9acdaff4fb3
name: hnix
version: 0.5.0
@ -85,20 +85,16 @@ library
, ansi-wl-pprint
, array >=0.4 && <0.6
, base >=4.9 && <5
, base16-bytestring
, binary
, bytestring
, compact
, containers
, cryptohash
, data-fix
, deepseq
, deepseq >=1.4.2 && <1.5
, deriving-compat >=0.3 && <0.5
, directory
, exceptions
, filepath
, hashable
, haskeline
, hashing
, http-client
, http-client-tls
, http-types
@ -106,17 +102,15 @@ library
, lens-family-core
, lens-family-th
, logict
, megaparsec
, megaparsec >=6.0 && <6.6
, monadlist
, mtl
, optparse-applicative
, pretty-show
, process
, regex-tdfa
, regex-tdfa-text
, scientific
, semigroups >=0.18 && <0.19
, serialise
, split
, syb
, template-haskell
@ -128,11 +122,24 @@ library
, unordered-containers >=0.2.9 && <0.3
, vector
, xml
if flag(tracing)
cpp-options: -DENABLE_TRACING=1
if impl(ghc < 8.4.0) && !flag(profiling)
if !impl(ghcjs)
build-depends:
ghc-datasize
base16-bytestring
, cryptohash-md5
, cryptohash-sha1
, cryptohash-sha256
, cryptohash-sha512
, serialise
if impl(ghcjs)
build-depends:
hashable >=1.2.4 && <1.3
else
exposed-modules:
Nix.Options.Parser
build-depends:
hashable >=1.2.5 && <1.3
, haskeline
, pretty-show
default-language: Haskell2010
executable hnix
@ -148,26 +155,35 @@ executable hnix
, ansi-wl-pprint
, base >=4.9 && <5
, bytestring
, compact
, containers
, data-fix
, deepseq
, deepseq >=1.4.2 && <1.5
, exceptions
, filepath
, hashing
, haskeline
, hnix
, mtl
, optparse-applicative
, pretty-show
, repline
, serialise
, template-haskell
, text
, time
, transformers
, unordered-containers >=0.2.9 && <0.3
if flag(tracing)
cpp-options: -DENABLE_TRACING=1
if !impl(ghcjs)
build-depends:
base16-bytestring
, cryptohash-md5
, cryptohash-sha1
, cryptohash-sha256
, cryptohash-sha512
, serialise
if impl(ghcjs)
buildable: False
else
buildable: True
default-language: Haskell2010
test-suite hnix-tests
@ -191,14 +207,14 @@ test-suite hnix-tests
, ansi-wl-pprint
, base >=4.9 && <5
, bytestring
, compact
, containers
, data-fix
, deepseq
, deepseq >=1.4.2 && <1.5
, directory
, exceptions
, filepath
, generic-random
, hashing
, hnix
, interpolate
, megaparsec
@ -207,7 +223,6 @@ test-suite hnix-tests
, pretty-show
, process
, quickcheck-instances
, serialise
, split
, tasty
, tasty-hunit
@ -219,8 +234,18 @@ test-suite hnix-tests
, transformers
, unix
, unordered-containers >=0.2.9 && <0.3
if flag(tracing)
cpp-options: -DENABLE_TRACING=1
if !impl(ghcjs)
build-depends:
base16-bytestring
, cryptohash-md5
, cryptohash-sha1
, cryptohash-sha256
, cryptohash-sha512
, serialise
if impl(ghcjs)
buildable: False
else
buildable: True
default-language: Haskell2010
benchmark hnix-benchmarks
@ -236,22 +261,31 @@ benchmark hnix-benchmarks
ansi-wl-pprint
, base >=4.9 && <5
, bytestring
, compact
, containers
, criterion
, data-fix
, deepseq
, deepseq >=1.4.2 && <1.5
, exceptions
, filepath
, hashing
, hnix
, mtl
, optparse-applicative
, serialise
, template-haskell
, text
, time
, transformers
, unordered-containers >=0.2.9 && <0.3
if flag(tracing)
cpp-options: -DENABLE_TRACING=1
if !impl(ghcjs)
build-depends:
base16-bytestring
, cryptohash-md5
, cryptohash-sha1
, cryptohash-sha256
, cryptohash-sha512
, serialise
if impl(ghcjs)
buildable: False
else
buildable: True
default-language: Haskell2010

View File

@ -28,6 +28,7 @@ import Nix
import Nix.Convert
import qualified Nix.Eval as Eval
-- import Nix.Lint
import Nix.Options.Parser
import qualified Nix.Type.Env as Env
import qualified Nix.Type.Infer as HM
import Nix.Utils

View File

@ -13,28 +13,6 @@ description:
extra-source-files:
- README.md
dependencies:
- base >= 4.9 && < 5
- ansi-wl-pprint
- bytestring
- compact
- containers
- data-fix
- deepseq
- exceptions
- filepath
- mtl
- optparse-applicative
- serialise
- template-haskell
- text
- time
- transformers
- unordered-containers >= 0.2.9 && < 0.3
ghc-options:
- -Wall
flags:
tracing:
description: Enable full debug tracing
@ -51,6 +29,9 @@ flags:
manual: True
default: False
ghc-options:
- -Wall
when:
- condition: flag(optimize)
ghc-options:
@ -62,34 +43,62 @@ when:
- condition: flag(tracing)
cpp-options: -DENABLE_TRACING=1
dependencies:
- base >= 4.9 && < 5
- ansi-wl-pprint
- bytestring
- containers
- data-fix
- deepseq >= 1.4.2 && < 1.5
- exceptions
- filepath
- hashing
- mtl
- optparse-applicative
- template-haskell
- text
- time
- transformers
- unordered-containers >= 0.2.9 && < 0.3
when:
- condition: "os(linux) && impl(ghc < 8.2)"
dependencies:
- compact
when:
- condition: "!impl(ghcjs)"
dependencies:
- base16-bytestring
- cryptohash-md5
- cryptohash-sha1
- cryptohash-sha256
- cryptohash-sha512
- serialise
library:
source-dirs: src
dependencies:
- aeson
- ansi-wl-pprint
- array >= 0.4 && < 0.6
- base16-bytestring
- array >= 0.4 && < 0.6
- binary
- cryptohash
- deriving-compat >= 0.3 && < 0.5
- deriving-compat >= 0.3 && < 0.5
- directory
- hashable
- http-types
- http-client
- http-client-tls
- haskeline
- lens-family
- lens-family-core
- lens-family-th
- logict
- megaparsec
- megaparsec >= 6.0 && < 6.6
- monadlist
- pretty-show
- process
- regex-tdfa
- regex-tdfa-text
- scientific
- semigroups >= 0.18 && < 0.19
- semigroups >= 0.18 && < 0.19
- split
- syb
- these
@ -100,6 +109,18 @@ library:
- condition: impl(ghc < 8.4.0) && !flag(profiling)
dependencies:
- ghc-datasize
when:
- condition: "impl(ghcjs)"
then:
dependencies:
- hashable >= 1.2.4 && < 1.3
else:
exposed-modules:
- Nix.Options.Parser
dependencies:
- hashable >= 1.2.5 && < 1.3
- haskeline
- pretty-show
executables:
hnix:
@ -111,6 +132,12 @@ executables:
- pretty-show
- repline
- haskeline
when:
- condition: "impl(ghcjs)"
then:
buildable: false
else:
buildable: true
tests:
hnix-tests:
@ -135,6 +162,12 @@ tests:
- megaparsec
- tasty-quickcheck
- pretty-show
when:
- condition: "impl(ghcjs)"
then:
buildable: false
else:
buildable: true
benchmarks:
hnix-benchmarks:
@ -143,3 +176,9 @@ benchmarks:
dependencies:
- hnix
- criterion
when:
- condition: "impl(ghcjs)"
then:
buildable: false
else:
buildable: true

View File

@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
@ -5,7 +6,9 @@
module Nix.Atoms where
#if MIN_VERSION_serialise(0, 2, 0)
import Codec.Serialise
#endif
import Control.DeepSeq
import Data.Data
import Data.Hashable
@ -26,7 +29,11 @@ data NAtom
-- | Null values. There's only one of this variant.
| NNull
deriving (Eq, Ord, Generic, Typeable, Data, Show, Read, NFData,
Serialise, Hashable)
Hashable)
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise NAtom
#endif
-- | Translate an atom into its nix representation.
atomText :: NAtom -> Text

View File

@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
@ -7,6 +8,7 @@
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
@ -24,17 +26,29 @@ import Control.Monad
import Control.Monad.Catch
import Control.Monad.ListM (sortByM)
import Control.Monad.Reader (asks)
import qualified Crypto.Hash.MD5 as MD5
import qualified Crypto.Hash.SHA1 as SHA1
import qualified Crypto.Hash.SHA256 as SHA256
import qualified Crypto.Hash.SHA512 as SHA512
-- Using package imports here because there is a bug in cabal2nix that forces
-- us to put the hashing package in the unconditional dependency list.
-- See https://github.com/NixOS/cabal2nix/issues/348 for more info
#if MIN_VERSION_hashing(0, 1, 0)
import Crypto.Hash
import qualified "hashing" Crypto.Hash.MD5 as MD5
import qualified "hashing" Crypto.Hash.SHA1 as SHA1
import qualified "hashing" Crypto.Hash.SHA256 as SHA256
import qualified "hashing" Crypto.Hash.SHA512 as SHA512
#else
import Data.ByteString.Base16 as Base16
import qualified "cryptohash-md5" Crypto.Hash.MD5 as MD5
import qualified "cryptohash-sha1" Crypto.Hash.SHA1 as SHA1
import qualified "cryptohash-sha256" Crypto.Hash.SHA256 as SHA256
import qualified "cryptohash-sha512" Crypto.Hash.SHA512 as SHA512
#endif
import qualified Data.Aeson as A
import qualified Data.Aeson.Encoding as A
import Data.Align (alignWith)
import Data.Array
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.ByteString.Base16 as Base16
import qualified Data.ByteString.Lazy as LBS
import Data.Char (isDigit)
import Data.Coerce
@ -127,12 +141,15 @@ builtinsList = sequence [
, add0 Normal "currentSystem" currentSystem
, add0 Normal "currentTime" currentTime_
, add2 Normal "deepSeq" deepSeq
#if MIN_VERSION_base(4, 10, 0)
-- TODO Remove this CPP after the Lift instance for NExpr works with GHC 8.0
, add0 TopLevel "derivation" $(do
let f = "data/nix/corepkgs/derivation.nix"
addDependentFile f
Success expr <- runIO $ parseNixFile f
[| cata Eval.eval expr |]
)
#endif
, add TopLevel "derivationStrict" derivationStrict_
, add TopLevel "dirOf" dirOf
, add2 Normal "div" div_
@ -763,14 +780,33 @@ listToAttrs = fromValue @[NThunk m] >=> \l ->
hashString :: MonadNix e m => Text -> Text -> Prim m Text
hashString algo s = Prim $ do
hash <- case algo of
"md5" -> pure MD5.hash
"sha1" -> pure SHA1.hash
"sha256" -> pure SHA256.hash
"sha512" -> pure SHA512.hash
case algo of
"md5" -> pure $
#if MIN_VERSION_hashing(0, 1, 0)
Text.pack $ show (hash (encodeUtf8 s) :: MD5.MD5)
#else
decodeUtf8 $ Base16.encode $ MD5.hash $ encodeUtf8 s
#endif
"sha1" -> pure $
#if MIN_VERSION_hashing(0, 1, 0)
Text.pack $ show (hash (encodeUtf8 s) :: SHA1.SHA1)
#else
decodeUtf8 $ Base16.encode $ SHA1.hash $ encodeUtf8 s
#endif
"sha256" -> pure $
#if MIN_VERSION_hashing(0, 1, 0)
Text.pack $ show (hash (encodeUtf8 s) :: SHA256.SHA256)
#else
decodeUtf8 $ Base16.encode $ SHA256.hash $ encodeUtf8 s
#endif
"sha512" -> pure $
#if MIN_VERSION_hashing(0, 1, 0)
Text.pack $ show (hash (encodeUtf8 s) :: SHA512.SHA512)
#else
decodeUtf8 $ Base16.encode $ SHA512.hash $ encodeUtf8 s
#endif
_ -> throwError $ ErrorCall $ "builtins.hashString: "
++ "expected \"md5\", \"sha1\", \"sha256\", or \"sha512\", got " ++ show algo
pure $ decodeUtf8 $ Base16.encode $ hash $ encodeUtf8 s
placeHolder :: MonadNix e m => m (NValue m) -> m (NValue m)
placeHolder = fromValue @Text >=> \_ -> do

View File

@ -5,29 +5,34 @@ module Nix.Cache where
import qualified Data.ByteString.Lazy as BS
import Nix.Expr.Types.Annotated
#ifdef __linux__
#if defined (__linux__) && MIN_VERSION_base(4, 10, 0)
#define USE_COMPACT 1
#endif
#ifdef USE_COMPACT
import qualified Data.Compact as C
import qualified Data.Compact.Serialize as C
#else
#endif
#if MIN_VERSION_serialise(0, 2, 0)
import qualified Codec.Serialise as S
#endif
readCache :: FilePath -> IO NExprLoc
readCache path = do
#ifdef USE_COMPACT
#if USE_COMPACT
eres <- C.unsafeReadCompact path
case eres of
Left err -> error $ "Error reading cache file: " ++ err
Right expr -> return $ C.getCompact expr
#else
#if MIN_VERSION_serialise(0, 2, 0)
eres <- S.deserialiseOrFail <$> BS.readFile path
case eres of
Left err -> error $ "Error reading cache file: " ++ show err
Right expr -> return expr
#else
error "readCache not implemented for this platform"
#endif
#endif
writeCache :: FilePath -> NExprLoc -> IO ()
@ -35,5 +40,9 @@ writeCache path expr =
#ifdef USE_COMPACT
C.writeCompact path =<< C.compact expr
#else
#if MIN_VERSION_serialise(0, 2, 0)
BS.writeFile path (S.serialise expr)
#else
error "writeCache not implemented for this platform"
#endif
#endif

View File

@ -66,7 +66,9 @@ import Nix.Scope
import Nix.Thunk
import Nix.Utils
import Nix.Value
#if MIN_VERSION_haskeline(0, 4, 7)
import System.Console.Haskeline.MonadException hiding (catch)
#endif
import System.Directory
import System.Environment
import System.Exit (ExitCode (ExitSuccess))
@ -464,10 +466,12 @@ instance MonadCatch m => MonadCatch (Lazy m) where
instance MonadThrow m => MonadThrow (Lazy m) where
throwM = Lazy . throwM
#if MIN_VERSION_haskeline(0, 4, 7)
instance MonadException m => MonadException (Lazy m) where
controlIO f = Lazy $ controlIO $ \(RunIO run) ->
let run' = RunIO (fmap Lazy . run . runLazy)
in runLazy <$> f run'
#endif
instance (MonadFix m, MonadCatch m, MonadIO m, Alternative m,
MonadPlus m, Typeable m)

View File

@ -1,5 +1,6 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFoldable #-}
@ -26,8 +27,10 @@
-- | The nix expression type and supporting types.
module Nix.Expr.Types where
#if MIN_VERSION_serialise(0, 2, 0)
import Codec.Serialise (Serialise)
import qualified Codec.Serialise as Ser
#endif
import Control.Applicative
import Control.DeepSeq
import Control.Monad
@ -40,7 +43,9 @@ import Data.Eq.Deriving
import Data.Fix
import Data.Functor.Classes
import Data.Hashable
#if MIN_VERSION_hashable(1, 2, 5)
import Data.Hashable.Lifted
#endif
import Data.List (inits, tails)
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as NE
@ -60,12 +65,31 @@ import Nix.Utils
import Text.Megaparsec.Pos
import Text.Read.Deriving
import Text.Show.Deriving
#if MIN_VERSION_base(4, 10, 0)
import Type.Reflection (eqTypeRep)
import qualified Type.Reflection as Reflection
#endif
type VarName = Text
instance Hashable1 NonEmpty -- an unfortunate orphan
-- unfortunate orphans
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable1 NonEmpty
#endif
#if !MIN_VERSION_base(4, 10, 0)
instance Eq1 NonEmpty where
liftEq eq (a NE.:| as) (b NE.:| bs) = eq a b && liftEq eq as bs
instance Show1 NonEmpty where
liftShowsPrec shwP shwL p (a NE.:| as) = showParen (p > 5) $
shwP 6 a . showString " :| " . shwL as
#endif
#if !MIN_VERSION_binary(0, 8, 4)
instance Binary a => Binary (NE.NonEmpty a) where
get = fmap NE.fromList Bin.get
put = Bin.put . NE.toList
#endif
-- | The main nix expression type. This is polymorphic so that it can be made
-- a functor, which allows us to traverse expressions and map functions over
@ -113,24 +137,40 @@ data NExprF r
| NAssert !r !r
-- ^ Assert that the first returns true before evaluating the second.
deriving (Ord, Eq, Generic, Generic1, Typeable, Data, Functor,
Foldable, Traversable, Show, NFData, NFData1, Serialise,
Hashable, Hashable1)
Foldable, Traversable, Show, NFData,
Hashable)
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable1 NExprF
#endif
#if MIN_VERSION_deepseq(1, 4, 3)
instance NFData1 NExprF
#endif
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise r => Serialise (NExprF r)
#endif
-- | We make an `IsString` for expressions, where the string is interpreted
-- as an identifier. This is the most common use-case...
instance IsString NExpr where
fromString = Fix . NSym . fromString
#if MIN_VERSION_base(4, 10, 0)
instance Lift (Fix NExprF) where
lift = dataToExpQ $ \b ->
case Reflection.typeOf b `eqTypeRep` Reflection.typeRep @Text of
Just HRefl -> Just [| pack $(liftString $ unpack b) |]
Nothing -> Nothing
#endif
-- | The monomorphic expression type is a fixed point of the polymorphic one.
type NExpr = Fix NExprF
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise NExpr
#endif
-- | A single line of the bindings section of a let expression or of a set.
data Binding r
@ -140,8 +180,20 @@ data Binding r
-- ^ Using a name already in scope, such as @inherit x;@ which is shorthand
-- for @x = x;@ or @inherit (x) y;@ which means @y = x.y;@.
deriving (Generic, Generic1, Typeable, Data, Ord, Eq, Functor,
Foldable, Traversable, Show, NFData, NFData1, Serialise,
Hashable, Hashable1)
Foldable, Traversable, Show, NFData,
Hashable)
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable1 Binding
#endif
#if MIN_VERSION_deepseq(1, 4, 3)
instance NFData1 Binding
#endif
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise r => Serialise (Binding r)
#endif
-- | @Params@ represents all the ways the formal parameters to a
-- function can be represented.
@ -153,8 +205,19 @@ data Params r
-- bind to the set in the function body. The bool indicates whether it is
-- variadic or not.
deriving (Ord, Eq, Generic, Generic1, Typeable, Data, Functor, Show,
Foldable, Traversable, NFData, NFData1, Serialise,
Hashable, Hashable1)
Foldable, Traversable, NFData, Hashable)
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable1 Params
#endif
#if MIN_VERSION_deepseq(1, 4, 3)
instance NFData1 Params
#endif
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise r => Serialise (Params r)
#endif
-- This uses an association list because nix XML serialization preserves the
-- order of the param set.
@ -167,8 +230,10 @@ instance IsString (Params r) where
-- antiquoted (surrounded by ${...}) or plain (not antiquoted).
data Antiquoted (v :: *) (r :: *) = Plain !v | EscapedNewline | Antiquoted !r
deriving (Ord, Eq, Generic, Generic1, Typeable, Data, Functor, Foldable,
Traversable, Show, Read, NFData, NFData1, Serialise,
Hashable, Hashable1)
Traversable, Show, Read, NFData, Hashable)
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable v => Hashable1 (Antiquoted v)
instance Hashable2 Antiquoted where
liftHashWithSalt2 ha _ salt (Plain a) =
@ -177,6 +242,15 @@ instance Hashable2 Antiquoted where
salt `hashWithSalt` (1 :: Int)
liftHashWithSalt2 _ hb salt (Antiquoted b) =
hb (salt `hashWithSalt` (2 :: Int)) b
#endif
#if MIN_VERSION_deepseq(1, 4, 3)
instance NFData v => NFData1 (Antiquoted v)
#endif
#if MIN_VERSION_serialise(0, 2, 0)
instance (Serialise v, Serialise r) => Serialise (Antiquoted v r)
#endif
-- | An 'NString' is a list of things that are either a plain string
-- or an antiquoted expression. After the antiquotes have been evaluated,
@ -190,8 +264,19 @@ data NString r
-- their indentation will be stripped, but the amount stripped is
-- remembered.
deriving (Eq, Ord, Generic, Generic1, Typeable, Data, Functor, Foldable,
Traversable, Show, Read, NFData, NFData1, Serialise,
Hashable, Hashable1)
Traversable, Show, Read, NFData, Hashable)
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable1 NString
#endif
#if MIN_VERSION_deepseq(1, 4, 3)
instance NFData1 NString
#endif
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise r => Serialise (NString r)
#endif
-- | For the the 'IsString' instance, we use a plain doublequoted string.
instance IsString (NString r) where
@ -221,7 +306,10 @@ data NKeyName r
= DynamicKey !(Antiquoted (NString r) r)
| StaticKey !VarName !(Maybe SourcePos)
deriving (Eq, Ord, Generic, Typeable, Data, Show, Read, NFData,
Serialise, Hashable)
Hashable)
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise r => Serialise (NKeyName r)
instance Serialise Pos where
encode x = Ser.encode (unPos x)
@ -230,6 +318,7 @@ instance Serialise Pos where
instance Serialise SourcePos where
encode (SourcePos f l c) = Ser.encode f <> Ser.encode l <> Ser.encode c
decode = SourcePos <$> Ser.decode <*> Ser.decode <*> Ser.decode
#endif
instance Hashable Pos where
hashWithSalt salt x = hashWithSalt salt (unPos x)
@ -243,11 +332,13 @@ instance Generic1 NKeyName where
from1 = id
to1 = id
#if MIN_VERSION_deepseq(1, 4, 3)
instance NFData1 NKeyName where
liftRnf _ (StaticKey !_ !_) = ()
liftRnf _ (DynamicKey (Plain !_)) = ()
liftRnf _ (DynamicKey EscapedNewline) = ()
liftRnf k (DynamicKey (Antiquoted r)) = k r
#endif
-- | Most key names are just static text, so this instance is convenient.
instance IsString (NKeyName r) where
@ -258,11 +349,13 @@ instance Eq1 NKeyName where
liftEq _ (StaticKey a _) (StaticKey b _) = a == b
liftEq _ _ _ = False
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable1 NKeyName where
liftHashWithSalt h salt (DynamicKey a) =
liftHashWithSalt2 (liftHashWithSalt h) h (salt `hashWithSalt` (0 :: Int)) a
liftHashWithSalt _ salt (StaticKey n p) =
salt `hashWithSalt` (1 :: Int) `hashWithSalt` n `hashWithSalt` p
#endif
-- Deriving this instance automatically is not possible because @r@
-- occurs not only as last argument in @Antiquoted (NString r) r@
@ -297,7 +390,11 @@ type NAttrPath r = NonEmpty (NKeyName r)
-- | There are two unary operations: logical not and integer negation.
data NUnaryOp = NNeg | NNot
deriving (Eq, Ord, Generic, Typeable, Data, Show, Read, NFData,
Serialise, Hashable)
Hashable)
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise NUnaryOp
#endif
-- | Binary operators expressible in the nix language.
data NBinaryOp
@ -318,7 +415,11 @@ data NBinaryOp
| NConcat -- ^ List concatenation (++)
| NApp -- ^ Apply a function to an argument.
deriving (Eq, Ord, Generic, Typeable, Data, Show, Read, NFData,
Serialise, Hashable)
Hashable)
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise NBinaryOp
#endif
-- | Get the name out of the parameter (there might be none).
paramName :: Params r -> Maybe VarName

View File

@ -1,4 +1,5 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
@ -20,7 +21,9 @@ module Nix.Expr.Types.Annotated
, SourcePos(..), unPos, mkPos
)where
#if MIN_VERSION_serialise(0, 2, 0)
import Codec.Serialise
#endif
import Control.DeepSeq
import Data.Aeson (ToJSON(..), FromJSON(..))
import Data.Aeson.TH
@ -31,7 +34,9 @@ import Data.Fix
import Data.Function (on)
import Data.Functor.Compose
import Data.Hashable
#if MIN_VERSION_hashable(1, 2, 5)
import Data.Hashable.Lifted
#endif
import Data.Ord.Deriving
import Data.Semigroup
import Data.Text (Text, pack)
@ -48,9 +53,13 @@ data SrcSpan = SrcSpan
{ spanBegin :: SourcePos
, spanEnd :: SourcePos
}
deriving (Ord, Eq, Generic, Typeable, Data, Show, NFData, Serialise,
deriving (Ord, Eq, Generic, Typeable, Data, Show, NFData,
Hashable)
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise SrcSpan
#endif
-- | A type constructor applied to a type along with an annotation
--
-- Intended to be used with 'Fix':
@ -60,8 +69,19 @@ data Ann ann a = Ann
, annotated :: a
}
deriving (Ord, Eq, Data, Generic, Generic1, Typeable, Functor, Foldable,
Traversable, Read, Show, NFData, NFData1, Serialise,
Hashable, Hashable1)
Traversable, Read, Show, NFData, Hashable)
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable ann => Hashable1 (Ann ann)
#endif
#if MIN_VERSION_serialise(0, 2, 0)
instance (Serialise ann, Serialise a) => Serialise (Ann ann a)
#endif
#if MIN_VERSION_deepseq(1, 4, 3)
instance NFData ann => NFData1 (Ann ann)
#endif
$(deriveEq1 ''Ann)
$(deriveEq2 ''Ann)
@ -88,9 +108,18 @@ type NExprLocF = AnnF SrcSpan NExprF
-- | A nix expression with source location at each subexpression.
type NExprLoc = Fix NExprLocF
#if MIN_VERSION_hashable(1, 2, 5) && MIN_VERSION_deepseq(1, 4, 3)
-- Needs deepseq-1.4.3 because Compose requires NFData1
instance NFData NExprLoc
#endif
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise NExprLoc
#endif
#if MIN_VERSION_hashable(1, 2, 5)
instance Hashable NExprLoc
#endif
instance Binary SrcSpan
instance (Binary ann, Binary a) => Binary (Ann ann a)
@ -100,9 +129,11 @@ instance Binary NExprLoc
instance ToJSON SrcSpan
instance FromJSON SrcSpan
#if MIN_VERSION_serialise(0, 2, 0)
instance Serialise r => Serialise (Compose (Ann SrcSpan) NExprF r) where
encode (Compose (Ann ann a)) = encode ann <> encode a
decode = (Compose .) . Ann <$> decode <*> decode
#endif
pattern AnnE :: forall ann (g :: * -> *). ann
-> g (Fix (Compose (Ann ann) g)) -> Fix (Compose (Ann ann) g)

View File

@ -1,13 +1,7 @@
module Nix.Options where
import Control.Arrow (second)
import Data.Char (isDigit)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Time
import Options.Applicative hiding (ParserResult(..))
import Text.PrettyPrint.ANSI.Leijen hiding ((<$>))
data Options = Options
{ verbose :: Verbosity
@ -83,122 +77,3 @@ data Verbosity
| DebugInfo
| Vomit
deriving (Eq, Ord, Enum, Bounded, Show)
decodeVerbosity :: Int -> Verbosity
decodeVerbosity 0 = ErrorsOnly
decodeVerbosity 1 = Informational
decodeVerbosity 2 = Talkative
decodeVerbosity 3 = Chatty
decodeVerbosity 4 = DebugInfo
decodeVerbosity _ = Vomit
argPair :: Mod OptionFields (Text, Text) -> Parser (Text, Text)
argPair = option $ str >>= \s ->
case Text.findIndex (== '=') s of
Nothing -> errorWithoutStackTrace
"Format of --arg/--argstr in hnix is: name=expr"
Just i -> return $ second Text.tail $ Text.splitAt i s
nixOptions :: UTCTime -> Parser Options
nixOptions current = Options
<$> (fromMaybe ErrorsOnly <$>
optional
(option (do a <- str
if all isDigit a
then pure $ decodeVerbosity (read a)
else fail "Argument to -v/--verbose must be a number")
( short 'v'
<> long "verbose"
<> help "Verbose output")))
<*> switch
( long "trace"
<> help "Enable tracing code (even more can be seen if built with --flags=tracing)")
<*> switch
( long "thunks"
<> help "Enable reporting of thunk tracing as well as regular evaluation")
<*> switch
( long "values"
<> help "Enable reporting of value provenance in error messages")
<*> optional (strOption
( long "reduce"
<> help "When done evaluating, output the evaluated part of the expression to FILE"))
<*> switch
( long "reduce-sets"
<> help "Reduce set members that aren't used; breaks if hasAttr is used")
<*> switch
( long "reduce-lists"
<> help "Reduce list members that aren't used; breaks if elemAt is used")
<*> switch
( long "parse"
<> help "Whether to parse the file (also the default right now)")
<*> switch
( long "parse-only"
<> help "Whether to parse only, no pretty printing or checking")
<*> switch
( long "find"
<> help "If selected, find paths within attr trees")
<*> optional (strOption
( long "find-file"
<> help "Look up the given files in Nix's search path"))
<*> switch
( long "strict"
<> help "When used with --eval, recursively evaluate list elements and attributes")
<*> switch
( long "force"
<> help "Whether to force the results of evaluation to normal form")
<*> switch
( long "eval"
<> help "Whether to evaluate, or just pretty-print")
<*> switch
( long "json"
<> help "Print the resulting value as an JSON representation")
<*> switch
( long "xml"
<> help "Print the resulting value as an XML representation")
<*> optional (strOption
( short 'A'
<> long "attr"
<> help "Select an attribute from the top-level Nix expression being evaluated"))
<*> many (strOption
( short 'I'
<> long "include"
<> help "Add a path to the Nix expression search path"))
<*> switch
( long "check"
<> help "Whether to check for syntax errors after parsing")
<*> optional (strOption
( long "read"
<> help "Read in an expression tree from a binary cache"))
<*> switch
( long "cache"
<> help "Write out the parsed expression tree to a binary cache")
<*> switch
( long "repl"
<> help "After performing any indicated actions, enter the REPL")
<*> switch
( long "ignore-errors"
<> help "Continue parsing files, even if there are errors")
<*> optional (strOption
( short 'E'
<> long "expr"
<> help "Expression to parse or evaluate"))
<*> many (argPair
( long "arg"
<> help "Argument to pass to an evaluated lambda"))
<*> many (argPair
( long "argstr"
<> help "Argument string to pass to an evaluated lambda"))
<*> optional (strOption
( short 'f'
<> long "file"
<> help "Parse all of the files given in FILE; - means stdin"))
<*> option (parseTimeOrError True defaultTimeLocale "%Y/%m/%d %H:%M:%S" <$> str)
( long "now"
<> value current
<> help "Set current time for testing purposes")
<*> many (strArgument (metavar "FILE" <> help "Path of file to parse"))
nixOptionsInfo :: UTCTime -> ParserInfo Options
nixOptionsInfo current =
info (helper <*> nixOptions current)
(fullDesc <> progDesc "" <> header "hnix")

130
src/Nix/Options/Parser.hs Normal file
View File

@ -0,0 +1,130 @@
module Nix.Options.Parser where
import Control.Arrow (second)
import Data.Char (isDigit)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Time
import Nix.Options
import Options.Applicative hiding (ParserResult(..))
import Text.PrettyPrint.ANSI.Leijen hiding ((<$>))
decodeVerbosity :: Int -> Verbosity
decodeVerbosity 0 = ErrorsOnly
decodeVerbosity 1 = Informational
decodeVerbosity 2 = Talkative
decodeVerbosity 3 = Chatty
decodeVerbosity 4 = DebugInfo
decodeVerbosity _ = Vomit
argPair :: Mod OptionFields (Text, Text) -> Parser (Text, Text)
argPair = option $ str >>= \s ->
case Text.findIndex (== '=') s of
Nothing -> errorWithoutStackTrace
"Format of --arg/--argstr in hnix is: name=expr"
Just i -> return $ second Text.tail $ Text.splitAt i s
nixOptions :: UTCTime -> Parser Options
nixOptions current = Options
<$> (fromMaybe ErrorsOnly <$>
optional
(option (do a <- str
if all isDigit a
then pure $ decodeVerbosity (read a)
else fail "Argument to -v/--verbose must be a number")
( short 'v'
<> long "verbose"
<> help "Verbose output")))
<*> switch
( long "trace"
<> help "Enable tracing code (even more can be seen if built with --flags=tracing)")
<*> switch
( long "thunks"
<> help "Enable reporting of thunk tracing as well as regular evaluation")
<*> switch
( long "values"
<> help "Enable reporting of value provenance in error messages")
<*> optional (strOption
( long "reduce"
<> help "When done evaluating, output the evaluated part of the expression to FILE"))
<*> switch
( long "reduce-sets"
<> help "Reduce set members that aren't used; breaks if hasAttr is used")
<*> switch
( long "reduce-lists"
<> help "Reduce list members that aren't used; breaks if elemAt is used")
<*> switch
( long "parse"
<> help "Whether to parse the file (also the default right now)")
<*> switch
( long "parse-only"
<> help "Whether to parse only, no pretty printing or checking")
<*> switch
( long "find"
<> help "If selected, find paths within attr trees")
<*> optional (strOption
( long "find-file"
<> help "Look up the given files in Nix's search path"))
<*> switch
( long "strict"
<> help "When used with --eval, recursively evaluate list elements and attributes")
<*> switch
( long "force"
<> help "Whether to force the results of evaluation to normal form")
<*> switch
( long "eval"
<> help "Whether to evaluate, or just pretty-print")
<*> switch
( long "json"
<> help "Print the resulting value as an JSON representation")
<*> switch
( long "xml"
<> help "Print the resulting value as an XML representation")
<*> optional (strOption
( short 'A'
<> long "attr"
<> help "Select an attribute from the top-level Nix expression being evaluated"))
<*> many (strOption
( short 'I'
<> long "include"
<> help "Add a path to the Nix expression search path"))
<*> switch
( long "check"
<> help "Whether to check for syntax errors after parsing")
<*> optional (strOption
( long "read"
<> help "Read in an expression tree from a binary cache"))
<*> switch
( long "cache"
<> help "Write out the parsed expression tree to a binary cache")
<*> switch
( long "repl"
<> help "After performing any indicated actions, enter the REPL")
<*> switch
( long "ignore-errors"
<> help "Continue parsing files, even if there are errors")
<*> optional (strOption
( short 'E'
<> long "expr"
<> help "Expression to parse or evaluate"))
<*> many (argPair
( long "arg"
<> help "Argument to pass to an evaluated lambda"))
<*> many (argPair
( long "argstr"
<> help "Argument string to pass to an evaluated lambda"))
<*> optional (strOption
( short 'f'
<> long "file"
<> help "Parse all of the files given in FILE; - means stdin"))
<*> option (parseTimeOrError True defaultTimeLocale "%Y/%m/%d %H:%M:%S" <$> str)
( long "now"
<> value current
<> help "Set current time for testing purposes")
<*> many (strArgument (metavar "FILE" <> help "Path of file to parse"))
nixOptionsInfo :: UTCTime -> ParserInfo Options
nixOptionsInfo current =
info (helper <*> nixOptions current)
(fullDesc <> progDesc "" <> header "hnix")

View File

@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
@ -29,7 +30,9 @@ import Nix.Value
import Text.Megaparsec.Pos
import qualified Text.PrettyPrint.ANSI.Leijen as P
import Text.PrettyPrint.ANSI.Leijen hiding ((<$>))
#if MIN_VERSION_pretty_show(1, 6, 16)
import qualified Text.Show.Pretty as PS
#endif
renderFrames :: forall v e m.
(MonadReader e m, Has e Options,
@ -111,7 +114,11 @@ renderExpr _level longLabel shortLabel e@(Fix (Compose (Ann _ x))) = do
opts :: Options <- asks (view hasLens)
let rendered
| verbose opts >= DebugInfo =
#if MIN_VERSION_pretty_show(1, 6, 16)
text (PS.ppShow (stripAnnotation e))
#else
text (show (stripAnnotation e))
#endif
| verbose opts >= Chatty =
prettyNix (stripAnnotation e)
| otherwise =

View File

@ -19,6 +19,7 @@ import Data.Time
import GHC.Exts
import Nix.Lint
import Nix.Options
import Nix.Options.Parser
import Nix.Parser
import Nix.Pretty
import Nix.Utils