diff --git a/.github/workflows/Cabal-Linux.yml b/.github/workflows/Cabal-Linux.yml index 606adc371..768319ba1 100644 --- a/.github/workflows/Cabal-Linux.yml +++ b/.github/workflows/Cabal-Linux.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ghc: [ "8.10", "8.4" ] + ghc: [ "8.10", "8.6" ] steps: - name: "Git checkout" diff --git a/.github/workflows/On-Release-Cabal-Linux.yml b/.github/workflows/On-Release-Cabal-Linux.yml index b59b6a5af..330e12c5c 100644 --- a/.github/workflows/On-Release-Cabal-Linux.yml +++ b/.github/workflows/On-Release-Cabal-Linux.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: # Since CI by default tests boundary GHCs, test middle versions of GHCs - ghc: [ "8.8", "8.6"] + ghc: [ "8.8" ] steps: - name: "Git checkout" uses: actions/checkout@v2 diff --git a/ChangeLog.md b/ChangeLog.md index 38d31cb82..515940a81 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -142,6 +142,11 @@ * [(link)](https://github.com/haskell-nix/hnix/pull/878/files) `Nix.Pretty`: `mkNixDoc`: got unflipped. * [(link)](https://github.com/haskell-nix/hnix/pull/886/commits/381b0e5df9cc620a25533ff1c84045a4ea37a833) `Nix.Value`: Data constructor for `NValue' t f m a` changed (`NValue -> NValue'`). + + * [(link)](https://github.com/haskell-nix/hnix/pull/884/files) `Nix.Parser`: `Parser`: Data type was equivalent to `Either`, so became a type synonim for `Either`. + + * [(link)](https://github.com/haskell-nix/hnix/pull/884/files) `Nix.Thunk.Basic`: `instance MonadThunk (NThunkF m v) m v`: `queryM`: implementation no longer blocks the thunk resource it only reads from. + * Additional: * [(link)](https://github.com/haskell-nix/hnix/commit/7e6cd97bf3288cb584241611fdb25bf85d7e0ba7) `cabal.project`: freed from the `cryptohash-sha512` override, Hackage trustees made a revision. diff --git a/hnix.cabal b/hnix.cabal index 3a30b7a87..2dfcc238a 100644 --- a/hnix.cabal +++ b/hnix.cabal @@ -13,317 +13,317 @@ build-type: Simple cabal-version: >= 1.10 data-dir: data/ data-files: - nix/corepkgs/buildenv.nix - nix/corepkgs/unpack-channel.nix - nix/corepkgs/derivation.nix - nix/corepkgs/fetchurl.nix - nix/corepkgs/imported-drv-to-derivation.nix + nix/corepkgs/buildenv.nix + nix/corepkgs/unpack-channel.nix + nix/corepkgs/derivation.nix + nix/corepkgs/fetchurl.nix + nix/corepkgs/imported-drv-to-derivation.nix extra-source-files: - ChangeLog.md - ReadMe.md - License - data/nix/corepkgs/buildenv.nix - data/nix/corepkgs/unpack-channel.nix - data/nix/corepkgs/derivation.nix - data/nix/corepkgs/fetchurl.nix - data/nix/corepkgs/imported-drv-to-derivation.nix - data/nix/tests/lang/binary-data - data/nix/tests/lang/data - data/nix/tests/lang/dir1/a.nix - data/nix/tests/lang/dir2/a.nix - data/nix/tests/lang/dir2/b.nix - data/nix/tests/lang/dir3/a.nix - data/nix/tests/lang/dir3/b.nix - data/nix/tests/lang/dir3/c.nix - data/nix/tests/lang/dir4/a.nix - data/nix/tests/lang/dir4/c.nix - data/nix/tests/lang/eval-fail-abort.nix - data/nix/tests/lang/eval-fail-antiquoted-path.nix - data/nix/tests/lang/eval-fail-assert.nix - data/nix/tests/lang/eval-fail-bad-antiquote-1.nix - data/nix/tests/lang/eval-fail-bad-antiquote-2.nix - data/nix/tests/lang/eval-fail-bad-antiquote-3.nix - data/nix/tests/lang/eval-fail-blackhole.nix - data/nix/tests/lang/eval-fail-deepseq.nix - data/nix/tests/lang/eval-fail-hashfile-missing.nix - data/nix/tests/lang/eval-fail-missing-arg.nix - data/nix/tests/lang/eval-fail-path-slash.nix - data/nix/tests/lang/eval-fail-remove.nix - data/nix/tests/lang/eval-fail-scope-5.nix - data/nix/tests/lang/eval-fail-seq.nix - data/nix/tests/lang/eval-fail-substring.nix - data/nix/tests/lang/eval-fail-to-path.nix - data/nix/tests/lang/eval-fail-undeclared-arg.nix - data/nix/tests/lang/eval-okay-any-all.exp - data/nix/tests/lang/eval-okay-any-all.nix - data/nix/tests/lang/eval-okay-arithmetic.exp - data/nix/tests/lang/eval-okay-arithmetic.nix - data/nix/tests/lang/eval-okay-attrnames.exp - data/nix/tests/lang/eval-okay-attrnames.nix - data/nix/tests/lang/eval-okay-attrs2.exp - data/nix/tests/lang/eval-okay-attrs2.nix - data/nix/tests/lang/eval-okay-attrs3.exp - data/nix/tests/lang/eval-okay-attrs3.nix - data/nix/tests/lang/eval-okay-attrs4.exp - data/nix/tests/lang/eval-okay-attrs4.nix - data/nix/tests/lang/eval-okay-attrs5.exp - data/nix/tests/lang/eval-okay-attrs5.nix - data/nix/tests/lang/eval-okay-attrs.exp - data/nix/tests/lang/eval-okay-attrs.nix - data/nix/tests/lang/eval-okay-autoargs.exp - data/nix/tests/lang/eval-okay-autoargs.flags - data/nix/tests/lang/eval-okay-autoargs.nix - data/nix/tests/lang/eval-okay-backslash-newline-1.exp - data/nix/tests/lang/eval-okay-backslash-newline-1.nix - data/nix/tests/lang/eval-okay-backslash-newline-2.exp - data/nix/tests/lang/eval-okay-backslash-newline-2.nix - data/nix/tests/lang/eval-okay-builtins-add.exp - data/nix/tests/lang/eval-okay-builtins-add.nix - data/nix/tests/lang/eval-okay-builtins.exp - data/nix/tests/lang/eval-okay-builtins.nix - data/nix/tests/lang/eval-okay-callable-attrs.exp - data/nix/tests/lang/eval-okay-callable-attrs.nix - data/nix/tests/lang/eval-okay-catattrs.exp - data/nix/tests/lang/eval-okay-catattrs.nix - data/nix/tests/lang/eval-okay-closure.exp.xml - data/nix/tests/lang/eval-okay-closure.nix - data/nix/tests/lang/eval-okay-comments.exp - data/nix/tests/lang/eval-okay-comments.nix - data/nix/tests/lang/eval-okay-concat.exp - data/nix/tests/lang/eval-okay-concatmap.exp - data/nix/tests/lang/eval-okay-concatmap.nix - data/nix/tests/lang/eval-okay-concat.nix - data/nix/tests/lang/eval-okay-concatstringssep.exp - data/nix/tests/lang/eval-okay-concatstringssep.nix - data/nix/tests/lang/eval-okay-context.exp - data/nix/tests/lang/eval-okay-context-introspection.exp - data/nix/tests/lang/eval-okay-context-introspection.nix - data/nix/tests/lang/eval-okay-context.nix - data/nix/tests/lang/eval-okay-curpos.exp - data/nix/tests/lang/eval-okay-curpos.nix - data/nix/tests/lang/eval-okay-deepseq.exp - data/nix/tests/lang/eval-okay-deepseq.nix - data/nix/tests/lang/eval-okay-delayed-with.exp - data/nix/tests/lang/eval-okay-delayed-with-inherit.exp - data/nix/tests/lang/eval-okay-delayed-with-inherit.nix - data/nix/tests/lang/eval-okay-delayed-with.nix - data/nix/tests/lang/eval-okay-dynamic-attrs-2.exp - data/nix/tests/lang/eval-okay-dynamic-attrs-2.nix - data/nix/tests/lang/eval-okay-dynamic-attrs-bare.exp - data/nix/tests/lang/eval-okay-dynamic-attrs-bare.nix - data/nix/tests/lang/eval-okay-dynamic-attrs.exp - data/nix/tests/lang/eval-okay-dynamic-attrs.nix - data/nix/tests/lang/eval-okay-elem.exp - data/nix/tests/lang/eval-okay-elem.nix - data/nix/tests/lang/eval-okay-empty-args.exp - data/nix/tests/lang/eval-okay-empty-args.nix - data/nix/tests/lang/eval-okay-eq-derivations.exp - data/nix/tests/lang/eval-okay-eq-derivations.nix - data/nix/tests/lang/eval-okay-eq.exp.disabled - data/nix/tests/lang/eval-okay-eq.nix - data/nix/tests/lang/eval-okay-filter.exp - data/nix/tests/lang/eval-okay-filter.nix - data/nix/tests/lang/eval-okay-flatten.exp - data/nix/tests/lang/eval-okay-flatten.nix - data/nix/tests/lang/eval-okay-float.exp - data/nix/tests/lang/eval-okay-float.nix - data/nix/tests/lang/eval-okay-fromjson.exp - data/nix/tests/lang/eval-okay-fromjson.nix - data/nix/tests/lang/eval-okay-fromTOML.exp - data/nix/tests/lang/eval-okay-fromTOML.nix - data/nix/tests/lang/eval-okay-functionargs.exp.xml - data/nix/tests/lang/eval-okay-functionargs.nix - data/nix/tests/lang/eval-okay-getattrpos.exp - data/nix/tests/lang/eval-okay-getattrpos.nix - data/nix/tests/lang/eval-okay-getattrpos-undefined.exp - data/nix/tests/lang/eval-okay-getattrpos-undefined.nix - data/nix/tests/lang/eval-okay-getenv.exp - data/nix/tests/lang/eval-okay-getenv.nix - data/nix/tests/lang/eval-okay-hash.exp - data/nix/tests/lang/eval-okay-hashfile.exp - data/nix/tests/lang/eval-okay-hashfile.nix - data/nix/tests/lang/eval-okay-hashstring.exp - data/nix/tests/lang/eval-okay-hashstring.nix - data/nix/tests/lang/eval-okay-if.exp - data/nix/tests/lang/eval-okay-if.nix - data/nix/tests/lang/eval-okay-import.exp - data/nix/tests/lang/eval-okay-import.nix - data/nix/tests/lang/eval-okay-ind-string.exp - data/nix/tests/lang/eval-okay-ind-string.nix - data/nix/tests/lang/eval-okay-let.exp - data/nix/tests/lang/eval-okay-let.nix - data/nix/tests/lang/eval-okay-list.exp - data/nix/tests/lang/eval-okay-list.nix - data/nix/tests/lang/eval-okay-listtoattrs.exp - data/nix/tests/lang/eval-okay-listtoattrs.nix - data/nix/tests/lang/eval-okay-logic.exp - data/nix/tests/lang/eval-okay-logic.nix - data/nix/tests/lang/eval-okay-mapattrs.exp - data/nix/tests/lang/eval-okay-mapattrs.nix - data/nix/tests/lang/eval-okay-map.exp - data/nix/tests/lang/eval-okay-map.nix - data/nix/tests/lang/eval-okay-nested-with.exp - data/nix/tests/lang/eval-okay-nested-with.nix - data/nix/tests/lang/eval-okay-new-let.exp - data/nix/tests/lang/eval-okay-new-let.nix - data/nix/tests/lang/eval-okay-null-dynamic-attrs.exp - data/nix/tests/lang/eval-okay-null-dynamic-attrs.nix - data/nix/tests/lang/eval-okay-overrides.exp - data/nix/tests/lang/eval-okay-overrides.nix - data/nix/tests/lang/eval-okay-partition.exp - data/nix/tests/lang/eval-okay-partition.nix - data/nix/tests/lang/eval-okay-pathexists.exp - data/nix/tests/lang/eval-okay-pathexists.nix - data/nix/tests/lang/eval-okay-path.nix - data/nix/tests/lang/eval-okay-patterns.exp - data/nix/tests/lang/eval-okay-patterns.nix - data/nix/tests/lang/eval-okay-readDir.exp - data/nix/tests/lang/eval-okay-readDir.nix - data/nix/tests/lang/eval-okay-readfile.exp - data/nix/tests/lang/eval-okay-readfile.nix - data/nix/tests/lang/eval-okay-redefine-builtin.exp - data/nix/tests/lang/eval-okay-redefine-builtin.nix - data/nix/tests/lang/eval-okay-regex-match.exp - data/nix/tests/lang/eval-okay-regex-match.nix - data/nix/tests/lang/eval-okay-regex-split.exp - data/nix/tests/lang/eval-okay-regex-split.nix - data/nix/tests/lang/eval-okay-remove.exp - data/nix/tests/lang/eval-okay-remove.nix - data/nix/tests/lang/eval-okay-replacestrings.exp - data/nix/tests/lang/eval-okay-replacestrings.nix - data/nix/tests/lang/eval-okay-scope-1.exp - data/nix/tests/lang/eval-okay-scope-1.nix - data/nix/tests/lang/eval-okay-scope-2.exp - data/nix/tests/lang/eval-okay-scope-2.nix - data/nix/tests/lang/eval-okay-scope-3.exp - data/nix/tests/lang/eval-okay-scope-3.nix - data/nix/tests/lang/eval-okay-scope-4.exp - data/nix/tests/lang/eval-okay-scope-4.nix - data/nix/tests/lang/eval-okay-scope-6.exp - data/nix/tests/lang/eval-okay-scope-6.nix - data/nix/tests/lang/eval-okay-scope-7.exp - data/nix/tests/lang/eval-okay-scope-7.nix - data/nix/tests/lang/eval-okay-search-path.exp - data/nix/tests/lang/eval-okay-search-path.flags - data/nix/tests/lang/eval-okay-search-path.nix - data/nix/tests/lang/eval-okay-seq.exp - data/nix/tests/lang/eval-okay-seq.nix - data/nix/tests/lang/eval-okay-sort.exp - data/nix/tests/lang/eval-okay-sort.nix - data/nix/tests/lang/eval-okay-splitversion.exp - data/nix/tests/lang/eval-okay-splitversion.nix - data/nix/tests/lang/eval-okay-string.exp - data/nix/tests/lang/eval-okay-string.nix - data/nix/tests/lang/eval-okay-strings-as-attrs-names.exp - data/nix/tests/lang/eval-okay-strings-as-attrs-names.nix - data/nix/tests/lang/eval-okay-substring.exp - data/nix/tests/lang/eval-okay-substring.nix - data/nix/tests/lang/eval-okay-tail-call-1.exp-disabled - data/nix/tests/lang/eval-okay-tail-call-1.nix - data/nix/tests/lang/eval-okay-tojson.exp - data/nix/tests/lang/eval-okay-tojson.nix - data/nix/tests/lang/eval-okay-toxml2.exp - data/nix/tests/lang/eval-okay-toxml2.nix - data/nix/tests/lang/eval-okay-toxml.exp - data/nix/tests/lang/eval-okay-toxml.nix - data/nix/tests/lang/eval-okay-tryeval.exp - data/nix/tests/lang/eval-okay-tryeval.nix - data/nix/tests/lang/eval-okay-types.exp - data/nix/tests/lang/eval-okay-types.nix - data/nix/tests/lang/eval-okay-versions.exp - data/nix/tests/lang/eval-okay-versions.nix - data/nix/tests/lang/eval-okay-with.exp - data/nix/tests/lang/eval-okay-with.nix - data/nix/tests/lang/eval-okay-xml.exp.xml - data/nix/tests/lang/eval-okay-xml.nix - data/nix/tests/lang/imported2.nix - data/nix/tests/lang/imported.nix - data/nix/tests/lang/lib.nix - data/nix/tests/lang/parse-fail-dup-attrs-1.nix - data/nix/tests/lang/parse-fail-dup-attrs-2.nix - data/nix/tests/lang/parse-fail-dup-attrs-3.nix - data/nix/tests/lang/parse-fail-dup-attrs-4.nix - data/nix/tests/lang/parse-fail-dup-attrs-7.nix - data/nix/tests/lang/parse-fail-dup-formals.nix - data/nix/tests/lang/parse-fail-mixed-nested-attrs1.nix - data/nix/tests/lang/parse-fail-mixed-nested-attrs2.nix - data/nix/tests/lang/parse-fail-patterns-1.nix - data/nix/tests/lang/parse-fail-regression-20060610.nix - data/nix/tests/lang/parse-fail-uft8.nix - data/nix/tests/lang/parse-fail-undef-var-2.nix - data/nix/tests/lang/parse-fail-undef-var.nix - data/nix/tests/lang/parse-okay-1.nix - data/nix/tests/lang/parse-okay-crlf.nix - data/nix/tests/lang/parse-okay-dup-attrs-5.nix - data/nix/tests/lang/parse-okay-dup-attrs-6.nix - data/nix/tests/lang/parse-okay-mixed-nested-attrs-1.nix - data/nix/tests/lang/parse-okay-mixed-nested-attrs-2.nix - data/nix/tests/lang/parse-okay-mixed-nested-attrs-3.nix - data/nix/tests/lang/parse-okay-regression-20041027.nix - data/nix/tests/lang/parse-okay-regression-751.nix - data/nix/tests/lang/parse-okay-subversion.nix - data/nix/tests/lang/parse-okay-url.nix - data/nix/tests/lang/readDir/bar - data/nix/tests/lang/readDir/foo/git-hates-directories - data/nix/tests/local.mk - data/nixpkgs-all-packages.nix - data/let-comments.nix - data/let-comments-multiline.nix - data/simple-pretty.nix - data/simple.nix - data/nixpkgs-all-packages-pretty.nix - data/let.nix - tests/eval-compare/builtins.appendContext.nix - tests/eval-compare/builtins.eq-bottom-00.nix - tests/eval-compare/builtins.fetchurl-01.nix - tests/eval-compare/builtins.fromJSON-01.nix - tests/eval-compare/builtins.getContext.nix - tests/eval-compare/builtins.lessThan-01.nix - tests/eval-compare/builtins.mapAttrs-01.nix - tests/eval-compare/builtins.pathExists.nix - tests/eval-compare/builtins.replaceStrings-01.nix - tests/eval-compare/builtins.split-01.nix - tests/eval-compare/builtins.split-02.nix - tests/eval-compare/builtins.split-03.nix - tests/eval-compare/builtins.split-04.nix - tests/eval-compare/builtins.string.store.nix - tests/eval-compare/builtins.toJSON.nix - tests/eval-compare/current-system.nix - tests/eval-compare/ellipsis.nix - tests/eval-compare/ind-string-01.nix - tests/eval-compare/ind-string-02.nix - tests/eval-compare/ind-string-03.nix - tests/eval-compare/ind-string-04.nix - tests/eval-compare/ind-string-05.nix - tests/eval-compare/ind-string-06.nix - tests/eval-compare/ind-string-07.nix - tests/eval-compare/ind-string-08.nix - tests/eval-compare/ind-string-09.nix - tests/eval-compare/ind-string-10.nix - tests/eval-compare/ind-string-11.nix - tests/eval-compare/ind-string-12.nix - tests/eval-compare/ind-string-13.nix - tests/eval-compare/ind-string-14.nix - tests/eval-compare/ind-string-15.nix - tests/eval-compare/ind-string-16.nix - tests/eval-compare/ind-string-17.nix - tests/eval-compare/paths-01.nix - tests/eval-compare/placeholder.nix - tests/files/attrs.nix - tests/files/callLibs.nix - tests/files/eighty.nix - tests/files/file.nix - tests/files/file2.nix - tests/files/findFile.nix - tests/files/force.nix - tests/files/goodbye.nix - tests/files/hello.nix - tests/files/hello2.nix - tests/files/if-then.nix - tests/files/lint.nix - tests/files/loop.nix - tests/files/test.nix - tests/files/with.nix + ChangeLog.md + ReadMe.md + License + data/nix/corepkgs/buildenv.nix + data/nix/corepkgs/unpack-channel.nix + data/nix/corepkgs/derivation.nix + data/nix/corepkgs/fetchurl.nix + data/nix/corepkgs/imported-drv-to-derivation.nix + data/nix/tests/lang/binary-data + data/nix/tests/lang/data + data/nix/tests/lang/dir1/a.nix + data/nix/tests/lang/dir2/a.nix + data/nix/tests/lang/dir2/b.nix + data/nix/tests/lang/dir3/a.nix + data/nix/tests/lang/dir3/b.nix + data/nix/tests/lang/dir3/c.nix + data/nix/tests/lang/dir4/a.nix + data/nix/tests/lang/dir4/c.nix + data/nix/tests/lang/eval-fail-abort.nix + data/nix/tests/lang/eval-fail-antiquoted-path.nix + data/nix/tests/lang/eval-fail-assert.nix + data/nix/tests/lang/eval-fail-bad-antiquote-1.nix + data/nix/tests/lang/eval-fail-bad-antiquote-2.nix + data/nix/tests/lang/eval-fail-bad-antiquote-3.nix + data/nix/tests/lang/eval-fail-blackhole.nix + data/nix/tests/lang/eval-fail-deepseq.nix + data/nix/tests/lang/eval-fail-hashfile-missing.nix + data/nix/tests/lang/eval-fail-missing-arg.nix + data/nix/tests/lang/eval-fail-path-slash.nix + data/nix/tests/lang/eval-fail-remove.nix + data/nix/tests/lang/eval-fail-scope-5.nix + data/nix/tests/lang/eval-fail-seq.nix + data/nix/tests/lang/eval-fail-substring.nix + data/nix/tests/lang/eval-fail-to-path.nix + data/nix/tests/lang/eval-fail-undeclared-arg.nix + data/nix/tests/lang/eval-okay-any-all.exp + data/nix/tests/lang/eval-okay-any-all.nix + data/nix/tests/lang/eval-okay-arithmetic.exp + data/nix/tests/lang/eval-okay-arithmetic.nix + data/nix/tests/lang/eval-okay-attrnames.exp + data/nix/tests/lang/eval-okay-attrnames.nix + data/nix/tests/lang/eval-okay-attrs2.exp + data/nix/tests/lang/eval-okay-attrs2.nix + data/nix/tests/lang/eval-okay-attrs3.exp + data/nix/tests/lang/eval-okay-attrs3.nix + data/nix/tests/lang/eval-okay-attrs4.exp + data/nix/tests/lang/eval-okay-attrs4.nix + data/nix/tests/lang/eval-okay-attrs5.exp + data/nix/tests/lang/eval-okay-attrs5.nix + data/nix/tests/lang/eval-okay-attrs.exp + data/nix/tests/lang/eval-okay-attrs.nix + data/nix/tests/lang/eval-okay-autoargs.exp + data/nix/tests/lang/eval-okay-autoargs.flags + data/nix/tests/lang/eval-okay-autoargs.nix + data/nix/tests/lang/eval-okay-backslash-newline-1.exp + data/nix/tests/lang/eval-okay-backslash-newline-1.nix + data/nix/tests/lang/eval-okay-backslash-newline-2.exp + data/nix/tests/lang/eval-okay-backslash-newline-2.nix + data/nix/tests/lang/eval-okay-builtins-add.exp + data/nix/tests/lang/eval-okay-builtins-add.nix + data/nix/tests/lang/eval-okay-builtins.exp + data/nix/tests/lang/eval-okay-builtins.nix + data/nix/tests/lang/eval-okay-callable-attrs.exp + data/nix/tests/lang/eval-okay-callable-attrs.nix + data/nix/tests/lang/eval-okay-catattrs.exp + data/nix/tests/lang/eval-okay-catattrs.nix + data/nix/tests/lang/eval-okay-closure.exp.xml + data/nix/tests/lang/eval-okay-closure.nix + data/nix/tests/lang/eval-okay-comments.exp + data/nix/tests/lang/eval-okay-comments.nix + data/nix/tests/lang/eval-okay-concat.exp + data/nix/tests/lang/eval-okay-concatmap.exp + data/nix/tests/lang/eval-okay-concatmap.nix + data/nix/tests/lang/eval-okay-concat.nix + data/nix/tests/lang/eval-okay-concatstringssep.exp + data/nix/tests/lang/eval-okay-concatstringssep.nix + data/nix/tests/lang/eval-okay-context.exp + data/nix/tests/lang/eval-okay-context-introspection.exp + data/nix/tests/lang/eval-okay-context-introspection.nix + data/nix/tests/lang/eval-okay-context.nix + data/nix/tests/lang/eval-okay-curpos.exp + data/nix/tests/lang/eval-okay-curpos.nix + data/nix/tests/lang/eval-okay-deepseq.exp + data/nix/tests/lang/eval-okay-deepseq.nix + data/nix/tests/lang/eval-okay-delayed-with.exp + data/nix/tests/lang/eval-okay-delayed-with-inherit.exp + data/nix/tests/lang/eval-okay-delayed-with-inherit.nix + data/nix/tests/lang/eval-okay-delayed-with.nix + data/nix/tests/lang/eval-okay-dynamic-attrs-2.exp + data/nix/tests/lang/eval-okay-dynamic-attrs-2.nix + data/nix/tests/lang/eval-okay-dynamic-attrs-bare.exp + data/nix/tests/lang/eval-okay-dynamic-attrs-bare.nix + data/nix/tests/lang/eval-okay-dynamic-attrs.exp + data/nix/tests/lang/eval-okay-dynamic-attrs.nix + data/nix/tests/lang/eval-okay-elem.exp + data/nix/tests/lang/eval-okay-elem.nix + data/nix/tests/lang/eval-okay-empty-args.exp + data/nix/tests/lang/eval-okay-empty-args.nix + data/nix/tests/lang/eval-okay-eq-derivations.exp + data/nix/tests/lang/eval-okay-eq-derivations.nix + data/nix/tests/lang/eval-okay-eq.exp.disabled + data/nix/tests/lang/eval-okay-eq.nix + data/nix/tests/lang/eval-okay-filter.exp + data/nix/tests/lang/eval-okay-filter.nix + data/nix/tests/lang/eval-okay-flatten.exp + data/nix/tests/lang/eval-okay-flatten.nix + data/nix/tests/lang/eval-okay-float.exp + data/nix/tests/lang/eval-okay-float.nix + data/nix/tests/lang/eval-okay-fromjson.exp + data/nix/tests/lang/eval-okay-fromjson.nix + data/nix/tests/lang/eval-okay-fromTOML.exp + data/nix/tests/lang/eval-okay-fromTOML.nix + data/nix/tests/lang/eval-okay-functionargs.exp.xml + data/nix/tests/lang/eval-okay-functionargs.nix + data/nix/tests/lang/eval-okay-getattrpos.exp + data/nix/tests/lang/eval-okay-getattrpos.nix + data/nix/tests/lang/eval-okay-getattrpos-undefined.exp + data/nix/tests/lang/eval-okay-getattrpos-undefined.nix + data/nix/tests/lang/eval-okay-getenv.exp + data/nix/tests/lang/eval-okay-getenv.nix + data/nix/tests/lang/eval-okay-hash.exp + data/nix/tests/lang/eval-okay-hashfile.exp + data/nix/tests/lang/eval-okay-hashfile.nix + data/nix/tests/lang/eval-okay-hashstring.exp + data/nix/tests/lang/eval-okay-hashstring.nix + data/nix/tests/lang/eval-okay-if.exp + data/nix/tests/lang/eval-okay-if.nix + data/nix/tests/lang/eval-okay-import.exp + data/nix/tests/lang/eval-okay-import.nix + data/nix/tests/lang/eval-okay-ind-string.exp + data/nix/tests/lang/eval-okay-ind-string.nix + data/nix/tests/lang/eval-okay-let.exp + data/nix/tests/lang/eval-okay-let.nix + data/nix/tests/lang/eval-okay-list.exp + data/nix/tests/lang/eval-okay-list.nix + data/nix/tests/lang/eval-okay-listtoattrs.exp + data/nix/tests/lang/eval-okay-listtoattrs.nix + data/nix/tests/lang/eval-okay-logic.exp + data/nix/tests/lang/eval-okay-logic.nix + data/nix/tests/lang/eval-okay-mapattrs.exp + data/nix/tests/lang/eval-okay-mapattrs.nix + data/nix/tests/lang/eval-okay-map.exp + data/nix/tests/lang/eval-okay-map.nix + data/nix/tests/lang/eval-okay-nested-with.exp + data/nix/tests/lang/eval-okay-nested-with.nix + data/nix/tests/lang/eval-okay-new-let.exp + data/nix/tests/lang/eval-okay-new-let.nix + data/nix/tests/lang/eval-okay-null-dynamic-attrs.exp + data/nix/tests/lang/eval-okay-null-dynamic-attrs.nix + data/nix/tests/lang/eval-okay-overrides.exp + data/nix/tests/lang/eval-okay-overrides.nix + data/nix/tests/lang/eval-okay-partition.exp + data/nix/tests/lang/eval-okay-partition.nix + data/nix/tests/lang/eval-okay-pathexists.exp + data/nix/tests/lang/eval-okay-pathexists.nix + data/nix/tests/lang/eval-okay-path.nix + data/nix/tests/lang/eval-okay-patterns.exp + data/nix/tests/lang/eval-okay-patterns.nix + data/nix/tests/lang/eval-okay-readDir.exp + data/nix/tests/lang/eval-okay-readDir.nix + data/nix/tests/lang/eval-okay-readfile.exp + data/nix/tests/lang/eval-okay-readfile.nix + data/nix/tests/lang/eval-okay-redefine-builtin.exp + data/nix/tests/lang/eval-okay-redefine-builtin.nix + data/nix/tests/lang/eval-okay-regex-match.exp + data/nix/tests/lang/eval-okay-regex-match.nix + data/nix/tests/lang/eval-okay-regex-split.exp + data/nix/tests/lang/eval-okay-regex-split.nix + data/nix/tests/lang/eval-okay-remove.exp + data/nix/tests/lang/eval-okay-remove.nix + data/nix/tests/lang/eval-okay-replacestrings.exp + data/nix/tests/lang/eval-okay-replacestrings.nix + data/nix/tests/lang/eval-okay-scope-1.exp + data/nix/tests/lang/eval-okay-scope-1.nix + data/nix/tests/lang/eval-okay-scope-2.exp + data/nix/tests/lang/eval-okay-scope-2.nix + data/nix/tests/lang/eval-okay-scope-3.exp + data/nix/tests/lang/eval-okay-scope-3.nix + data/nix/tests/lang/eval-okay-scope-4.exp + data/nix/tests/lang/eval-okay-scope-4.nix + data/nix/tests/lang/eval-okay-scope-6.exp + data/nix/tests/lang/eval-okay-scope-6.nix + data/nix/tests/lang/eval-okay-scope-7.exp + data/nix/tests/lang/eval-okay-scope-7.nix + data/nix/tests/lang/eval-okay-search-path.exp + data/nix/tests/lang/eval-okay-search-path.flags + data/nix/tests/lang/eval-okay-search-path.nix + data/nix/tests/lang/eval-okay-seq.exp + data/nix/tests/lang/eval-okay-seq.nix + data/nix/tests/lang/eval-okay-sort.exp + data/nix/tests/lang/eval-okay-sort.nix + data/nix/tests/lang/eval-okay-splitversion.exp + data/nix/tests/lang/eval-okay-splitversion.nix + data/nix/tests/lang/eval-okay-string.exp + data/nix/tests/lang/eval-okay-string.nix + data/nix/tests/lang/eval-okay-strings-as-attrs-names.exp + data/nix/tests/lang/eval-okay-strings-as-attrs-names.nix + data/nix/tests/lang/eval-okay-substring.exp + data/nix/tests/lang/eval-okay-substring.nix + data/nix/tests/lang/eval-okay-tail-call-1.exp-disabled + data/nix/tests/lang/eval-okay-tail-call-1.nix + data/nix/tests/lang/eval-okay-tojson.exp + data/nix/tests/lang/eval-okay-tojson.nix + data/nix/tests/lang/eval-okay-toxml2.exp + data/nix/tests/lang/eval-okay-toxml2.nix + data/nix/tests/lang/eval-okay-toxml.exp + data/nix/tests/lang/eval-okay-toxml.nix + data/nix/tests/lang/eval-okay-tryeval.exp + data/nix/tests/lang/eval-okay-tryeval.nix + data/nix/tests/lang/eval-okay-types.exp + data/nix/tests/lang/eval-okay-types.nix + data/nix/tests/lang/eval-okay-versions.exp + data/nix/tests/lang/eval-okay-versions.nix + data/nix/tests/lang/eval-okay-with.exp + data/nix/tests/lang/eval-okay-with.nix + data/nix/tests/lang/eval-okay-xml.exp.xml + data/nix/tests/lang/eval-okay-xml.nix + data/nix/tests/lang/imported2.nix + data/nix/tests/lang/imported.nix + data/nix/tests/lang/lib.nix + data/nix/tests/lang/parse-fail-dup-attrs-1.nix + data/nix/tests/lang/parse-fail-dup-attrs-2.nix + data/nix/tests/lang/parse-fail-dup-attrs-3.nix + data/nix/tests/lang/parse-fail-dup-attrs-4.nix + data/nix/tests/lang/parse-fail-dup-attrs-7.nix + data/nix/tests/lang/parse-fail-dup-formals.nix + data/nix/tests/lang/parse-fail-mixed-nested-attrs1.nix + data/nix/tests/lang/parse-fail-mixed-nested-attrs2.nix + data/nix/tests/lang/parse-fail-patterns-1.nix + data/nix/tests/lang/parse-fail-regression-20060610.nix + data/nix/tests/lang/parse-fail-uft8.nix + data/nix/tests/lang/parse-fail-undef-var-2.nix + data/nix/tests/lang/parse-fail-undef-var.nix + data/nix/tests/lang/parse-okay-1.nix + data/nix/tests/lang/parse-okay-crlf.nix + data/nix/tests/lang/parse-okay-dup-attrs-5.nix + data/nix/tests/lang/parse-okay-dup-attrs-6.nix + data/nix/tests/lang/parse-okay-mixed-nested-attrs-1.nix + data/nix/tests/lang/parse-okay-mixed-nested-attrs-2.nix + data/nix/tests/lang/parse-okay-mixed-nested-attrs-3.nix + data/nix/tests/lang/parse-okay-regression-20041027.nix + data/nix/tests/lang/parse-okay-regression-751.nix + data/nix/tests/lang/parse-okay-subversion.nix + data/nix/tests/lang/parse-okay-url.nix + data/nix/tests/lang/readDir/bar + data/nix/tests/lang/readDir/foo/git-hates-directories + data/nix/tests/local.mk + data/nixpkgs-all-packages.nix + data/let-comments.nix + data/let-comments-multiline.nix + data/simple-pretty.nix + data/simple.nix + data/nixpkgs-all-packages-pretty.nix + data/let.nix + tests/eval-compare/builtins.appendContext.nix + tests/eval-compare/builtins.eq-bottom-00.nix + tests/eval-compare/builtins.fetchurl-01.nix + tests/eval-compare/builtins.fromJSON-01.nix + tests/eval-compare/builtins.getContext.nix + tests/eval-compare/builtins.lessThan-01.nix + tests/eval-compare/builtins.mapAttrs-01.nix + tests/eval-compare/builtins.pathExists.nix + tests/eval-compare/builtins.replaceStrings-01.nix + tests/eval-compare/builtins.split-01.nix + tests/eval-compare/builtins.split-02.nix + tests/eval-compare/builtins.split-03.nix + tests/eval-compare/builtins.split-04.nix + tests/eval-compare/builtins.string.store.nix + tests/eval-compare/builtins.toJSON.nix + tests/eval-compare/current-system.nix + tests/eval-compare/ellipsis.nix + tests/eval-compare/ind-string-01.nix + tests/eval-compare/ind-string-02.nix + tests/eval-compare/ind-string-03.nix + tests/eval-compare/ind-string-04.nix + tests/eval-compare/ind-string-05.nix + tests/eval-compare/ind-string-06.nix + tests/eval-compare/ind-string-07.nix + tests/eval-compare/ind-string-08.nix + tests/eval-compare/ind-string-09.nix + tests/eval-compare/ind-string-10.nix + tests/eval-compare/ind-string-11.nix + tests/eval-compare/ind-string-12.nix + tests/eval-compare/ind-string-13.nix + tests/eval-compare/ind-string-14.nix + tests/eval-compare/ind-string-15.nix + tests/eval-compare/ind-string-16.nix + tests/eval-compare/ind-string-17.nix + tests/eval-compare/paths-01.nix + tests/eval-compare/placeholder.nix + tests/files/attrs.nix + tests/files/callLibs.nix + tests/files/eighty.nix + tests/files/file.nix + tests/files/file2.nix + tests/files/findFile.nix + tests/files/force.nix + tests/files/goodbye.nix + tests/files/hello.nix + tests/files/hello2.nix + tests/files/if-then.nix + tests/files/lint.nix + tests/files/loop.nix + tests/files/test.nix + tests/files/with.nix source-repository head type: git @@ -332,7 +332,7 @@ source-repository head flag optimize description: Enable all optimization flags manual: True - default: False + default: True flag profiling description: Enable profiling @@ -341,63 +341,63 @@ flag profiling library exposed-modules: - Nix - Nix.Atoms - Nix.Builtins - Nix.Cache - Nix.Cited - Nix.Cited.Basic - Nix.Context - Nix.Convert - Nix.Effects - Nix.Effects.Basic - Nix.Effects.Derivation - Nix.Eval - Nix.Exec - Nix.Expr - Nix.Expr.Shorthands - Nix.Expr.Strings - Nix.Expr.Types - Nix.Expr.Types.Annotated - Nix.Frames - Nix.Fresh - Nix.Fresh.Basic - Nix.Json - Nix.Lint - Nix.Normal - Nix.Options - Nix.Parser - Nix.Pretty - Nix.Reduce - Nix.Render - Nix.Render.Frame - Nix.Scope - Nix.Standard - Nix.String - Nix.String.Coerce - Nix.TH - Nix.Thunk - Nix.Thunk.Basic - Nix.Type.Assumption - Nix.Type.Env - Nix.Type.Infer - Nix.Type.Type - Nix.Utils - Nix.Utils.Fix1 - Nix.Value - Nix.Value.Equal - Nix.Value.Monad - Nix.Var - Nix.XML + Nix + Nix.Atoms + Nix.Builtins + Nix.Cache + Nix.Cited + Nix.Cited.Basic + Nix.Context + Nix.Convert + Nix.Effects + Nix.Effects.Basic + Nix.Effects.Derivation + Nix.Eval + Nix.Exec + Nix.Expr + Nix.Expr.Shorthands + Nix.Expr.Strings + Nix.Expr.Types + Nix.Expr.Types.Annotated + Nix.Frames + Nix.Fresh + Nix.Fresh.Basic + Nix.Json + Nix.Lint + Nix.Normal + Nix.Options + Nix.Parser + Nix.Pretty + Nix.Reduce + Nix.Render + Nix.Render.Frame + Nix.Scope + Nix.Standard + Nix.String + Nix.String.Coerce + Nix.TH + Nix.Thunk + Nix.Thunk.Basic + Nix.Type.Assumption + Nix.Type.Env + Nix.Type.Infer + Nix.Type.Type + Nix.Utils + Nix.Utils.Fix1 + Nix.Value + Nix.Value.Equal + Nix.Value.Monad + Nix.Var + Nix.XML other-modules: - Paths_hnix + Paths_hnix hs-source-dirs: - src + src ghc-options: -Wall -fprint-potential-instances build-depends: aeson >= 1.4.2 && < 1.6 , array >= 0.4 && < 0.6 - , base >= 4.11 && < 5 + , base >= 4.12 && < 5 , binary >= 0.8.5 && < 0.9 , bytestring >= 0.10.8 && < 0.11 , comonad >= 5.0.4 && < 5.1 @@ -449,10 +449,12 @@ library , vector >= 0.12.0 && < 0.13 , xml >= 1.3.14 && < 1.4 if flag(optimize) - ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O2 + default-extensions: + ApplicativeDo + ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O3 if !impl(ghcjs) exposed-modules: - Nix.Options.Parser + Nix.Options.Parser build-depends: base16-bytestring >= 0.1.1 && < 1.1 , pretty-show >= 1.9.5 && < 1.11 @@ -463,13 +465,13 @@ library default-language: Haskell2010 executable hnix + hs-source-dirs: + main main-is: Main.hs other-modules: - Repl - Paths_hnix - hs-source-dirs: - main - ghc-options: -Wall -rtsopts + Repl + Paths_hnix + ghc-options: -Wall build-depends: aeson , base @@ -497,7 +499,9 @@ executable hnix , transformers , unordered-containers if flag(optimize) - ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O2 + default-extensions: + ApplicativeDo + ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O3 if impl(ghc < 8.10) -- GHC < 8.10 comes with haskeline < 0.8, which we don't support. -- To simplify CI, we just disable the component. @@ -510,16 +514,16 @@ test-suite hnix-tests type: exitcode-stdio-1.0 main-is: Main.hs other-modules: - EvalTests - NixLanguageTests - ParserTests - PrettyParseTests - PrettyTests - ReduceExprTests - TestCommon - Paths_hnix + EvalTests + NixLanguageTests + ParserTests + PrettyParseTests + PrettyTests + ReduceExprTests + TestCommon + Paths_hnix hs-source-dirs: - tests + tests ghc-options: -Wall -threaded build-depends: Diff @@ -555,7 +559,9 @@ test-suite hnix-tests , unix , unordered-containers if flag(optimize) - ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O2 + default-extensions: + ApplicativeDo + ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O3 if impl(ghcjs) buildable: False default-language: Haskell2010 @@ -564,10 +570,10 @@ benchmark hnix-benchmarks type: exitcode-stdio-1.0 main-is: Main.hs other-modules: - ParserBench - Paths_hnix + ParserBench + Paths_hnix hs-source-dirs: - benchmarks + benchmarks ghc-options: -Wall build-depends: base @@ -589,7 +595,9 @@ benchmark hnix-benchmarks , transformers , unordered-containers if flag(optimize) - ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O2 + default-extensions: + ApplicativeDo + ghc-options: -fexpose-all-unfoldings -fspecialise-aggressively -O3 if impl(ghcjs) buildable: False default-language: Haskell2010 diff --git a/main/Main.hs b/main/Main.hs index ab04d5436..e43fdce88 100644 --- a/main/Main.hs +++ b/main/Main.hs @@ -85,48 +85,54 @@ main = do ) (readFrom opts) - processFile opts path = do - eres <- parseNixFileLoc path - handleResult opts (pure path) eres + processFile opts path = + do + eres <- parseNixFileLoc path + handleResult opts (pure path) eres - handleResult opts mpath = \case - Failure err -> - bool - errorWithoutStackTrace - (liftIO . hPutStrLn stderr) - (ignoreErrors opts) - $ "Parse failed: " <> show err + handleResult opts mpath = + either + (\ err -> + bool + errorWithoutStackTrace + (liftIO . hPutStrLn stderr) + (ignoreErrors opts) + $ "Parse failed: " <> show err + ) - Success expr -> do - when (check opts) $ do - expr' <- liftIO (reduceExpr mpath expr) - either - (\ err -> errorWithoutStackTrace $ "Type error: " <> PS.ppShow err) - (\ ty -> liftIO $ putStrLn $ "Type of expression: " <> PS.ppShow - (fromJust $ Map.lookup "it" $ Env.types ty) - ) - (HM.inferTop Env.empty [("it", stripAnnotation expr')]) + (\ expr -> + do + when (check opts) $ + do + expr' <- liftIO (reduceExpr mpath expr) + either + (\ err -> errorWithoutStackTrace $ "Type error: " <> PS.ppShow err) + (\ ty -> liftIO $ putStrLn $ "Type of expression: " <> PS.ppShow + (fromJust $ Map.lookup "it" $ Env.types ty) + ) + (HM.inferTop Env.empty [("it", stripAnnotation expr')]) - -- liftIO $ putStrLn $ runST $ - -- runLintM opts . renderSymbolic =<< lint opts expr + -- liftIO $ putStrLn $ runST $ + -- runLintM opts . renderSymbolic =<< lint opts expr - catch (process opts mpath expr) $ \case - NixException frames -> - errorWithoutStackTrace - . show - =<< renderFrames @(StdValue (StandardT (StdIdT IO))) - @(StdThunk (StandardT (StdIdT IO))) - frames + catch (process opts mpath expr) $ + \case + NixException frames -> + errorWithoutStackTrace . show + =<< renderFrames @(StdValue (StandardT (StdIdT IO))) + @(StdThunk (StandardT (StdIdT IO))) + frames - when (repl opts) $ - withNixContext mempty $ - bool - Repl.main - (do - val <- Nix.nixEvalExprLoc mpath expr - Repl.main' $ pure val - ) - (evaluate opts) + when (repl opts) $ + withNixContext mempty $ + bool + Repl.main + (do + val <- Nix.nixEvalExprLoc mpath expr + Repl.main' $ pure val + ) + (evaluate opts) + ) process opts mpath expr | evaluate opts = @@ -137,8 +143,8 @@ main = do && null (argstr opts) ) -> evaluateExpression mpath Nix.nixEvalExprLoc printer expr | otherwise -> processResult printer =<< Nix.nixEvalExprLoc mpath expr - | xml opts = error "Rendering expression trees to XML is not yet implemented" - | json opts = error "Rendering expression trees to JSON is not implemented" + | xml opts = fail "Rendering expression trees to XML is not yet implemented" + | json opts = fail "Rendering expression trees to JSON is not implemented" | verbose opts >= DebugInfo = liftIO $ putStr $ PS.ppShow $ stripAnnotation expr | cache opts , Just path <- mpath = liftIO $ writeCache (addExtension (dropExtension path) "nixc") expr diff --git a/main/Repl.hs b/main/Repl.hs index 334207fec..65b23b65a 100644 --- a/main/Repl.hs +++ b/main/Repl.hs @@ -9,9 +9,7 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiWayIf #-} -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} @@ -29,12 +27,14 @@ import Nix.Scope import Nix.Utils import Nix.Value.Monad ( demand ) -import qualified Data.List -import qualified Data.Maybe +import qualified Data.List as List +import qualified Data.Maybe as Maybe import qualified Data.HashMap.Lazy -import Data.Text (Text) -import qualified Data.Text -import qualified Data.Text.IO +import Data.Char ( isSpace ) +import Data.List ( dropWhileEnd ) +import Data.Text ( Text ) +import qualified Data.Text as Text +import qualified Data.Text.IO as Text.IO import Data.Version ( showVersion ) import Paths_hnix ( version ) @@ -47,7 +47,7 @@ import Prettyprinter ( Doc , space ) import qualified Prettyprinter -import qualified Prettyprinter.Render.Text +import qualified Prettyprinter.Render.Text as Prettyprinter import System.Console.Haskeline.Completion ( Completion(isFinished) @@ -57,13 +57,15 @@ import System.Console.Haskeline.Completion ) import System.Console.Repline ( Cmd , CompletionFunc - , CompleterStyle (Prefix) + , CompleterStyle(Prefix) + , MultiLine(SingleLine, MultiLine) , ExitDecision(Exit) , HaskelineT + , evalRepl ) -import qualified System.Console.Repline -import qualified System.Exit -import qualified System.IO.Error +import qualified System.Console.Repline as Console +import qualified System.Exit as Exit +import qualified System.IO.Error as Error -- | Repl entry point main :: (MonadNix e t f m, MonadIO m, MonadMask m) => m () @@ -73,8 +75,12 @@ main = main' Nothing -- -- Passed value is stored in context with "input" key. main' :: (MonadNix e t f m, MonadIO m, MonadMask m) => Maybe (NValue t f m) -> m () -main' iniVal = initState iniVal >>= \s -> flip evalStateT s - $ System.Console.Repline.evalRepl +main' iniVal = + do + s <- initState iniVal + + evalStateT + (evalRepl banner cmd options @@ -83,33 +89,41 @@ main' iniVal = initState iniVal >>= \s -> flip evalStateT s completion (rcFile *> greeter) finalizer + ) + s where commandPrefix = ':' banner = pure . \case - System.Console.Repline.SingleLine -> "hnix> " - System.Console.Repline.MultiLine -> "| " + SingleLine -> "hnix> " + MultiLine -> "| " greeter = - liftIO - $ putStrLn - $ "Welcome to hnix " - <> showVersion version - <> ". For help type :help\n" + liftIO $ + putStrLn $ + "Welcome to hnix " + <> showVersion version + <> ". For help type :help\n" finalizer = do liftIO $ putStrLn "Goodbye." pure Exit - rcFile = do - f <- liftIO $ Data.Text.IO.readFile ".hnixrc" `catch` handleMissing - for_ (words . Data.Text.unpack <$> Data.Text.lines f) $ \case - ((prefix:command) : xs) | prefix == commandPrefix -> do - let arguments = unwords xs - optMatcher command options arguments - x -> cmd $ unwords x + rcFile = + do + f <- liftIO $ Text.IO.readFile ".hnixrc" `catch` handleMissing + + traverse_ + (\case + ((prefix:command) : xs) | prefix == commandPrefix -> + do + let arguments = unwords xs + optMatcher command options arguments + x -> cmd $ unwords x + ) + (words . Text.unpack <$> Text.lines f) handleMissing e - | System.IO.Error.isDoesNotExistError e = pure "" + | Error.isDoesNotExistError e = pure "" | otherwise = throwIO e -- Replicated and slightly adjusted `optMatcher` from `System.Console.Repline` @@ -118,12 +132,12 @@ main' iniVal = initState iniVal >>= \s -> flip evalStateT s -- * @putStrLn@ instead of @outputStrLn@ optMatcher :: MonadIO m => String - -> System.Console.Repline.Options m + -> Console.Options m -> String -> m () optMatcher s [] _ = liftIO $ putStrLn $ "No such command :" <> s optMatcher s ((x, m) : xs) args - | s `Data.List.isPrefixOf` x = m args + | s `List.isPrefixOf` x = m args | otherwise = optMatcher s xs args @@ -156,19 +170,23 @@ initState mIni = do opts :: Nix.Options <- asks (view hasLens) - pure $ IState - Nothing - (Data.HashMap.Lazy.fromList - $ ("builtins", builtins) : fmap ("input",) (Data.Maybe.maybeToList mIni)) - defReplConfig - { cfgStrict = strict opts - , cfgValues = values opts - } + pure $ + IState + Nothing + (Data.HashMap.Lazy.fromList $ + ("builtins", builtins) : fmap ("input",) (Maybe.maybeToList mIni) + ) + defReplConfig + { cfgStrict = strict opts + , cfgValues = values opts + } where evalText :: (MonadNix e t f m) => Text -> m (NValue t f m) - evalText expr = case parseNixTextLoc expr of - Failure e -> error $ "Impossible happened: Unable to parse expression - '" <> Data.Text.unpack expr <> "' error was " <> show e - Success e -> do evalExprLoc e + evalText expr = + either + (\ e -> fail $ "Impossible happened: Unable to parse expression - '" <> Text.unpack expr <> "' fail was " <> show e) + (\ e -> do evalExprLoc e) + (parseNixTextLoc expr) type Repl e t f m = HaskelineT (StateT (IState t f m) m) @@ -189,10 +207,10 @@ exec update source = do -- Parser ( returns AST as `NExprLoc` ) case parseExprOrBinding source of - (Failure err, _) -> do + (Left err, _) -> do liftIO $ print err pure Nothing - (Success expr, isBinding) -> do + (Right expr, isBinding) -> do -- Type Inference ( returns Typing Environment ) -- @@ -204,11 +222,11 @@ exec update source = do mVal <- lift $ lift $ try $ pushScope (replCtx st) (evalExprLoc expr) - case mVal of - Left (NixException frames) -> do + either + (\ (NixException frames) -> do lift $ lift $ liftIO . print =<< renderFrames @(NValue t f m) @t frames - pure Nothing - Right val -> do + pure Nothing) + (\ val -> do -- Update the interpreter state when (update && isBinding) $ do -- Set `replIt` to last entered expression @@ -220,6 +238,8 @@ exec update source = do _ -> pure () pure $ pure val + ) + mVal where -- If parsing fails, turn the input into singleton attribute set -- and try again. @@ -227,24 +247,29 @@ exec update source = do -- This allows us to handle assignments like @a = 42@ -- which get turned into @{ a = 42; }@ parseExprOrBinding i = - case parseNixTextLoc i of - Success expr -> (Success expr, False) - Failure e -> - case parseNixTextLoc $ toAttrSet i of - Failure _ -> (Failure e, False) -- return the first parsing failure - Success e' -> (Success e', True) - - toAttrSet i = "{" <> i <> (if Data.Text.isSuffixOf ";" i then mempty else ";") <> "}" + either + (\ e -> + either + (const (Left e, False)) -- return the first parsing failure + (\ e' -> (pure e', True)) + (parseNixTextLoc $ toAttrSet i)) + (\ expr -> (pure expr, False)) + (parseNixTextLoc i) + + toAttrSet i = + "{" <> i <> bool ";" mempty (Text.isSuffixOf ";" i) <> "}" cmd :: (MonadNix e t f m, MonadIO m) => String -> Repl e t f m () -cmd source = do - mVal <- exec True (Data.Text.pack source) - case mVal of - Nothing -> pure () - Just val -> printValue val +cmd source = + do + mVal <- exec True (Text.pack source) + maybe + (pure ()) + printValue + mVal printValue :: (MonadNix e t f m, MonadIO m) => NValue t f m @@ -267,7 +292,7 @@ browse :: (MonadNix e t f m, MonadIO m) browse _ = do st <- get for_ (Data.HashMap.Lazy.toList $ replCtx st) $ \(k, v) -> do - liftIO $ putStr $ Data.Text.unpack $ k <> " = " + liftIO $ putStr $ Text.unpack $ k <> " = " printValue v -- | @:load@ command @@ -275,13 +300,14 @@ load :: (MonadNix e t f m, MonadIO m) => String -> Repl e t f m () -load args = do - contents <- liftIO - $ Data.Text.IO.readFile - $ Data.Text.unpack - $ Data.Text.strip - $ Data.Text.pack args - void $ exec True contents +load args = + do + contents <- liftIO + $ Text.IO.readFile + $ trim args + void $ exec True contents + where + trim = dropWhileEnd isSpace . dropWhile isSpace -- | @:type@ command typeof @@ -291,14 +317,15 @@ typeof typeof args = do st <- get mVal <- - case Data.HashMap.Lazy.lookup line (replCtx st) of - Nothing -> exec False line - Just val -> pure $ pure val + maybe + (exec False line) + (pure . pure) + (Data.HashMap.Lazy.lookup line (replCtx st)) traverse_ printValueType mVal where - line = Data.Text.pack args + line = Text.pack args printValueType val = do s <- lift . lift . showValueType $ val @@ -307,7 +334,7 @@ typeof args = do -- | @:quit@ command quit :: (MonadNix e t f m, MonadIO m) => a -> Repl e t f m () -quit _ = liftIO System.Exit.exitSuccess +quit _ = liftIO Exit.exitSuccess -- | @:set@ command setConfig :: (MonadNix e t f m, MonadIO m) => String -> Repl e t f m () @@ -324,7 +351,7 @@ setConfig args = case words args of -- | Prefix tab completer defaultMatcher :: MonadIO m => [(String, CompletionFunc m)] defaultMatcher = - [ (":load", System.Console.Repline.fileCompleter) + [ (":load", Console.fileCompleter) ] completion @@ -353,11 +380,11 @@ completeFunc reversedPrev word $ fmap helpOptionName (helpOptions :: HelpOptions e t f m) -- Files - | any (`Data.List.isPrefixOf` word) [ "/", "./", "../", "~/" ] = + | any (`List.isPrefixOf` word) [ "/", "./", "../", "~/" ] = listFiles word -- Attributes of sets in REPL context - | var : subFields <- Data.Text.split (== '.') (Data.Text.pack word) , not $ null subFields = + | var : subFields <- Text.split (== '.') (Text.pack word) , not $ null subFields = do s <- get maybe @@ -365,7 +392,7 @@ completeFunc reversedPrev word (\ binding -> do candidates <- lift $ algebraicComplete subFields binding - pure $ notFinished <$> listCompletion (Data.Text.unpack . (var <>) <$> candidates) + pure $ notFinished <$> listCompletion (Text.unpack . (var <>) <$> candidates) ) (Data.HashMap.Lazy.lookup var (replCtx s)) @@ -379,11 +406,11 @@ completeFunc reversedPrev word pure $ listCompletion $ ["__includes"] - <> (Data.Text.unpack <$> contextKeys) - <> (Data.Text.unpack <$> shortBuiltins) + <> (Text.unpack <$> contextKeys) + <> (Text.unpack <$> shortBuiltins) where - listCompletion = fmap simpleCompletion . filter (word `Data.List.isPrefixOf`) + listCompletion = fmap simpleCompletion . filter (word `List.isPrefixOf`) notFinished x = x { isFinished = False } @@ -527,8 +554,8 @@ help hs _ = do liftIO $ putStrLn "Available commands:\n" for_ hs $ \h -> liftIO . - Data.Text.IO.putStrLn . - Prettyprinter.Render.Text.renderStrict . + Text.IO.putStrLn . + Prettyprinter.renderStrict . Prettyprinter.layoutPretty Prettyprinter.defaultLayoutOptions $ ":" <> Prettyprinter.pretty (helpOptionName h) <> space @@ -538,5 +565,5 @@ help hs _ = do options :: (MonadNix e t f m, MonadIO m) - => System.Console.Repline.Options (Repl e t f m) + => Console.Options (Repl e t f m) options = (\h -> (helpOptionName h, helpOptionFunction h)) <$> helpOptions diff --git a/src/Nix.hs b/src/Nix.hs index 1e6885846..eef1c00ff 100644 --- a/src/Nix.hs +++ b/src/Nix.hs @@ -123,9 +123,10 @@ evaluateExpression mpath evaluator handler expr = do ) =<< demand f where parseArg s = - case parseNixText s of - Success x -> x - Failure err -> errorWithoutStackTrace (show err) + either + (errorWithoutStackTrace . show) + id + (parseNixText s) eval' = normalForm <=< nixEvalExpr mpath diff --git a/src/Nix/Builtins.hs b/src/Nix/Builtins.hs index 4b838e5b5..b46a0e491 100644 --- a/src/Nix/Builtins.hs +++ b/src/Nix/Builtins.hs @@ -326,7 +326,7 @@ derivation => m (NValue t f m) derivation = foldFix Eval.eval $$(do -- This is compiled in so that we only parse it once at compile-time. - let Success expr = parseNixText [text| + let Right expr = parseNixText [text| drvAttrs @ { outputs ? [ "out" ], ... }: let @@ -379,7 +379,7 @@ foldNixPath f z = foldrM go z $ (fromInclude . stringIgnoreContext <$> dirs) - <> ((uriAwareSplit . Text.pack) `ifJust` mPath) + <> ((uriAwareSplit . Text.pack) `whenJust` mPath) <> [ fromInclude $ Text.pack $ "nix=" <> dataDir <> "/nix/corepkgs" ] where fromInclude x = (x, ) $ @@ -777,7 +777,7 @@ splitMatches -> [NValue t f m] splitMatches _ [] haystack = [thunkStr haystack] splitMatches _ ([] : _) _ = - error "Error in splitMatches: this should never happen!" + fail "Fail in splitMatches: this should never happen!" splitMatches numDropped (((_, (start, len)) : captures) : mts) haystack = thunkStr before : caps : splitMatches (numDropped + relStart + len) mts @@ -1494,7 +1494,7 @@ placeHolder = fromValue >=> fromStringNoContext >=> \t -> do $ case Base16.decode (text h) of -- The result coming out of hashString is base16 encoded #if MIN_VERSION_base16_bytestring(1,0,0) Right d -> d - Left e -> error $ "Couldn't Base16 decode the text: '" <> show (text h) <> "'.\nThe Left error content: '" <> e <> "'." + Left e -> error $ "Couldn't Base16 decode the text: '" <> show (text h) <> "'.\nThe Left fail content: '" <> e <> "'." #else (d, "") -> d (_, e) -> error $ "Couldn't Base16 decode the text: '" <> show (text h) <> "'.\nUndecodable remainder: '" <> show e <> "'." @@ -1668,7 +1668,7 @@ trace_ msg action = traceEffect @t @f @m . Text.unpack . stringIgnoreContext =<< fromValue msg pure action --- Please, can function remember error context +-- Please, can function remember fail context addErrorContext :: forall e t f m . MonadNix e t f m diff --git a/src/Nix/Cache.hs b/src/Nix/Cache.hs index 1ca44b234..81e007efd 100644 --- a/src/Nix/Cache.hs +++ b/src/Nix/Cache.hs @@ -23,16 +23,16 @@ readCache path = do #if USE_COMPACT eres <- C.unsafeReadCompact path case eres of - Left err -> error $ "Error reading cache file: " <> err + Left err -> fail $ "Error reading cache file: " <> err Right expr -> pure $ C.getCompact expr #else #ifdef MIN_VERSION_serialise eres <- S.deserialiseOrFail <$> BS.readFile path case eres of - Left err -> error $ "Error reading cache file: " <> show err + Left err -> fail $ "Error reading cache file: " <> show err Right expr -> pure expr #else - error "readCache not implemented for this platform" + fail "readCache not implemented for this platform" #endif #endif @@ -44,6 +44,6 @@ writeCache path expr = #ifdef MIN_VERSION_serialise BS.writeFile path (S.serialise expr) #else - error "writeCache not implemented for this platform" + fail "writeCache not implemented for this platform" #endif #endif diff --git a/src/Nix/Cited/Basic.hs b/src/Nix/Cited/Basic.hs index 91cafa1ac..d4b6d157a 100644 --- a/src/Nix/Cited/Basic.hs +++ b/src/Nix/Cited/Basic.hs @@ -150,11 +150,9 @@ displayProvenance => [Provenance m v] -> m a -> m a -displayProvenance ps f = +displayProvenance = list id (\ (Provenance scope e@(Compose (Ann s _)) : _) -> withFrame Info (ForcingExpr scope (wrapExprLoc s e)) ) - ps - f diff --git a/src/Nix/Effects.hs b/src/Nix/Effects.hs index 7973eea59..4245fea3d 100644 --- a/src/Nix/Effects.hs +++ b/src/Nix/Effects.hs @@ -160,9 +160,10 @@ instance MonadExec IO where if T.null t then pure $ Left $ ErrorCall $ "exec has no output :" <> emsg else - case parseNixTextLoc t of - Failure err -> pure $ Left $ ErrorCall $ "Error parsing output of exec: " <> show err <> " " <> emsg - Success v -> pure $ Right v + either + (\ err -> pure $ Left $ ErrorCall $ "Error parsing output of exec: " <> show err <> " " <> emsg) + (pure . pure) + (parseNixTextLoc t) err -> pure $ Left $ ErrorCall $ "exec failed: " <> show err <> " " <> emsg deriving @@ -204,9 +205,10 @@ instance MonadInstantiate IO where pure $ case exitCode of ExitSuccess -> - case parseNixTextLoc (T.pack out) of - Failure e -> Left $ ErrorCall $ "Error parsing output of nix-instantiate: " <> show e - Success v -> Right v + either + (\ e -> Left $ ErrorCall $ "Error parsing output of nix-instantiate: " <> show e) + pure + (parseNixTextLoc (T.pack out)) status -> Left $ ErrorCall $ "nix-instantiate failed: " <> show status <> ": " <> err deriving diff --git a/src/Nix/Effects/Basic.hs b/src/Nix/Effects/Basic.hs index 919b53aa6..c997e0f90 100644 --- a/src/Nix/Effects/Basic.hs +++ b/src/Nix/Effects/Basic.hs @@ -1,4 +1,3 @@ -{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} @@ -98,7 +97,7 @@ findEnvPathM name = do mres <- lookupVar "__nixPath" maybe - (error "impossible") + (fail "impossible") ( (\ nv -> do @@ -243,7 +242,7 @@ findPathM = findPathBy existingPath do apath <- makeAbsolutePath @t @f path doesExist <- doesPathExist apath - pure $ ifTrue (pure apath) doesExist + pure $ pure apath `whenTrue` doesExist defaultImportPath :: (MonadNix e t f m, MonadState (HashMap FilePath NExprLoc, b) m) @@ -257,12 +256,14 @@ defaultImportPath path = do maybe (do eres <- parseNixFileLoc path - case eres of - Failure err -> throwError $ ErrorCall . show $ fillSep ["Parse during import failed:", err] - Success expr -> + either + (\ err -> throwError $ ErrorCall . show $ fillSep ["Parse during import failed:", err]) + (\ expr -> do modify (first (M.insert path expr)) pure expr + ) + eres ) pure -- return expr (M.lookup path imports) @@ -274,7 +275,7 @@ defaultPathToDefaultNix = pathToDefaultNixFile pathToDefaultNixFile :: MonadFile m => FilePath -> m FilePath pathToDefaultNixFile p = do isDir <- doesDirectoryExist p - pure $ p ifTrue "default.nix" isDir + pure $ p "default.nix" `whenTrue` isDir defaultTraceEffect :: MonadPutStr m => String -> m () defaultTraceEffect = Nix.Effects.putStrLn diff --git a/src/Nix/Effects/Derivation.hs b/src/Nix/Effects/Derivation.hs index bb54d773b..4fc6bf16a 100644 --- a/src/Nix/Effects/Derivation.hs +++ b/src/Nix/Effects/Derivation.hs @@ -140,8 +140,8 @@ unparseDrv Derivation{..} = Text.append "Derive" $ parens mFixed ) , -- inputDrvs - serializeList $ flip fmap (Map.toList $ snd inputs) (\(path, outs) -> - parens [s path, serializeList $ fmap s $ sort outs]) + serializeList $ (\(path, outs) -> + parens [s path, serializeList $ s <$> sort outs]) <$> Map.toList (snd inputs) , -- inputSrcs serializeList (fmap s $ Set.toList $ fst inputs) , s platform @@ -149,15 +149,14 @@ unparseDrv Derivation{..} = Text.append "Derive" $ parens , -- run script args serializeList $ fmap s args , -- env (key value pairs) - serializeList $ flip fmap (Map.toList env) (\(k, v) -> - parens [s k, s v]) + serializeList $ (\(k, v) -> parens [s k, s v]) <$> Map.toList env ] where parens :: [Text] -> Text parens ts = Text.concat ["(", Text.intercalate "," ts, ")"] serializeList :: [Text] -> Text serializeList ls = Text.concat ["[", Text.intercalate "," ls, "]"] - s = (Text.cons '\"') . (`Text.snoc` '\"') . Text.concatMap escape + s = Text.cons '\"' . (`Text.snoc` '\"') . Text.concatMap escape escape :: Char -> Text escape '\\' = "\\\\" escape '\"' = "\\\"" @@ -178,12 +177,12 @@ derivationParser :: Parsec () Text Derivation derivationParser = do _ <- "Derive(" fullOutputs <- serializeList $ - fmap (\[n, p, ht, h] -> (n, p, ht, h)) $ parens s + (\[n, p, ht, h] -> (n, p, ht, h)) <$> parens s _ <- "," inputDrvs <- fmap Map.fromList $ serializeList $ fmap (,) ("(" *> s <* ",") <*> (serializeList s <* ")") _ <- "," - inputSrcs <- fmap Set.fromList $ serializeList s + inputSrcs <- Set.fromList <$> serializeList s _ <- "," platform <- s _ <- "," @@ -191,7 +190,7 @@ derivationParser = do _ <- "," args <- serializeList s _ <- "," - env <- fmap Map.fromList $ serializeList $ fmap (\[a, b] -> (a, b)) $ parens s + env <- fmap Map.fromList $ serializeList $ (\[a, b] -> (a, b)) <$> parens s _ <- ")" eof @@ -213,7 +212,8 @@ derivationParser = do regular = noneOf ['\\', '"'] parens :: Parsec () Text a -> Parsec () Text [a] - parens p = (string "(") *> sepBy p (string ",") <* (string ")") + parens p = + (string "(") *> sepBy p (string ",") <* (string ")") serializeList p = (string "[") *> sepBy p (string ",") <* (string "]") parseFixed :: [(Text, Text, Text, Text)] -> (Maybe Store.SomeNamedDigest, HashMode) @@ -297,11 +297,11 @@ buildDerivationWithContext drvAttrs = do drvName <- getAttr "name" $ extractNixString >=> assertDrvStoreName withFrame' Info (ErrorCall $ "While evaluating derivation " <> show drvName) $ do - useJson <- getAttrOr "__structuredAttrs" False $ pure - ignoreNulls <- getAttrOr "__ignoreNulls" False $ pure + useJson <- getAttrOr "__structuredAttrs" False pure + ignoreNulls <- getAttrOr "__ignoreNulls" False pure args <- getAttrOr "args" mempty $ traverse (fromValue' >=> extractNixString) - builder <- getAttr "builder" $ extractNixString + builder <- getAttr "builder" extractNixString platform <- getAttr "system" $ extractNoCtx >=> assertNonNull mHash <- getAttrOr "outputHash" mempty $ extractNoCtx >=> (pure . pure) hashMode <- getAttrOr "outputHashMode" Flat $ extractNoCtx >=> parseHashMode @@ -311,7 +311,7 @@ buildDerivationWithContext drvAttrs = do maybe (pure Nothing) (\ hash -> do - when (outputs /= ["out"]) $ lift $ throwError $ ErrorCall $ "Multiple outputs are not supported for fixed-output derivations" + when (outputs /= ["out"]) $ lift $ throwError $ ErrorCall "Multiple outputs are not supported for fixed-output derivations" hashType <- getAttr "outputHashAlgo" extractNoCtx digest <- lift $ either (throwError . ErrorCall) pure $ Store.mkNamedDigest hashType hash pure $ pure digest) diff --git a/src/Nix/Eval.hs b/src/Nix/Eval.hs index 8c00450ad..35696fbde 100644 --- a/src/Nix/Eval.hs +++ b/src/Nix/Eval.hs @@ -440,7 +440,7 @@ evalSetterKeyName = \case StaticKey k -> pure (pure k) DynamicKey k -> - ((pure . stringIgnoreContext) `ifJust`) <$> runAntiquoted "\n" assembleString (fromValueMay =<<) k + ((pure . stringIgnoreContext) `whenJust`) <$> runAntiquoted "\n" assembleString (fromValueMay =<<) k assembleString :: forall v m diff --git a/src/Nix/Exec.hs b/src/Nix/Exec.hs index fad478dfe..7f00fd741 100644 --- a/src/Nix/Exec.hs +++ b/src/Nix/Exec.hs @@ -1,5 +1,4 @@ {-# LANGUAGE AllowAmbiguousTypes #-} -{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE CPP #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-} @@ -289,17 +288,18 @@ callFunc -> m (NValue t f m) callFunc fun arg = do - fun' <- demand fun frames :: Frames <- asks (view hasLens) when (length frames > 2000) $ throwError $ ErrorCall "Function call stack exhausted" + + fun' <- demand fun case fun' of - NVClosure _params f -> do - f arg - NVBuiltin name f -> do - span <- currentPos - withFrame Info (Calling @m @(NValue t f m) name span) (f arg) - s@(NVSet m _) | Just f <- M.lookup "__functor" m -> do - ((`callFunc` arg) <=< (`callFunc` s)) =<< demand f + NVClosure _params f -> f arg + NVBuiltin name f -> + do + span <- currentPos + withFrame Info ((Calling @m @(NValue t f m)) name span) (f arg) + (NVSet m _) | Just f <- M.lookup "__functor" m -> + ((`callFunc` arg) <=< (`callFunc` fun')) =<< demand f x -> throwError $ ErrorCall $ "Attempt to call non-function: " <> show x execUnaryOp @@ -311,12 +311,13 @@ execUnaryOp -> m (NValue t f m) execUnaryOp scope span op arg = do case arg of - NVConstant c -> case (op, c) of - (NNeg, NInt i ) -> unaryOp $ NInt (-i) - (NNeg, NFloat f) -> unaryOp $ NFloat (-f) - (NNot, NBool b ) -> unaryOp $ NBool (not b) - _ -> - throwError $ ErrorCall $ "unsupported argument type for unary operator " <> show op + NVConstant c -> + case (op, c) of + (NNeg, NInt i ) -> unaryOp $ NInt (-i) + (NNeg, NFloat f) -> unaryOp $ NFloat (-f) + (NNot, NBool b ) -> unaryOp $ NBool (not b) + _ -> + throwError $ ErrorCall $ "unsupported argument type for unary operator " <> show op x -> throwError $ ErrorCall $ "argument to unary operator must evaluate to an atomic type: " <> show x where diff --git a/src/Nix/Expr/Strings.hs b/src/Nix/Expr/Strings.hs index 687936665..08b9f900a 100644 --- a/src/Nix/Expr/Strings.hs +++ b/src/Nix/Expr/Strings.hs @@ -98,7 +98,7 @@ stripIndent xs = dropSpaces 0 x = x dropSpaces n (Plain t : cs) = Plain (T.drop n t) : cs - dropSpaces _ _ = error "stripIndent: impossible" + dropSpaces _ _ = fail "stripIndent: impossible" cleanup (Nothing, Plain y) = T.all (== ' ') y cleanup (Just (Plain x), Plain y) | "\n" `T.isSuffixOf` x = T.all (== ' ') y diff --git a/src/Nix/Expr/Types.hs b/src/Nix/Expr/Types.hs index 0467801a2..b61254fb4 100644 --- a/src/Nix/Expr/Types.hs +++ b/src/Nix/Expr/Types.hs @@ -231,7 +231,7 @@ instance IsString (NString r) where -- In particular, those include: -- -- * The RHS of a @binding@ inside @let@: @let ${"a"} = 3; in ...@ --- produces a syntax error. +-- produces a syntax fail. -- * The attribute names of an 'inherit': @inherit ${"a"};@ is forbidden. -- -- Note: In Nix, a simple string without antiquotes such as @"foo"@ is diff --git a/src/Nix/Frames.hs b/src/Nix/Frames.hs index 2f701ab0c..b2c7fd56a 100644 --- a/src/Nix/Frames.hs +++ b/src/Nix/Frames.hs @@ -61,5 +61,5 @@ throwError :: forall s e m a . (Framed e m, Exception s, MonadThrow m) => s -> m a throwError err = do context <- asks (view hasLens) - traceM "Throwing error..." + traceM "Throwing fail..." throwM $ NixException (NixFrame Error (toException err) : context) diff --git a/src/Nix/Lint.hs b/src/Nix/Lint.hs index 3b8bc1b38..57d8eb3fe 100644 --- a/src/Nix/Lint.hs +++ b/src/Nix/Lint.hs @@ -13,7 +13,6 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE InstanceSigs #-} -{-# LANGUAGE ApplicativeDo #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_GHC -Wno-missing-methods #-} @@ -236,7 +235,7 @@ merge context = go <$> go xs ys -} --- | unify raises an error if the result is would be 'NMany mempty'. +-- | unify raises an fail if the result is would be 'NMany mempty'. unify :: forall e m . MonadLint e m @@ -412,7 +411,7 @@ lintBinaryOp op lsym rarg = NConcat -> [TList y] - _ -> error "Should not be possible" -- symerr or this fun signature should be changed to work in type scope + _ -> fail "Should not be possible" -- symerr or this fun signature should be changed to work in type scope where check lsym rsym xs = do @@ -468,7 +467,7 @@ instance MonadThrow (Lint s) where throwM e = Lint $ ReaderT $ \_ -> throw e instance MonadCatch (Lint s) where - catch _m _h = Lint $ ReaderT $ \_ -> error "Cannot catch in 'Lint s'" + catch _m _h = Lint $ ReaderT $ \_ -> fail "Cannot catch in 'Lint s'" runLintM :: Options -> Lint s a -> ST s a runLintM opts action = do diff --git a/src/Nix/Normal.hs b/src/Nix/Normal.hs index 703b3f70a..6b1c1c0f8 100644 --- a/src/Nix/Normal.hs +++ b/src/Nix/Normal.hs @@ -61,7 +61,7 @@ normalizeValue v = run $ iterNValueM run go (fmap Free . sequenceNValue' run) v (do i <- ask when (i > 2000) - $ error "Exceeded maximum normalization depth of 2000 levels" + $ fail "Exceeded maximum normalization depth of 2000 levels" -- 2021-02-22: NOTE: `normalizeValue` should be adopted to work without fliping of the force (f) lifted (lifted $ \f -> f =<< force t) $ local succ . k ) diff --git a/src/Nix/Options/Parser.hs b/src/Nix/Options/Parser.hs index 195174645..67fc63656 100644 --- a/src/Nix/Options/Parser.hs +++ b/src/Nix/Options/Parser.hs @@ -8,7 +8,10 @@ import Data.Char ( isDigit ) import Data.Maybe ( fromMaybe ) import Data.Text ( Text ) import qualified Data.Text as Text -import Data.Time +import Data.Time ( UTCTime + , defaultTimeLocale + , parseTimeOrError + ) import Nix.Options import Options.Applicative hiding ( ParserResult(..) ) import Data.Version ( showVersion ) @@ -16,6 +19,7 @@ import Development.GitRev ( gitCommitDate , gitBranch , gitHash ) import Paths_hnix ( version ) +import Nix.Utils ( bool ) decodeVerbosity :: Int -> Verbosity decodeVerbosity 0 = ErrorsOnly @@ -26,32 +30,37 @@ 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 -> pure $ second Text.tail $ Text.splitAt i s +argPair = + option $ + do + s <- str + maybe + (errorWithoutStackTrace "Format of --arg/--argstr in hnix is: name=expr") + (pure . second Text.tail . (`Text.splitAt` s)) + (Text.findIndex (== '=') s) nixOptions :: UTCTime -> Parser Options nixOptions current = - Options - <$> (fromMaybe Informational <$> - optional - (option + Options <$> + (fromMaybe Informational <$> + 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" - ) + (do + a <- str + bool + (fail "Argument to -v/--verbose must be a number") + (pure $ decodeVerbosity $ read a) + (all isDigit a) + ) + ( short 'v' + <> long "verbose" + <> help "Verbose output" ) + ) + ) <*> switch ( long "trace" <> help "Enable tracing code (even more can be seen if built with --flags=tracing)" @@ -132,7 +141,7 @@ nixOptions current = ) <*> switch ( long "check" - <> help "Whether to check for syntax errors after parsing" + <> help "Whether to check for syntax fails after parsing" ) <*> optional (strOption @@ -149,8 +158,8 @@ nixOptions current = <> help "After performing any indicated actions, enter the REPL" ) <*> switch - ( long "ignore-errors" - <> help "Continue parsing files, even if there are errors" + ( long "ignore-fails" + <> help "Continue parsing files, even if there are fails" ) <*> optional (strOption @@ -194,26 +203,30 @@ versionOpt :: Parser (a -> a) versionOpt = shortVersionOpt <*> debugVersionOpt where shortVersionOpt :: Parser (a -> a) - shortVersionOpt = infoOption - (showVersion version) - ( long "version" - <> help "Show release version" - ) + shortVersionOpt = + infoOption + (showVersion version) + ( long "version" + <> help "Show release version" + ) -- 2020-09-13: NOTE: Does not work for direct `nix-build`s, works for `nix-shell` `cabal` builds. debugVersionOpt :: Parser (a -> a) - debugVersionOpt = infoOption - ( concat - [ "Version: ", showVersion version - , "\nCommit: ", $(gitHash) - , "\n date: ", $(gitCommitDate) - , "\n branch: ", $(gitBranch) - ] - ) - ( long "long-version" - <> help "Show long debug version form" - ) + debugVersionOpt = + infoOption + ( concat + [ "Version: ", showVersion version + , "\nCommit: ", $(gitHash) + , "\n date: ", $(gitCommitDate) + , "\n branch: ", $(gitBranch) + ] + ) + ( long "long-version" + <> help "Show long debug version form" + ) nixOptionsInfo :: UTCTime -> ParserInfo Options -nixOptionsInfo current = info (helper <*> versionOpt <*> nixOptions current) - (fullDesc <> progDesc "" <> header "hnix") +nixOptionsInfo current = + info + (helper <*> versionOpt <*> nixOptions current) + (fullDesc <> progDesc "" <> header "hnix") diff --git a/src/Nix/Parser.hs b/src/Nix/Parser.hs index e6b00fa5e..84df7a2f1 100644 --- a/src/Nix/Parser.hs +++ b/src/Nix/Parser.hs @@ -1,11 +1,9 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveDataTypeable #-} -{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE ApplicativeDo #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_GHC -Wno-missing-signatures #-} @@ -19,7 +17,7 @@ module Nix.Parser , parseFromFileEx , Parser , parseFromText - , Result(..) + , Result , reservedNames , OperatorInfo(..) , NSpecialOp(..) @@ -566,8 +564,8 @@ reservedNames = type Parser = ParsecT Void Text (State SourcePos) --- This is just a @Either (Doc Void) a@ -data Result a = Success a | Failure (Doc Void) deriving (Show, Functor) +type Result a = Either (Doc Void) a + parseFromFileEx :: MonadFile m => Parser a -> FilePath -> m (Result a) parseFromFileEx p path = @@ -576,16 +574,16 @@ parseFromFileEx p path = pure $ either - (Failure . pretty . errorBundlePretty) - Success + (Left . pretty . errorBundlePretty) + Right $ (`evalState` initialPos path) $ runParserT p path txt parseFromText :: Parser a -> Text -> Result a parseFromText p txt = let file = "" in either - (Failure . pretty . errorBundlePretty) - Success + (Left . pretty . errorBundlePretty) + Right $ (`evalState` initialPos file) $ (`runParserT` file) p txt {- Parser.Operators -} @@ -724,7 +722,7 @@ getUnaryOperator = (m Map.!) zipWith buildEntry [1 ..] - (nixOperators (error "unused")) + (nixOperators (fail "unused")) buildEntry i = concatMap $ @@ -741,7 +739,7 @@ getBinaryOperator = (m Map.!) zipWith buildEntry [1 ..] - (nixOperators (error "unused")) + (nixOperators (fail "unused")) buildEntry i = concatMap $ @@ -759,7 +757,7 @@ getSpecialOperator o = m Map.! o zipWith buildEntry [1 ..] - (nixOperators (error "unused")) + (nixOperators (fail "unused")) buildEntry i = concatMap $ diff --git a/src/Nix/Pretty.hs b/src/Nix/Pretty.hs index 1ed7c5d5a..44e0a8e1c 100644 --- a/src/Nix/Pretty.hs +++ b/src/Nix/Pretty.hs @@ -14,7 +14,7 @@ module Nix.Pretty where import Control.Applicative ( (<|>) ) -import Control.Monad.Free +import Control.Monad.Free ( Free(Free) ) import Data.Fix ( Fix(..) , foldFix ) import Data.HashMap.Lazy ( toList ) @@ -144,7 +144,7 @@ prettyString (Indented _ parts) = group $ nest 2 $ vcat prettyParams :: Params (NixDoc ann) -> Doc ann prettyParams (Param n ) = pretty n prettyParams (ParamSet s v mname) = prettyParamSet s v <> - (\ name -> ("@" <> pretty name) `ifTrue` not (Text.null name)) `ifJust` mname + (\ name -> ("@" <> pretty name) `whenTrue` not (Text.null name)) `whenJust` mname prettyParamSet :: ParamSet (NixDoc ann) -> Bool -> Doc ann prettyParamSet args var = @@ -168,7 +168,7 @@ prettyBind (NamedVar n v _p) = prettyBind (Inherit s ns _p) = "inherit " <> scope <> align (fillSep (fmap prettyKeyName ns)) <> ";" where - scope = ((<> " ") . parens . withoutParens) `ifJust` s + scope = ((<> " ") . parens . withoutParens) `whenJust` s prettyKeyName :: NKeyName (NixDoc ann) -> Doc ann prettyKeyName (StaticKey "") = "\"\"" @@ -252,7 +252,7 @@ exprFNixDoc = \case $ wrapPath selectOp r <> "." <> prettySelector attr <> ordoc where r = mkNixDoc selectOp (wrapParens appOpNonAssoc r') - ordoc = ((" or " <>) . wrapParens appOpNonAssoc) `ifJust` o + ordoc = ((" or " <>) . wrapParens appOpNonAssoc) `whenJust` o NHasAttr r attr -> mkNixDoc hasAttrOp (wrapParens hasAttrOp r <> " ? " <> prettySelector attr) NEnvPath p -> simpleExpr $ pretty ("<" <> p <> ">") diff --git a/src/Nix/Reduce.hs b/src/Nix/Reduce.hs index 6574c49fa..f7b3ca155 100644 --- a/src/Nix/Reduce.hs +++ b/src/Nix/Reduce.hs @@ -1,6 +1,5 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE AllowAmbiguousTypes #-} -{-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} @@ -32,21 +31,39 @@ module Nix.Reduce import Control.Applicative import Control.Arrow ( second ) -import Control.Monad -import Control.Monad.Catch +import Control.Monad ( MonadPlus + , join + ) +import Control.Monad.Catch ( MonadCatch(catch) ) #if !MIN_VERSION_base(4,13,0) +import Prelude hiding ( fail ) import Control.Monad.Fail #endif -import Control.Monad.Fix -import Control.Monad.IO.Class -import Control.Monad.Reader -import Control.Monad.State.Strict +import Control.Monad.Fix ( MonadFix ) +import Control.Monad.IO.Class ( MonadIO(liftIO) ) +import Control.Monad.Reader ( MonadReader(local) + , ReaderT(runReaderT) + , asks + ) +import Control.Monad.State.Strict ( MonadState + , StateT + , gets + , modify + , evalStateT + ) import Data.Bifunctor ( first ) -import Data.Fix ( Fix(..), foldFix, foldFixM ) +import Data.Fix ( Fix(..) + , foldFix + , foldFixM + ) import Data.HashMap.Lazy ( HashMap ) import qualified Data.HashMap.Lazy as M import qualified Data.HashMap.Strict as MS -import Data.IORef +import Data.IORef ( IORef + , newIORef + , readIORef + , writeIORef + ) import Data.List.NonEmpty ( NonEmpty(..) ) import qualified Data.List.NonEmpty as NE import Data.Maybe ( fromMaybe @@ -69,12 +86,25 @@ import System.Directory import System.FilePath newtype Reducer m a = Reducer - { runReducer :: ReaderT (Maybe FilePath, Scopes (Reducer m) NExprLoc) - (StateT (HashMap FilePath NExprLoc, MS.HashMap Text Text) m) a } - deriving (Functor, Applicative, Alternative, Monad, MonadPlus, - MonadFix, MonadIO, MonadFail, - MonadReader (Maybe FilePath, Scopes (Reducer m) NExprLoc), - MonadState (HashMap FilePath NExprLoc, MS.HashMap Text Text)) + { runReducer :: + ReaderT + ( Maybe FilePath + , Scopes (Reducer m) NExprLoc + ) + ( StateT + ( HashMap FilePath NExprLoc + , MS.HashMap Text Text + ) + m + ) + a + } + deriving + ( Functor, Applicative, Alternative + , Monad, MonadPlus, MonadFix, MonadIO, MonadFail + , MonadReader (Maybe FilePath, Scopes (Reducer m) NExprLoc) + , MonadState (HashMap FilePath NExprLoc, MS.HashMap Text Text) + ) staticImport :: forall m @@ -94,29 +124,35 @@ staticImport pann path = do (maybe path (\p -> takeDirectory p path) mfile) imports <- gets fst - case M.lookup path' imports of - Just expr -> pure expr - Nothing -> go path' + maybe + (go path') + pure + (M.lookup path' imports) where go path = do liftIO $ putStrLn $ "Importing file " <> path eres <- liftIO $ parseNixFileLoc path - case eres of - Failure err -> error $ "Parse failed: " <> show err - Success x -> do + either + (\ err -> fail $ "Parse failed: " <> show err) + (\ x -> do let pos = SourcePos "Reduce.hs" (mkPos 1) (mkPos 1) span = SrcSpan pos pos - cur = NamedVar (StaticKey "__cur_file" :| mempty) - (Fix (NLiteralPath_ pann path)) - pos + cur = + NamedVar + (StaticKey "__cur_file" :| mempty) + (Fix (NLiteralPath_ pann path)) + pos x' = Fix (NLet_ span [cur] x) modify (first (M.insert path x')) - local (const (pure path, emptyScopes @m @NExprLoc)) $ do - x'' <- foldFix reduce x' - modify (first (M.insert path x'')) - pure x'' + local (const (pure path, emptyScopes @m @NExprLoc)) $ + do + x'' <- foldFix reduce x' + modify (first (M.insert path x'')) + pure x'' + ) + eres -- gatherNames :: NExprLoc -> HashSet VarName -- gatherNames = foldFix $ \case @@ -144,17 +180,18 @@ reduce -- | Reduce the variable to its value if defined. -- Leave it as it is otherwise. -reduce (NSym_ ann var) = lookupVar var <&> \case - Nothing -> Fix (NSym_ ann var) - Just v -> v +reduce (NSym_ ann var) = + fromMaybe (Fix (NSym_ ann var)) <$> lookupVar var -- | Reduce binary and integer negation. -reduce (NUnary_ uann op arg) = arg >>= \x -> case (op, x) of - (NNeg, Fix (NConstant_ cann (NInt n))) -> - pure $ Fix $ NConstant_ cann (NInt (negate n)) - (NNot, Fix (NConstant_ cann (NBool b))) -> - pure $ Fix $ NConstant_ cann (NBool (not b)) - _ -> pure $ Fix $ NUnary_ uann op x +reduce (NUnary_ uann op arg) = + do + x <- arg + pure $ Fix $ + case (op, x) of + (NNeg, Fix (NConstant_ cann (NInt n))) -> NConstant_ cann (NInt (negate n)) + (NNot, Fix (NConstant_ cann (NBool b))) -> NConstant_ cann (NBool (not b)) + _ -> NUnary_ uann op x -- | Reduce function applications. -- @@ -163,25 +200,31 @@ reduce (NUnary_ uann op arg) = arg >>= \x -> case (op, x) of -- * Reduce a lambda function by adding its name to the local -- scope and recursively reducing its body. reduce (NBinary_ bann NApp fun arg) = fun >>= \case - f@(Fix (NSym_ _ "import")) -> arg >>= \case - -- Fix (NEnvPath_ pann origPath) -> staticImport pann origPath - Fix (NLiteralPath_ pann origPath) -> staticImport pann origPath - v -> pure $ Fix $ NBinary_ bann NApp f v - - Fix (NAbs_ _ (Param name) body) -> do - x <- arg - pushScope (M.singleton name x) (foldFix reduce body) + f@(Fix (NSym_ _ "import")) -> + (\case + -- Fix (NEnvPath_ pann origPath) -> staticImport pann origPath + Fix (NLiteralPath_ pann origPath) -> staticImport pann origPath + v -> pure $ Fix $ NBinary_ bann NApp f v + ) =<< arg + + Fix (NAbs_ _ (Param name) body) -> + do + x <- arg + pushScope + (M.singleton name x) + (foldFix reduce body) f -> Fix . NBinary_ bann NApp f <$> arg -- | Reduce an integer addition to its result. -reduce (NBinary_ bann op larg rarg) = do - lval <- larg - rval <- rarg - case (op, lval, rval) of - (NPlus, Fix (NConstant_ ann (NInt x)), Fix (NConstant_ _ (NInt y))) -> - pure $ Fix (NConstant_ ann (NInt (x + y))) - _ -> pure $ Fix $ NBinary_ bann op lval rval +reduce (NBinary_ bann op larg rarg) = + do + lval <- larg + rval <- rarg + pure $ Fix $ + case (op, lval, rval) of + (NPlus, Fix (NConstant_ ann (NInt x)), Fix (NConstant_ _ (NInt y))) -> NConstant_ ann (NInt (x + y)) + _ -> NBinary_ bann op lval rval -- | Reduce a select on a Set by substituting the set to the selected value. -- @@ -199,7 +242,7 @@ reduce base@(NSelect_ _ _ attrs _) sId = Fix <$> sequence base -- The selection AttrPath is composed of StaticKeys. sAttrPath (StaticKey _ : xs) = sAttrPath xs - sAttrPath [] = True + sAttrPath [] = True sAttrPath _ = False -- Find appropriate bind in set's binds. findBind [] _ = Nothing @@ -229,9 +272,10 @@ reduce e@(NSet_ ann NNonRecursive binds) = ) binds - if usesInherit - then clearScopes @NExprLoc $ Fix . NSet_ ann NNonRecursive <$> traverse sequence binds - else Fix <$> sequence e + bool + (Fix <$> sequence e) + (clearScopes @NExprLoc $ Fix . NSet_ ann NNonRecursive <$> traverse sequence binds) + usesInherit -- Encountering a 'rec set' construction eliminates any hope of inlining -- definitions. @@ -285,22 +329,28 @@ reduce (NLet_ ann binds body) = -- | Reduce an if to the relevant path if -- the condition is a boolean constant. -reduce e@(NIf_ _ b t f) = b >>= \case - Fix (NConstant_ _ (NBool b')) -> if b' then t else f - _ -> Fix <$> sequence e +reduce e@(NIf_ _ b t f) = + (\case + Fix (NConstant_ _ (NBool b')) -> if b' then t else f + _ -> Fix <$> sequence e + ) =<< b -- | Reduce an assert atom to its encapsulated -- symbol if the assertion is a boolean constant. -reduce e@(NAssert_ _ b body) = b >>= \case - Fix (NConstant_ _ (NBool b')) | b' -> body - _ -> Fix <$> sequence e +reduce e@(NAssert_ _ b body) = + (\case + Fix (NConstant_ _ (NBool b')) | b' -> body + _ -> Fix <$> sequence e + ) =<< b reduce (NAbs_ ann params body) = do params' <- sequence params -- Make sure that variable definitions in scope do not override function -- arguments. - let args = case params' of - Param name -> M.singleton name (Fix (NSym_ ann name)) + let + args = + case params' of + Param name -> M.singleton name (Fix (NSym_ ann name)) ParamSet pset _ _ -> M.fromList $ fmap (\(k, _) -> (k, Fix (NSym_ ann k))) pset Fix . NAbs_ ann params' <$> pushScope args body @@ -309,7 +359,7 @@ reduce v = Fix <$> sequence v -- newtype FlaggedF f r = FlaggedF { flagged :: (IORef Bool, f r) } newtype FlaggedF f r = FlaggedF (IORef Bool, f r) - deriving (Functor, Foldable, Traversable) + deriving (Functor, Foldable, Traversable) instance Show (f r) => Show (FlaggedF f r) where show (FlaggedF (_, x)) = show x @@ -325,9 +375,16 @@ flagExprLoc = foldFixM $ \x -> do -- stripFlags = foldFix $ Fix . snd . flagged pruneTree :: MonadIO n => Options -> Flagged NExprLocF -> n (Maybe NExprLoc) -pruneTree opts = foldFixM $ \(FlaggedF (b, Compose x)) -> do - used <- liftIO $ readIORef b - pure $ if used then Fix . Compose <$> traverse prune x else Nothing +pruneTree opts = + foldFixM $ + \(FlaggedF (b, Compose x)) -> + do + used <- liftIO $ readIORef b + pure $ + bool + Nothing + (Fix . Compose <$> traverse prune x) + used where prune :: NExprF (Maybe NExprLoc) -> Maybe (NExprF NExprLoc) prune = \case @@ -352,7 +409,7 @@ pruneTree opts = foldFixM $ \(FlaggedF (b, Compose x)) -> do -- These are the only short-circuiting binary operators NBinary NAnd (Just (Fix (Compose (Ann _ larg)))) _ -> pure larg - NBinary NOr (Just (Fix (Compose (Ann _ larg)))) _ -> pure larg + NBinary NOr (Just (Fix (Compose (Ann _ larg)))) _ -> pure larg -- If the function was never called, it means its argument was in a -- thunk that was forced elsewhere. @@ -360,7 +417,7 @@ pruneTree opts = foldFixM $ \(FlaggedF (b, Compose x)) -> do -- The idea behind emitted a binary operator where one side may be -- invalid is that we're trying to emit what will reproduce whatever - -- error the user encountered, which means providing all aspects of + -- fail the user encountered, which means providing all aspects of -- the evaluation path they ultimately followed. NBinary op Nothing (Just rarg) -> pure $ NBinary op nNull rarg NBinary op (Just larg) Nothing -> pure $ NBinary op larg nNull @@ -369,12 +426,12 @@ pruneTree opts = foldFixM $ \(FlaggedF (b, Compose x)) -> do NWith Nothing (Just (Fix (Compose (Ann _ body)))) -> pure body NAssert Nothing _ -> - error "How can an assert be used, but its condition not?" + fail "How can an assert be used, but its condition not?" NAssert _ (Just (Fix (Compose (Ann _ body)))) -> pure body NAssert (Just cond) _ -> pure $ NAssert cond nNull - NIf Nothing _ _ -> error "How can an if be used, but its condition not?" + NIf Nothing _ _ -> fail "How can an if be used, but its condition not?" NIf _ Nothing (Just (Fix (Compose (Ann _ f)))) -> pure f NIf _ (Just (Fix (Compose (Ann _ t)))) Nothing -> pure t @@ -390,16 +447,16 @@ pruneTree opts = foldFixM $ \(FlaggedF (b, Compose x)) -> do :: Antiquoted Text (Maybe NExprLoc) -> Maybe (Antiquoted Text NExprLoc) pruneAntiquotedText (Plain v) = pure (Plain v) pruneAntiquotedText EscapedNewline = pure EscapedNewline - pruneAntiquotedText (Antiquoted Nothing ) = Nothing pruneAntiquotedText (Antiquoted (Just k)) = pure (Antiquoted k) + pruneAntiquotedText (Antiquoted Nothing ) = Nothing pruneAntiquoted :: Antiquoted (NString (Maybe NExprLoc)) (Maybe NExprLoc) -> Maybe (Antiquoted (NString NExprLoc) NExprLoc) pruneAntiquoted (Plain v) = pure (Plain (pruneString v)) pruneAntiquoted EscapedNewline = pure EscapedNewline - pruneAntiquoted (Antiquoted Nothing ) = Nothing pruneAntiquoted (Antiquoted (Just k)) = pure (Antiquoted k) + pruneAntiquoted (Antiquoted Nothing ) = Nothing pruneKeyName :: NKeyName (Maybe NExprLoc) -> NKeyName NExprLoc pruneKeyName (StaticKey n) = StaticKey n @@ -416,12 +473,12 @@ pruneTree opts = foldFixM $ \(FlaggedF (b, Compose x)) -> do | otherwise = ParamSet (fmap (second (fmap (fromMaybe nNull))) xs) b n pruneBinding :: Binding (Maybe NExprLoc) -> Maybe (Binding NExprLoc) - pruneBinding (NamedVar _ Nothing _) = Nothing - pruneBinding (NamedVar xs (Just x) pos) = + pruneBinding (NamedVar _ Nothing _) = Nothing + pruneBinding (NamedVar xs (Just x) pos) = pure (NamedVar (NE.map pruneKeyName xs) x pos) pruneBinding (Inherit _ [] _) = Nothing - pruneBinding (Inherit (join -> Nothing) _ _) = Nothing - pruneBinding (Inherit (join -> m) xs pos) = + pruneBinding (Inherit (join -> Nothing) _ _) = Nothing + pruneBinding (Inherit (join -> m) xs pos) = pure (Inherit m (fmap pruneKeyName xs) pos) reducingEvalExpr diff --git a/src/Nix/Render.hs b/src/Nix/Render.hs index 408eb9999..106cefbfa 100644 --- a/src/Nix/Render.hs +++ b/src/Nix/Render.hs @@ -100,7 +100,7 @@ renderLocation (SrcSpan (SourcePos file begLine begCol) (SourcePos file' endLine , txt ] else pure msg -renderLocation (SrcSpan beg end) msg = fail $ "Don't know how to render range from " <> show beg <>" to " <> show end <>" for error: " <> show msg +renderLocation (SrcSpan beg end) msg = fail $ "Don't know how to render range from " <> show beg <>" to " <> show end <>" for fail: " <> show msg errorContext :: FilePath -> Pos -> Pos -> Pos -> Pos -> Doc a errorContext path bl bc _el _ec = diff --git a/src/Nix/Render/Frame.hs b/src/Nix/Render/Frame.hs index 7178ed4b8..a88e842c1 100644 --- a/src/Nix/Render/Frame.hs +++ b/src/Nix/Render/Frame.hs @@ -60,7 +60,7 @@ renderFrames (x : xs) = do frames where go :: NixFrame -> [Doc ann] - go f = (\ pos -> ["While evaluating at " <> pretty (sourcePosPretty pos) <> colon]) `ifJust` framePos @v @m f + go f = (\ pos -> ["While evaluating at " <> pretty (sourcePosPretty pos) <> colon]) `whenJust` framePos @v @m f framePos :: forall v (m :: * -> *) @@ -91,7 +91,7 @@ renderFrame (NixFrame level f) | Just (e :: ExecFrame t f m) <- fromException f = renderExecFrame level e | Just (e :: ErrorCall) <- fromException f = pure [pretty (show e)] | Just (e :: SynHoleInfo m v) <- fromException f = pure [pretty (show e)] - | otherwise = error $ "Unrecognized frame: " <> show f + | otherwise = fail $ "Unrecognized frame: " <> show f wrapExpr :: NExprF r -> NExpr wrapExpr x = Fix (Fix (NSym "") <$ x) diff --git a/src/Nix/TH.hs b/src/Nix/TH.hs index b1a7c93d3..ef8e38254 100644 --- a/src/Nix/TH.hs +++ b/src/Nix/TH.hs @@ -25,9 +25,11 @@ import Nix.Parser quoteExprExp :: String -> ExpQ quoteExprExp s = do - expr <- case parseNixText (Text.pack s) of - Failure err -> fail $ show err - Success e -> pure e + expr <- + either + (fail . show) + pure + (parseNixText (Text.pack s)) dataToExpQ (const Nothing `extQ` metaExp (freeVars expr) `extQ` (pure . liftText)) expr @@ -37,10 +39,14 @@ quoteExprExp s = do quoteExprPat :: String -> PatQ quoteExprPat s = do - expr <- case parseNixText (Text.pack s) of - Failure err -> fail $ show err - Success e -> pure e - dataToPatQ (const Nothing `extQ` metaPat (freeVars expr)) expr + expr <- + either + (fail . show) + pure + (parseNixText (Text.pack s)) + dataToPatQ + (const Nothing `extQ` metaPat (freeVars expr)) + expr freeVars :: NExpr -> Set VarName freeVars e = case unFix e of diff --git a/src/Nix/Thunk/Basic.hs b/src/Nix/Thunk/Basic.hs index ad66333db..a435f7708 100644 --- a/src/Nix/Thunk/Basic.hs +++ b/src/Nix/Thunk/Basic.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} @@ -23,14 +24,70 @@ import Control.Monad.Catch ( MonadCatch(..) ) import Nix.Thunk import Nix.Var -import Nix.Utils ( bool ) +import Nix.Utils ( bool + , dup + ) + + +-- * Data type @Deferred@ + +-- | Data is computed OR in a lazy thunk state which +-- is still not evaluated. +data Deferred m v = Computed v | Deferred (m v) + deriving (Functor, Foldable, Traversable) + +-- ** Utils + +-- | @Deferred (Computed|Deferred)@ analog of @either@. +deferred :: (v -> b) -> (m v -> b) -> Deferred m v -> b +deferred f1 f2 def = + case def of + Computed v -> f1 v + Deferred action -> f2 action +{-# inline deferred #-} + + +-- * Thunk references & lock handling + +-- | Thunk resource reference (@ref-tf: Ref m@), and as such also also hold +-- a @Bool@ lock flag. +type ThunkRef m = (Var m Bool) + +-- | Reference (@ref-tf: Ref m v@) to a value that the thunk holds. +type ThunkValueRef m v = Var m (Deferred m v) + +-- | @ref-tf@ lock instruction for @Ref m@ (@ThunkRef@). +lock :: Bool -> (Bool, Bool) +lock = (True, ) + +-- | @ref-tf@ unlock instruction for @Ref m@ (@ThunkRef@). +unlock :: Bool -> (Bool, Bool) +unlock = (False, ) + +-- | Takes @ref-tf: Ref m@ reference, returns Bool result of the operation. +lockThunk + :: ( MonadBasicThunk m + , MonadCatch m + ) + => ThunkRef m + -> m Bool +lockThunk r = atomicModifyVar r lock + +-- | Takes @ref-tf: Ref m@ reference, returns Bool result of the operation. +unlockThunk + :: ( MonadBasicThunk m + , MonadCatch m + ) + => ThunkRef m + -> m Bool +unlockThunk r = atomicModifyVar r unlock -data Deferred m v = Deferred (m v) | Computed v - deriving (Functor, Foldable, Traversable) + +-- * Data type for thunks: @NThunkF@ -- | The type of very basic thunks data NThunkF m v - = Thunk (ThunkId m) (Var m Bool) (Var m (Deferred m v)) + = Thunk (ThunkId m) (ThunkRef m) (ThunkValueRef m v) instance (Eq v, Eq (ThunkId m)) => Eq (NThunkF m v) where Thunk x _ _ == Thunk y _ _ = x == y @@ -40,87 +97,84 @@ instance Show (NThunkF m v) where type MonadBasicThunk m = (MonadThunkId m, MonadVar m) + +-- ** @instance MonadThunk NThunkF@ + instance (MonadBasicThunk m, MonadCatch m) => MonadThunk (NThunkF m v) m v where + -- | Return thunk ID thunkId :: NThunkF m v -> ThunkId m thunkId (Thunk n _ _) = n + -- | Create new thunk thunk :: m v -> m (NThunkF m v) thunk action = do freshThunkId <- freshId Thunk freshThunkId <$> newVar False <*> newVar (Deferred action) + -- | Non-blocking query, return value if @Computed@, + -- return first argument otherwise. queryM :: m v -> NThunkF m v -> m v - queryM n (Thunk _ active ref) = + queryM n (Thunk _ _ ref) = do - thunkIsAvaliable <- not <$> atomicModifyVar active (True, ) - bool - n - go - thunkIsAvaliable - where - go = do - eres <- readVar ref - res <- - case eres of - Computed v -> pure v - Deferred _mv -> n - _ <- atomicModifyVar active (False, ) - pure res + deferred + pure + (const n) + =<< readVar ref force :: NThunkF m v -> m v - force (Thunk n active ref) = - do - eres <- readVar ref - case eres of - Computed v -> pure v - Deferred action -> - do - nowActive <- atomicModifyVar active (True, ) - bool - (do - v <- catch action $ \(e :: SomeException) -> - do - _ <- atomicModifyVar active (False, ) - throwM e - writeVar ref (Computed v) - _ <- atomicModifyVar active (False, ) - pure v - ) - (throwM $ ThunkLoop $ show n) - nowActive + force = forceMain forceEff :: NThunkF m v -> m v - forceEff (Thunk _ active ref) = - do - nowActive <- atomicModifyVar active (True, ) - bool - (do - eres <- readVar ref - case eres of - Computed v -> pure v - Deferred action -> - do - v <- action - writeVar ref (Computed v) - _ <- atomicModifyVar active (False, ) - pure v - ) - (pure $ error "Loop detected") - nowActive + forceEff = forceMain further :: NThunkF m v -> m (NThunkF m v) - further t@(Thunk _ _ ref) = do - _ <- atomicModifyVar ref $ - \x -> case x of - Computed _ -> (x, x) - Deferred d -> (Deferred d, x) - pure t + further t@(Thunk _ _ ref) = + do + _ <- + atomicModifyVar + ref + dup + pure t --- * Kleisli functor HOFs +-- *** United body of `force*` + +-- | If @m v@ is @Computed@ - returns is +forceMain + :: ( MonadBasicThunk m + , MonadCatch m + ) + => NThunkF m v + -> m v +forceMain (Thunk n thunkRef thunkValRef) = + do + deferred + pure + (\ action -> + do + lockedIt <- lockThunk thunkRef + bool + (throwM $ ThunkLoop $ show n) + (do + v <- catch action $ \(e :: SomeException) -> + do + _unlockedIt <- unlockThunk thunkRef + throwM e + writeVar thunkValRef (Computed v) + _unlockedIt <- unlockThunk thunkRef + pure v + ) + (not lockedIt) + ) + =<< readVar thunkValRef +{-# inline forceMain #-} -- it is big function, but internal, and look at its use. + + + +-- ** Kleisli functor HOFs: @instance MonadThunkF NThunkF@ instance (MonadBasicThunk m, MonadCatch m) => MonadThunkF (NThunkF m v) m v where @@ -130,22 +184,23 @@ instance (MonadBasicThunk m, MonadCatch m) -> m r -> NThunkF m v -> m r - queryMF k n (Thunk _ active ref) = + queryMF k n (Thunk _ thunkRef thunkValRef) = do - thunkIsAvaliable <- not <$> atomicModifyVar active (True, ) + lockedIt <- lockThunk thunkRef bool n go - thunkIsAvaliable + (not lockedIt) where go = do - eres <- readVar ref + eres <- readVar thunkValRef res <- - case eres of - Computed v -> k v - Deferred _mv -> n - _ <- atomicModifyVar active (False, ) + deferred + k + (const n) + eres + _unlockedIt <- unlockThunk thunkRef pure res forceF @@ -166,9 +221,12 @@ instance (MonadBasicThunk m, MonadCatch m) -> m (NThunkF m v) furtherF k t@(Thunk _ _ ref) = do - _ <- atomicModifyVar ref $ - \x -> case x of - Computed _ -> (x, x) - Deferred d -> (Deferred (k d), x) + _modifiedIt <- atomicModifyVar ref $ + \x -> + deferred + (const (x, x)) + (\ d -> (Deferred (k d), x)) + x pure t + diff --git a/src/Nix/Utils.hs b/src/Nix/Utils.hs index 3f6cdb983..df2cd31ce 100644 --- a/src/Nix/Utils.hs +++ b/src/Nix/Utils.hs @@ -40,6 +40,9 @@ import Prelude as X hiding ( putStr , putStrLn , print +#if !MIN_VERSION_base(4,13,0) + , fail +#endif ) trace :: String -> a -> a trace = const id @@ -62,19 +65,21 @@ type AlgM f m a = f a -> m a -- | "Transform" here means a modification of a catamorphism. type Transform f a = (Fix f -> a) -> Fix f -> a -{-# inline (<&>)#-} (<&>) :: Functor f => f a -> (a -> c) -> f c (<&>) = flip (<$>) +{-# inline (<&>) #-} -{-# inline (??)#-} (??) :: Functor f => f (a -> b) -> a -> f b fab ?? a = fmap ($ a) fab +{-# inline (??) #-} loeb :: Functor f => f (f a -> a) -> f a loeb x = go where go = fmap ($ go) x loebM :: (MonadFix m, Traversable t) => t (t a -> m a) -> m (t a) -loebM f = mfix $ \a -> traverse ($ a) f +-- Sectioning here insures optimization happening. +loebM f = mfix $ \a -> (`traverse` f) ($ a) +{-# inline loebM #-} para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a para f = f . fmap (id &&& para f) . unFix @@ -175,15 +180,14 @@ alterF f k m = ) $ f $ M.lookup k m -{-# inline bool #-} -- | From @Data.Bool ( bool )@. bool :: a -> a -> Bool -> a bool f t b = if b then t else f +{-# inline bool #-} -{-# inline list #-} -- | Analog for @bool@ or @maybe@, for list-like cons structures. list :: Foldable t @@ -193,76 +197,78 @@ list e f l = (f l) e (null l) +{-# inline list #-} -{-# inline free #-} -- | Lambda analog of @maybe@ or @either@ for Free monad. free :: (a -> b) -> (f (Free f a) -> b) -> Free f a -> b free fP fF fr = case fr of Pure a -> fP a Free fa -> fF fa +{-# inline free #-} -{-# inline ifTrue #-} -ifTrue :: (Monoid a) + +whenTrue :: (Monoid a) => a -> Bool -> a -ifTrue = +whenTrue = bool mempty +{-# inline whenTrue #-} -{-# inline ifFalse #-} -ifFalse :: (Monoid a) +whenFalse :: (Monoid a) => a -> Bool -> a -ifFalse f = +whenFalse f = bool f mempty +{-# inline whenFalse #-} -{-# inline ifJust #-} -ifJust :: (Monoid b) +whenJust :: (Monoid b) => (a -> b) -> Maybe a -> b -ifJust = +whenJust = maybe mempty +{-# inline whenJust #-} -{-# inline ifNothing #-} -ifNothing :: (Monoid b) +whenNothing :: (Monoid b) => b -> Maybe a -> b -ifNothing f = +whenNothing f = maybe f mempty +{-# inline whenNothing #-} -{-# inline ifRight #-} -ifRight :: (Monoid c) +whenRight :: (Monoid c) => (b -> c) -> Either a b -> c -ifRight = +whenRight = either mempty +{-# inline whenRight #-} -{-# inline ifLeft #-} -ifLeft :: (Monoid c) +whenLeft :: (Monoid c) => (a -> c) -> Either a b -> c -ifLeft f = +whenLeft f = either f mempty +{-# inline whenLeft #-} -{-# inline ifFree #-} -ifFree :: (Monoid b) +whenFree :: (Monoid b) => (f (Free f a) -> b) -> Free f a -> b -ifFree = +whenFree = free mempty +{-# inline whenFree #-} -{-# inline ifPure #-} -ifPure :: (Monoid b) +whenPure :: (Monoid b) => (a -> b) -> Free f a -> b -ifPure f = +whenPure f = free f mempty +{-# inline whenPure #-} --- From @base@ @Data.Foldable@ +-- | From @base@ @Data.Foldable@ traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f () traverse_ f = foldr c (pure ()) -- See Note [List fusion and continuations in 'c'] @@ -273,3 +279,18 @@ traverse_ f = foldr c (pure ()) for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f () for_ = flip traverse_ {-# inline for_ #-} + +-- | Apply a single function to both components of a pair. +-- +-- > both succ (1,2) == (2,3) +-- +-- Taken From package @extra@ +both :: (a -> b) -> (a, a) -> (b, b) +both f (x,y) = (f x, f y) +{-# inline both #-} + + +-- | Duplicates object into a tuple. +dup :: a -> (a, a) +dup x = (x, x) +{-# inline dup #-} diff --git a/src/Nix/Utils/Fix1.hs b/src/Nix/Utils/Fix1.hs index 921187c9f..1b2e2fe11 100644 --- a/src/Nix/Utils/Fix1.hs +++ b/src/Nix/Utils/Fix1.hs @@ -19,9 +19,11 @@ import Control.Monad ( MonadPlus ) import Control.Monad.Fix ( MonadFix ) import Control.Monad.IO.Class ( MonadIO ) import Control.Monad.Trans.Class ( MonadTrans - , lift ) + , lift + ) import Control.Monad.Ref ( MonadAtomicRef(..) - , MonadRef(..) ) + , MonadRef(..) + ) import Control.Monad.Catch ( MonadCatch , MonadMask , MonadThrow ) @@ -90,16 +92,25 @@ deriving instance MonadState s (t (Fix1T t m) m) type MonadFix1T t m = (MonadTrans (Fix1T t), Monad (t (Fix1T t m) m)) -instance (MonadFix1T t m, MonadRef m) - => MonadRef (Fix1T t m) where +instance + ( MonadFix1T t m + , MonadRef m + ) + => MonadRef (Fix1T t m) + where type Ref (Fix1T t m) = Ref m + newRef = lift . newRef readRef = lift . readRef writeRef r = lift . writeRef r -instance (MonadFix1T t m, MonadAtomicRef m) - => MonadAtomicRef (Fix1T t m) where +instance + ( MonadFix1T t m + , MonadAtomicRef m + ) + => MonadAtomicRef (Fix1T t m) + where atomicModifyRef r = lift . atomicModifyRef r {- diff --git a/src/Nix/Value.hs b/src/Nix/Value.hs index c42521074..0540c859d 100644 --- a/src/Nix/Value.hs +++ b/src/Nix/Value.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE ConstraintKinds #-} @@ -34,6 +35,9 @@ import Control.Monad.Free ( Free(..) import Control.Monad.Trans.Class ( MonadTrans , lift ) +#if !MIN_VERSION_base(4,13,0) +import Control.Monad.Fail +#endif import qualified Data.Aeson as Aeson import Data.Functor.Classes ( Show1 , liftShowsPrec @@ -55,6 +59,9 @@ import Nix.Thunk import Nix.Utils import Data.Eq.Deriving + +-- * @__NValueF__@: Base functor + -- | An NValueF p m r represents all the possible types of Nix values. -- -- Is is the base functor to form the Free monad of nix expressions. @@ -119,8 +126,6 @@ import Data.Eq.Deriving -- pattern to account for the possibility of an NValue to no be fully -- evaluated yet, as opposed to an NValue'. --- * @__NValueF__@: Base functor - data NValueF p m r = NVConstantF NAtom -- | A string has a value and a context, which can be used to record what a @@ -778,7 +783,7 @@ type MonadDataContext f (m :: * -> *) -- * @MonadDataErrorContext@ type MonadDataErrorContext t f m - = (Show t, Typeable t, Typeable m, Typeable f, MonadDataContext f m) + = (Show t, Typeable t, Typeable m, Typeable f, MonadDataContext f m, MonadFail m) instance MonadDataErrorContext t f m => Exception (ValueFrame t f m) diff --git a/src/Nix/XML.hs b/src/Nix/XML.hs index 133db784f..96adb13fe 100644 --- a/src/Nix/XML.hs +++ b/src/Nix/XML.hs @@ -72,7 +72,7 @@ paramsXML (ParamSet s b mname) = where battr = [ Attr (unqual "ellipsis") "1" | b ] nattr = - ((: mempty) . Attr (unqual "name") . Text.unpack) `ifJust` mname + ((: mempty) . Attr (unqual "name") . Text.unpack) `whenJust` mname paramSetXML :: ParamSet r -> [Content] paramSetXML = fmap (\(k, _) -> Elem $ mkElem "attr" "name" (Text.unpack k)) diff --git a/tests/EvalTests.hs b/tests/EvalTests.hs index e9075b72d..7122a0cdf 100644 --- a/tests/EvalTests.hs +++ b/tests/EvalTests.hs @@ -23,6 +23,7 @@ import Nix import Nix.Standard import Nix.TH import Nix.Value.Equal +import Nix.Utils import qualified System.Directory as D import System.Environment import System.FilePath @@ -466,10 +467,10 @@ constantEqual expected actual = do assertBool message eq constantEqualText' :: Text -> Text -> Assertion -constantEqualText' expected actual = do - let Success expected' = parseNixTextLoc expected - Success actual' = parseNixTextLoc actual - constantEqual expected' actual' +constantEqualText' expected actual = + do + let (Right expected', Right actual') = both parseNixTextLoc (expected, actual) + constantEqual expected' actual' constantEqualText :: Text -> Text -> Assertion constantEqualText expected actual = do @@ -479,23 +480,30 @@ constantEqualText expected actual = do assertEvalMatchesNix actual assertNixEvalThrows :: Text -> Assertion -assertNixEvalThrows a = do - let Success a' = parseNixTextLoc a - time <- getCurrentTime - let opts = defaultOptions time - errored <- catch - (False <$ runWithBasicEffectsIO opts - (normalForm =<< nixEvalExprLoc mempty a')) - (\(_ :: NixException) -> pure True) - unless errored $ - assertFailure "Did not catch nix exception" +assertNixEvalThrows a = + do + time <- getCurrentTime + let + opts = defaultOptions time + Right a' = parseNixTextLoc a + errored <- + catch + (False <$ + runWithBasicEffectsIO + opts + (normalForm =<< nixEvalExprLoc mempty a') + ) + (\(_ :: NixException) -> pure True) + unless errored $ assertFailure "Did not catch nix exception" freeVarsEqual :: Text -> [VarName] -> Assertion -freeVarsEqual a xs = do - let Success a' = parseNixText a +freeVarsEqual a xs = + do + let + Right a' = parseNixText a xs' = S.fromList xs - free = freeVars a' - assertEqual "" xs' free + free' = freeVars a' + assertEqual "" xs' free' maskedFiles :: [FilePath] maskedFiles = diff --git a/tests/Main.hs b/tests/Main.hs index fd643a2a9..e13bf6abe 100644 --- a/tests/Main.hs +++ b/tests/Main.hs @@ -76,16 +76,19 @@ ensureNixpkgsCanParse = -- parser is fully executed. _ <- consider file (parseNixFileLoc file) $ Exc.evaluate . force pure () - v -> error $ "Unexpected parse from default.nix: " <> show v + v -> fail $ "Unexpected parse from default.nix: " <> show v where getExpr k m = let Just (Just r) = lookup k m in r getString k m = let Fix (NStr (DoubleQuoted [Plain str])) = getExpr k m in str - consider path action k = action >>= \case - Failure err -> errorWithoutStackTrace $ - "Parsing " <> path <> " failed: " <> show err - Success expr -> k expr + consider path action k = + do + x <- action + either + (\ err -> errorWithoutStackTrace $ "Parsing " <> path <> " failed: " <> show err) + k + x main :: IO () main = do diff --git a/tests/NixLanguageTests.hs b/tests/NixLanguageTests.hs index 952fcab74..6ca819238 100644 --- a/tests/NixLanguageTests.hs +++ b/tests/NixLanguageTests.hs @@ -101,29 +101,35 @@ genTests = do ["parse", "fail"] -> assertParseFail opts $ the files ["eval" , "okay"] -> assertEval opts files ["eval" , "fail"] -> assertEvalFail $ the files - _ -> error $ "Unexpected: " <> show kind + _ -> fail $ "Unexpected: " <> show kind assertParse :: Options -> FilePath -> Assertion -assertParse _opts file = parseNixFileLoc file >>= \case - Success _expr -> pure () -- pure $! runST $ void $ lint opts expr - Failure err -> - assertFailure $ "Failed to parse " <> file <> ":\n" <> show err +assertParse _opts file = + do + x <- parseNixFileLoc file + either + (\ err -> assertFailure $ "Failed to parse " <> file <> ":\n" <> show err) + (const $ pure ()) -- pure $! runST $ void $ lint opts expr + x assertParseFail :: Options -> FilePath -> Assertion assertParseFail opts file = do eres <- parseNixFileLoc file catch - (case eres of - Success expr -> do - _ <- pure $! runST $ void $ lint opts expr - assertFailure - $ "Unexpected success parsing `" - <> file - <> ":\nParsed value: " - <> show expr - Failure _ -> pure () + (either + (const $ pure ()) + (\ expr -> + do + _ <- pure $! runST $ void $ lint opts expr + assertFailure $ + "Unexpected success parsing `" + <> file + <> ":\nParsed value: " + <> show expr + ) + eres ) - $ \(_ :: SomeException) -> pure () + $ \(_ :: SomeException) -> pure () assertLangOk :: Options -> FilePath -> Assertion assertLangOk opts file = do @@ -167,7 +173,7 @@ assertEval _opts files = do <> ".flags: " <> show err Opts.Success opts' -> assertLangOk opts' name - Opts.CompletionInvoked _ -> error "unused" + Opts.CompletionInvoked _ -> fail "unused" _ -> assertFailure $ "Unknown test type " <> show files where name = diff --git a/tests/ParserTests.hs b/tests/ParserTests.hs index 692831cad..59d806339 100644 --- a/tests/ParserTests.hs +++ b/tests/ParserTests.hs @@ -325,10 +325,11 @@ case_operators = do assertParseFail "+ 3" assertParseFail "foo +" -case_comments = do - Success expected <- parseNixFile "data/let.nix" - assertParseFile "let-comments-multiline.nix" expected - assertParseFile "let-comments.nix" expected +case_comments = + do + Right expected <- parseNixFile "data/let.nix" + assertParseFile "let-comments-multiline.nix" expected + assertParseFile "let-comments.nix" expected case_select_or_precedence = assertParsePrint [text|let @@ -366,39 +367,53 @@ tests = $testGroupGenerator --------------------------------------------------------------------------------- assertParseText :: Text -> NExpr -> Assertion -assertParseText str expected = case parseNixText str of - Success actual -> - assertEqual ("When parsing " <> unpack str) - (stripPositionInfo expected) (stripPositionInfo actual) - Failure err -> - assertFailure $ "Unexpected error parsing `" <> unpack str <> "':\n" <> show err +assertParseText str expected = + either + (\ err -> + assertFailure $ "Unexpected fail parsing `" <> unpack str <> "':\n" <> show err + ) + (assertEqual + ("When parsing " <> unpack str) + (stripPositionInfo expected) + . stripPositionInfo + ) + (parseNixText str) assertParseFile :: FilePath -> NExpr -> Assertion -assertParseFile file expected = do +assertParseFile file expected = + do res <- parseNixFile $ "data/" <> file - case res of - Success actual -> assertEqual ("Parsing data file " <> file) - (stripPositionInfo expected) (stripPositionInfo actual) - Failure err -> - assertFailure $ "Unexpected error parsing data file `" - <> file <> "':\n" <> show err + either + (\ err -> + assertFailure $ "Unexpected fail parsing data file `" <> file <> "':\n" <> show err + ) + (assertEqual + ("Parsing data file " <> file) + (stripPositionInfo expected) + . stripPositionInfo + ) + res assertParseFail :: Text -> Assertion -assertParseFail str = case parseNixText str of - Failure _ -> pure () - Success r -> - assertFailure $ "Unexpected success parsing `" - <> unpack str <> ":\nParsed value: " <> show r +assertParseFail str = + either + (const $ pure ()) + (\ r -> + assertFailure $ "Unexpected success parsing `" <> unpack str <> ":\nParsed value: " <> show r + ) + (parseNixText str) -- assertRoundTrip :: Text -> Assertion -- assertRoundTrip src = assertParsePrint src src assertParsePrint :: Text -> Text -> Assertion assertParsePrint src expect = - let Success expr = parseNixTextLoc src - result = renderStrict - . layoutPretty (LayoutOptions $ AvailablePerLine 80 0.4) - . prettyNix - . stripAnnotation - $ expr + let + Right expr = parseNixTextLoc src + result = + renderStrict + . layoutPretty (LayoutOptions $ AvailablePerLine 80 0.4) + . prettyNix + . stripAnnotation $ + expr in assertEqual "" expect result diff --git a/tests/PrettyParseTests.hs b/tests/PrettyParseTests.hs index 5707802b4..08095841d 100644 --- a/tests/PrettyParseTests.hs +++ b/tests/PrettyParseTests.hs @@ -30,6 +30,9 @@ import Test.Tasty import Test.Tasty.Hedgehog import Text.Megaparsec ( Pos ) import qualified Text.Show.Pretty as PS +import Options.Applicative ( Applicative(liftA2) + , liftA3 + ) asciiString :: MonadGen m => m String asciiString = Gen.list (Range.linear 1 15) Gen.lower @@ -112,23 +115,23 @@ genExpr = Gen.sized $ \(Size n) -> Fix <$> if n < 2 , (1, Gen.resize (Size (n `div` 2)) genAssert) ] where - genConstant = NConstant <$> genAtom - genStr = NStr <$> genString - genSym = NSym <$> asciiText - genList = NList <$> fairList genExpr - genSet = NSet NNonRecursive <$> fairList genBinding - genRecSet = NSet NRecursive <$> fairList genBinding + genConstant = NConstant <$> genAtom + genStr = NStr <$> genString + genSym = NSym <$> asciiText + genList = NList <$> fairList genExpr + genSet = NSet NNonRecursive <$> fairList genBinding + genRecSet = NSet NRecursive <$> fairList genBinding genLiteralPath = NLiteralPath . ("./" <>) <$> asciiString - genEnvPath = NEnvPath <$> asciiString - genUnary = NUnary <$> Gen.enumBounded <*> genExpr - genBinary = NBinary <$> Gen.enumBounded <*> genExpr <*> genExpr - genSelect = NSelect <$> genExpr <*> genAttrPath <*> Gen.maybe genExpr - genHasAttr = NHasAttr <$> genExpr <*> genAttrPath - genAbs = NAbs <$> genParams <*> genExpr - genLet = NLet <$> fairList genBinding <*> genExpr - genIf = NIf <$> genExpr <*> genExpr <*> genExpr - genWith = NWith <$> genExpr <*> genExpr - genAssert = NAssert <$> genExpr <*> genExpr + genEnvPath = NEnvPath <$> asciiString + genUnary = liftA2 NUnary Gen.enumBounded genExpr + genBinary = liftA3 NBinary Gen.enumBounded genExpr genExpr + genSelect = liftA3 NSelect genExpr genAttrPath (Gen.maybe genExpr) + genHasAttr = liftA2 NHasAttr genExpr genAttrPath + genAbs = liftA2 NAbs genParams genExpr + genLet = liftA2 NLet (fairList genBinding) genExpr + genIf = liftA3 NIf genExpr genExpr genExpr + genWith = liftA2 NWith genExpr genExpr + genAssert = liftA2 NAssert genExpr genExpr -- | Useful when there are recursive positions at each element of the list as -- it divides the size by the length of the generated list. @@ -185,35 +188,38 @@ prop_prettyparse :: Monad m => NExpr -> PropertyT m () prop_prettyparse p = do let prog = show (prettyNix p) case parse (pack prog) of - Failure s -> do + Left s -> do footnote $ show $ vsep [fillSep ["Parse failed:", pretty (show s)], indent 2 (prettyNix p)] discard - Success v + Right v | equivUpToNormalization p v -> success - | otherwise -> do - let pp = normalise prog + | otherwise -> + do + let + pp = normalise prog pv = normalise (show (prettyNix v)) - footnote - $ show - $ vsep - $ [ "----------------------------------------" - , vsep ["Expr before:", indent 2 (pretty (PS.ppShow p))] - , "----------------------------------------" - , vsep ["Expr after:", indent 2 (pretty (PS.ppShow v))] - , "----------------------------------------" - , vsep ["Pretty before:", indent 2 (pretty prog)] - , "----------------------------------------" - , vsep ["Pretty after:", indent 2 (prettyNix v)] - , "----------------------------------------" - , vsep ["Normalised before:", indent 2 (pretty pp)] - , "----------------------------------------" - , vsep ["Normalised after:", indent 2 (pretty pv)] - , "========================================" - , vsep ["Normalised diff:", pretty (ppDiff (ldiff pp pv))] - , "========================================" - ] - assert (pp == pv) + + footnote $ + show $ + vsep + [ "----------------------------------------" + , vsep ["Expr before:", indent 2 (pretty (PS.ppShow p))] + , "----------------------------------------" + , vsep ["Expr after:", indent 2 (pretty (PS.ppShow v))] + , "----------------------------------------" + , vsep ["Pretty before:", indent 2 (pretty prog)] + , "----------------------------------------" + , vsep ["Pretty after:", indent 2 (prettyNix v)] + , "----------------------------------------" + , vsep ["Normalised before:", indent 2 (pretty pp)] + , "----------------------------------------" + , vsep ["Normalised after:", indent 2 (pretty pv)] + , "========================================" + , vsep ["Normalised diff:", pretty (ppDiff (ldiff pp pv))] + , "========================================" + ] + assert (pp == pv) where parse = parseNixText diff --git a/tests/ReduceExprTests.hs b/tests/ReduceExprTests.hs index c3490252f..6b15287ee 100644 --- a/tests/ReduceExprTests.hs +++ b/tests/ReduceExprTests.hs @@ -26,8 +26,10 @@ tests = testGroup ] assertSucc :: Result a -> IO a -assertSucc (Success a) = pure a -assertSucc (Failure d) = assertFailure $ show d +assertSucc = + either + (assertFailure . show) + pure cmpReduceResult :: Result NExprLoc -> NExpr -> Assertion cmpReduceResult r e = do diff --git a/tests/TestCommon.hs b/tests/TestCommon.hs index 658b1cd19..2edd0b21d 100644 --- a/tests/TestCommon.hs +++ b/tests/TestCommon.hs @@ -22,27 +22,34 @@ import System.Process import Test.Tasty.HUnit hnixEvalFile :: Options -> FilePath -> IO (StdValue (StandardT (StdIdT IO))) -hnixEvalFile opts file = do - parseResult <- parseNixFileLoc file - case parseResult of - Failure err -> error $ "Parsing failed for file `" <> file <> "`.\n" <> show err - Success expr -> do - setEnv "TEST_VAR" "foo" - runWithBasicEffects opts - $ catch (evaluateExpression (pure file) nixEvalExprLoc normalForm expr) - $ \case - NixException frames -> - errorWithoutStackTrace - . show - =<< renderFrames @(StdValue (StandardT (StdIdT IO))) - @(StdThunk (StandardT (StdIdT IO))) - frames +hnixEvalFile opts file = + do + parseResult <- parseNixFileLoc file + either + (\ err -> fail $ "Parsing failed for file `" <> file <> "`.\n" <> show err) + (\ expr -> + do + setEnv "TEST_VAR" "foo" + runWithBasicEffects opts $ + catch (evaluateExpression (pure file) nixEvalExprLoc normalForm expr) $ + \case + NixException frames -> + errorWithoutStackTrace . show + =<< renderFrames + @(StdValue (StandardT (StdIdT IO))) + @(StdThunk (StandardT (StdIdT IO))) + frames + ) + parseResult hnixEvalText :: Options -> Text -> IO (StdValue (StandardT (StdIdT IO))) -hnixEvalText opts src = case parseNixText src of - Failure err -> error $ "Parsing failed for expression `" <> unpack src <> "`.\n" <> show err - Success expr -> - runWithBasicEffects opts $ normalForm =<< nixEvalExpr mempty expr +hnixEvalText opts src = + either + (\ err -> fail $ "Parsing failed for expression `" <> unpack src <> "`.\n" <> show err) + (\ expr -> + runWithBasicEffects opts $ normalForm =<< nixEvalExpr mempty expr + ) + (parseNixText src) nixEvalString :: String -> IO String nixEvalString expr = do