diff --git a/default.nix b/default.nix index bbca114..b04780a 100644 --- a/default.nix +++ b/default.nix @@ -1,32 +1,7 @@ -let - hostPkgs = import {}; - pinnedPkgs = hostPkgs.fetchFromGitHub { - owner = "NixOS"; - repo = "nixpkgs-channels"; - rev = "ee28e35ba37ab285fc29e4a09f26235ffe4123e2"; - sha256 = "0a6xrqjj2ihkz1bizhy5r843n38xgimzw5s2mfc42kk2rgc95gw5"; - }; - -in { nixpkgs ? import pinnedPkgs {} - , compiler ? "ghc822" - , doProfiling ? false - , doBenchmark ? false }: - -let - - inherit (nixpkgs) pkgs; - - haskellPackages = let hpkgs = pkgs.haskell.packages.${compiler}; in - hpkgs // { - mkDerivation = args: hpkgs.mkDerivation (args // { - enableLibraryProfiling = doProfiling; - enableExecutableProfiling = doProfiling; - }); - }; - - pkg = haskellPackages.developPackage { +{ pkgs ? import {} }: pkgs.haskellPackages.developPackage { root = ./.; source-overrides = { + unordered-containers = "0.2.9.0"; # Use a particular commit from github insert-ordered-containers = pkgs.fetchFromGitHub { owner = "mightybyte"; @@ -35,10 +10,4 @@ let sha256 = "0l0g6ns5bcrcaij0wbdgc04qyl9h0vk1kx9lkzdkwj9v51l26azm"; }; }; - }; - - variant = if doBenchmark - then pkgs.haskell.lib.doBenchmark - else pkgs.lib.id; - -in variant pkg +} diff --git a/hnix.cabal b/hnix.cabal index 747ad3e..023243f 100644 --- a/hnix.cabal +++ b/hnix.cabal @@ -1,189 +1,155 @@ --- This file has been generated from package.yaml by hpack version 0.27.0. --- --- see: https://github.com/sol/hpack --- --- hash: 429fc2370bb078161c283b1238eb797ca1c03c46e4c1a2f68ac80937a901bb79 +Name: hnix +Version: 0.5.0 +Synopsis: Haskell implementation of the Nix language +Description: + Haskell implementation of the Nix language. -name: hnix -version: 0.5.0 -synopsis: Haskell implementation of the Nix language -description: Haskell implementation of the Nix language. -category: System, Data, Nix -homepage: https://github.com/jwiegley/hnix#readme -bug-reports: https://github.com/jwiegley/hnix/issues -author: John Wiegley -maintainer: johnw@newartisans.com -license: BSD3 -license-file: LICENSE -build-type: Simple -cabal-version: >= 1.10 +License: BSD3 +License-file: LICENSE +Author: John Wiegley +Maintainer: johnw@newartisans.com +Category: Data, Nix +Build-type: Simple +Cabal-version: >=1.10 +Homepage: http://github.com/jwiegley/hnix -extra-source-files: - README.md +Extra-source-files: data/*.nix -source-repository head - type: git - location: https://github.com/jwiegley/hnix +Flag Parsec + Description: Use parsec instead of Trifecta + Default: False -flag parsec - description: Use parsec instead of Trifecta - manual: True - default: False - -library - exposed-modules: - Nix - Nix.Atoms - Nix.Builtins - Nix.Eval - Nix.Expr - Nix.Expr.Shorthands - Nix.Expr.Types - Nix.Expr.Types.Annotated - Nix.Lint - Nix.Monad - Nix.Monad.Instance - Nix.Parser - Nix.Parser.Library - Nix.Parser.Operators - Nix.Pretty - Nix.Scope - Nix.Stack - Nix.StringOperations - Nix.TH - Nix.Thunk - Nix.Utils - Nix.Value - Nix.XML - other-modules: - Paths_hnix - hs-source-dirs: - src - ghc-options: -Wall - build-depends: - aeson +Library + Default-language: Haskell2010 + Exposed-modules: + Nix + Nix.Atoms + Nix.Scope + Nix.Stack + Nix.Eval + Nix.XML + Nix.Thunk + Nix.Lint + Nix.Monad + Nix.Monad.Instance + Nix.Builtins + Nix.Parser + Nix.Expr + Nix.Pretty + Nix.Parser.Operators + Nix.StringOperations + Nix.TH + Nix.Expr.Types + Nix.Expr.Types.Annotated + Other-modules: + Nix.Parser.Library + Nix.Expr.Shorthands + Nix.Utils + Build-depends: + base >= 4.9 && < 5 + , aeson , ansi-wl-pprint - , array >=0.4 && <0.6 - , base >=4.9 && <5 + , array >= 0.4 && < 0.6 , base16-bytestring - , bytestring , containers , cryptohash - , data-fix - , deepseq - , deriving-compat >=0.3 && <0.5 - , directory - , exceptions - , filepath - , insert-ordered-containers >=0.2.2 && <0.3 + , deriving-compat >= 0.3 && < 0.5 + , text + , bytestring , monadlist , mtl - , parsers >=0.10 + , transformers + , parsers >= 0.10 + , insert-ordered-containers >= 0.2.2 + , unordered-containers >= 0.2.9 && < 0.3 + , data-fix + , deepseq + , exceptions + , insert-ordered-containers >= 0.2.2 && < 0.3 , process + , directory + , filepath + , scientific + , semigroups >= 0.18 && < 0.19 + , split + , template-haskell , regex-tdfa , regex-tdfa-text - , scientific - , semigroups >=0.18 && <0.19 - , split - , syb - , template-haskell - , text , these - , transformers , unix - , unordered-containers >=0.2.9 && <0.3 + , syb , vector , xml if flag(parsec) - cpp-options: -DUSE_PARSEC - build-depends: - parsec + Cpp-options: -DUSE_PARSEC + Build-depends: parsec else - build-depends: - trifecta - default-language: Haskell2010 - -executable hnix - main-is: Main.hs - other-modules: - Paths_hnix - hs-source-dirs: - main + Build-depends: trifecta ghc-options: -Wall - build-depends: - ansi-wl-pprint - , base >=4.9 && <5 + +Executable hnix + Default-language: Haskell2010 + Main-is: Main.hs + Hs-source-dirs: main + Build-depends: + base >= 4.3 && < 5 + , hnix , containers + , ansi-wl-pprint , data-fix , deepseq - , exceptions - , hnix - , insert-ordered-containers >=0.2.2 && <0.3 - , mtl , optparse-applicative - , template-haskell , text + , template-haskell , transformers - , unordered-containers >=0.2.9 && <0.3 - default-language: Haskell2010 - -test-suite hnix-tests - type: exitcode-stdio-1.0 - main-is: Main.hs - other-modules: - EvalTests - NixLanguageTests - ParserTests - PrettyTests - Paths_hnix - hs-source-dirs: - tests - ghc-options: -Wall - build-depends: - Glob - , ansi-wl-pprint - , base >=4.9 && <5 - , containers - , data-fix - , exceptions , filepath + Ghc-options: -Wall + +Test-suite hnix-tests + Type: exitcode-stdio-1.0 + Hs-source-dirs: tests + Default-language: Haskell2010 + Main-is: Main.hs + Other-modules: + TestCommon + ParserTests + EvalTests + PrettyTests + NixLanguageTests + Build-depends: + base >= 4.3 && < 5 + , containers + , text + , data-fix , hnix - , insert-ordered-containers >=0.2.2 && <0.3 - , interpolate - , mtl + , tasty + , tasty-th + , tasty-hunit + , directory + , Glob + , filepath , process , split - , tasty - , tasty-hunit - , tasty-th - , template-haskell - , text , transformers + , interpolate + , insert-ordered-containers , unix - , unordered-containers >=0.2.9 && <0.3 - default-language: Haskell2010 + , unordered-containers -benchmark hnix-benchmarks - type: exitcode-stdio-1.0 - main-is: Main.hs - other-modules: - ParserBench - Paths_hnix - hs-source-dirs: - benchmarks - ghc-options: -Wall - build-depends: - ansi-wl-pprint - , base >=4.9 && <5 +Benchmark hnix-benchmarks + Type: exitcode-stdio-1.0 + Hs-source-dirs: benchmarks + Default-language: Haskell2010 + Main-is: Main.hs + Other-modules: + ParserBench + Build-depends: + base >= 4.3 && < 5 , containers - , criterion - , data-fix - , exceptions - , hnix - , insert-ordered-containers >=0.2.2 && <0.3 - , mtl - , template-haskell , text - , transformers - , unordered-containers >=0.2.9 && <0.3 - default-language: Haskell2010 + , hnix + , criterion + +source-repository head + type: git + location: git://github.com/jwiegley/hnix.git diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index 83ef102..8d6cdad 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -399,13 +399,13 @@ match_ pat str = force pat $ \pat' -> force str $ \str' -> case (pat', str') of -- jww (2018-04-05): We should create a fundamental type for compiled -- regular expressions if it turns out they get used often. - (NVStr p _, NVStr s _) -> return $ NVList $ + (NVStr p _, NVStr s _) -> return $ let re = makeRegex (encodeUtf8 p) :: Regex in case matchOnceText re (encodeUtf8 s) of Just ("", sarr, "") -> let s = map fst (elems sarr) in - map (valueThunk @m . flip NVStr mempty . decodeUtf8) + NVList $ map (valueThunk @m . flip NVStr mempty . decodeUtf8) (if length s > 1 then tail s else s) - _ -> [] + _ -> NVConstant NNull (p, s) -> throwError $ "builtins.match: expected a regex" ++ " and a string, but got: " ++ show (p, s) diff --git a/tests/EvalTests.hs b/tests/EvalTests.hs index 05bb43a..a4b606f 100644 --- a/tests/EvalTests.hs +++ b/tests/EvalTests.hs @@ -14,6 +14,7 @@ import Nix.Value import Test.Tasty import Test.Tasty.HUnit import Test.Tasty.TH +import TestCommon case_basic_sum = constantEqualStr "2" "1 + 1" @@ -71,6 +72,8 @@ case_function_recursive_sets = case_nested_with = constantEqualStr "2" "with { x = 1; }; with { x = 2; }; x" +case_match_failure_null = assertEvalMatchesNix "builtins.match \"ab\" \"abc\"" + ----------------------- tests :: TestTree diff --git a/tests/NixLanguageTests.hs b/tests/NixLanguageTests.hs index 19efb0d..5ee4afe 100644 --- a/tests/NixLanguageTests.hs +++ b/tests/NixLanguageTests.hs @@ -2,7 +2,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} -module NixLanguageTests (genTests) where +module NixLanguageTests where --(genTests) where import Control.Arrow ((&&&)) import Control.Exception @@ -23,11 +23,17 @@ import Nix.Utils import Nix.Stack import Nix.Value import Nix.XML +import System.Directory import System.Environment import System.FilePath import System.FilePath.Glob (compile, globDir1) +import System.IO +import System.Posix.Temp +import System.Process import Test.Tasty import Test.Tasty.HUnit +import Text.Printf +import TestCommon {- From (git://nix)/tests/lang.sh we see that @@ -49,7 +55,6 @@ From (git://nix)/tests/lang.sh we see that TEST_VAR=foo should be in all the environments # for eval-okay-getenv.nix -} - groupBy :: Ord k => (v -> k) -> [v] -> Map k [v] groupBy key = Map.fromListWith (++) . map (key &&& pure) @@ -94,13 +99,13 @@ assertParseFail file = do assertLangOk :: FilePath -> Assertion assertLangOk file = do - actual <- printNix <$> nixEvalFile (file ++ ".nix") + actual <- printNix <$> hnixEvalFile (file ++ ".nix") expected <- Text.readFile $ file ++ ".exp" assertEqual "" expected $ Text.pack (actual ++ "\n") assertLangOkXml :: FilePath -> Assertion assertLangOkXml file = do - actual <- toXML <$> nixEvalFile (file ++ ".nix") + actual <- toXML <$> hnixEvalFile (file ++ ".nix") expected <- Text.readFile $ file ++ ".exp.xml" assertEqual "" expected $ Text.pack actual @@ -127,13 +132,3 @@ assertEvalFail file = catch ?? (\(_ :: SomeException) -> return ()) $ do evalResult `seq` assertFailure $ file ++ " should not evaluate.\nThe evaluation result was `" ++ evalResult ++ "`." - -nixEvalFile :: FilePath -> IO (NValueNF (Lazy IO)) -nixEvalFile file = do - parseResult <- parseNixFileLoc file - case parseResult of - Failure err -> - error $ "Parsing failed for file `" ++ file ++ "`.\n" ++ show err - Success expression -> do - setEnv "TEST_VAR" "foo" - evalLoc (Just file) expression diff --git a/tests/TestCommon.hs b/tests/TestCommon.hs new file mode 100644 index 0000000..73607c9 --- /dev/null +++ b/tests/TestCommon.hs @@ -0,0 +1,50 @@ +module TestCommon where + +import Nix +import Nix.Monad +import Nix.Monad.Instance +import Nix.Parser +import Nix.Pretty +import System.Directory +import System.Environment +import System.IO +import System.Posix.Temp +import System.Process +import Test.Tasty.HUnit + +hnixEvalFile :: FilePath -> IO (NValueNF (Lazy IO)) +hnixEvalFile file = do + parseResult <- parseNixFileLoc file + case parseResult of + Failure err -> + error $ "Parsing failed for file `" ++ file ++ "`.\n" ++ show err + Success expression -> do + setEnv "TEST_VAR" "foo" + evalLoc (Just file) expression + +hnixEvalString :: String -> IO (NValueNF (Lazy IO)) +hnixEvalString expr = do + case parseNixString expr of + Failure err -> + error $ "Parsing failed for expressien `" ++ expr ++ "`.\n" ++ show err + Success expression -> eval Nothing expression + +nixEvalString :: String -> IO String +nixEvalString expr = do + (fp,h) <- mkstemp "nix-test-eval" + hPutStr h expr + hClose h + res <- nixEvalFile fp + removeFile fp + return res + +nixEvalFile :: FilePath -> IO String +nixEvalFile fp = do + readProcess "nix-instantiate" ["--eval", fp] "" + + +assertEvalMatchesNix :: String -> Assertion +assertEvalMatchesNix expr = do + hnixVal <- (++"\n") . printNix <$> hnixEvalString expr + nixVal <- nixEvalString expr + assertEqual expr nixVal hnixVal