aboutsummaryrefslogtreecommitdiff
path: root/tests/functional/lang
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-10-05 12:12:18 -0400
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-12-01 12:06:43 -0500
commit30dcc19d1f30fc203be460134c4578509cce704f (patch)
tree6cc32609b9984a2c4d5ecc0cac5cf30609e208b9 /tests/functional/lang
parent72425212657d795dc215b334b7c8c8cd36d06b72 (diff)
Put functional tests in `tests/functional`
I think it is bad for these reasons when `tests/` contains a mix of functional and integration tests - Concepts is harder to understand, the documentation makes a good unit vs functional vs integration distinction, but when the integration tests are just two subdirs within `tests/` this is not clear. - Source filtering in the `flake.nix` is more complex. We need to filter out some of the dirs from `tests/`, rather than simply pick the dirs we want and take all of them. This is a good sign the structure of what we are trying to do is not matching the structure of the files. With this change we have a clean: ```shell-session $ git show 'HEAD:tests' tree HEAD:tests functional/ installer/ nixos/ ``` (cherry picked from commit 68c81c737571794f7246db53fb4774e94fcf4b7e)
Diffstat (limited to 'tests/functional/lang')
-rw-r--r--tests/functional/lang/binary-databin0 -> 1024 bytes
-rw-r--r--tests/functional/lang/data1
-rw-r--r--tests/functional/lang/dir1/a.nix1
-rw-r--r--tests/functional/lang/dir2/a.nix1
-rw-r--r--tests/functional/lang/dir2/b.nix1
-rw-r--r--tests/functional/lang/dir3/a.nix1
-rw-r--r--tests/functional/lang/dir3/b.nix1
-rw-r--r--tests/functional/lang/dir3/c.nix1
-rw-r--r--tests/functional/lang/dir4/a.nix1
-rw-r--r--tests/functional/lang/dir4/c.nix1
-rw-r--r--tests/functional/lang/empty.exp0
-rw-r--r--tests/functional/lang/eval-fail-abort.err.exp10
-rw-r--r--tests/functional/lang/eval-fail-abort.nix1
-rw-r--r--tests/functional/lang/eval-fail-antiquoted-path.err.exp1
-rw-r--r--tests/functional/lang/eval-fail-assert.err.exp36
-rw-r--r--tests/functional/lang/eval-fail-assert.nix5
-rw-r--r--tests/functional/lang/eval-fail-bad-antiquote-1.err.exp10
-rw-r--r--tests/functional/lang/eval-fail-bad-antiquote-2.err.exp1
-rw-r--r--tests/functional/lang/eval-fail-bad-antiquote-3.err.exp10
-rw-r--r--tests/functional/lang/eval-fail-bad-string-interpolation-1.err.exp10
-rw-r--r--tests/functional/lang/eval-fail-bad-string-interpolation-1.nix1
-rw-r--r--tests/functional/lang/eval-fail-bad-string-interpolation-2.err.exp1
-rw-r--r--tests/functional/lang/eval-fail-bad-string-interpolation-2.nix1
-rw-r--r--tests/functional/lang/eval-fail-bad-string-interpolation-3.err.exp10
-rw-r--r--tests/functional/lang/eval-fail-bad-string-interpolation-3.nix1
-rw-r--r--tests/functional/lang/eval-fail-blackhole.err.exp18
-rw-r--r--tests/functional/lang/eval-fail-blackhole.nix5
-rw-r--r--tests/functional/lang/eval-fail-deepseq.err.exp26
-rw-r--r--tests/functional/lang/eval-fail-deepseq.nix1
-rw-r--r--tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp8
-rw-r--r--tests/functional/lang/eval-fail-dup-dynamic-attrs.nix4
-rw-r--r--tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp38
-rw-r--r--tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix5
-rw-r--r--tests/functional/lang/eval-fail-fromTOML-timestamps.err.exp12
-rw-r--r--tests/functional/lang/eval-fail-fromTOML-timestamps.nix130
-rw-r--r--tests/functional/lang/eval-fail-hashfile-missing.err.exp19
-rw-r--r--tests/functional/lang/eval-fail-hashfile-missing.nix5
-rw-r--r--tests/functional/lang/eval-fail-list.err.exp10
-rw-r--r--tests/functional/lang/eval-fail-list.nix1
-rw-r--r--tests/functional/lang/eval-fail-missing-arg.err.exp16
-rw-r--r--tests/functional/lang/eval-fail-missing-arg.nix1
-rw-r--r--tests/functional/lang/eval-fail-nonexist-path.err.exp1
-rw-r--r--tests/functional/lang/eval-fail-nonexist-path.nix4
-rw-r--r--tests/functional/lang/eval-fail-path-slash.err.exp8
-rw-r--r--tests/functional/lang/eval-fail-path-slash.nix6
-rw-r--r--tests/functional/lang/eval-fail-recursion.err.exp16
-rw-r--r--tests/functional/lang/eval-fail-recursion.nix1
-rw-r--r--tests/functional/lang/eval-fail-remove.err.exp19
-rw-r--r--tests/functional/lang/eval-fail-remove.nix5
-rw-r--r--tests/functional/lang/eval-fail-scope-5.err.exp36
-rw-r--r--tests/functional/lang/eval-fail-scope-5.nix10
-rw-r--r--tests/functional/lang/eval-fail-seq.err.exp18
-rw-r--r--tests/functional/lang/eval-fail-seq.nix1
-rw-r--r--tests/functional/lang/eval-fail-set-override.err.exp6
-rw-r--r--tests/functional/lang/eval-fail-set-override.nix1
-rw-r--r--tests/functional/lang/eval-fail-set.err.exp7
-rw-r--r--tests/functional/lang/eval-fail-set.nix1
-rw-r--r--tests/functional/lang/eval-fail-substring.err.exp12
-rw-r--r--tests/functional/lang/eval-fail-substring.nix1
-rw-r--r--tests/functional/lang/eval-fail-to-path.err.exp14
-rw-r--r--tests/functional/lang/eval-fail-to-path.nix1
-rw-r--r--tests/functional/lang/eval-fail-toJSON.err.exp57
-rw-r--r--tests/functional/lang/eval-fail-toJSON.nix10
-rw-r--r--tests/functional/lang/eval-fail-undeclared-arg.err.exp17
-rw-r--r--tests/functional/lang/eval-fail-undeclared-arg.nix1
-rw-r--r--tests/functional/lang/eval-okay-any-all.exp1
-rw-r--r--tests/functional/lang/eval-okay-any-all.nix11
-rw-r--r--tests/functional/lang/eval-okay-arithmetic.exp1
-rw-r--r--tests/functional/lang/eval-okay-arithmetic.nix59
-rw-r--r--tests/functional/lang/eval-okay-attrnames.exp1
-rw-r--r--tests/functional/lang/eval-okay-attrnames.nix11
-rw-r--r--tests/functional/lang/eval-okay-attrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-attrs.nix5
-rw-r--r--tests/functional/lang/eval-okay-attrs2.exp1
-rw-r--r--tests/functional/lang/eval-okay-attrs2.nix10
-rw-r--r--tests/functional/lang/eval-okay-attrs3.exp1
-rw-r--r--tests/functional/lang/eval-okay-attrs3.nix22
-rw-r--r--tests/functional/lang/eval-okay-attrs4.exp1
-rw-r--r--tests/functional/lang/eval-okay-attrs4.nix7
-rw-r--r--tests/functional/lang/eval-okay-attrs5.exp1
-rw-r--r--tests/functional/lang/eval-okay-attrs5.nix21
-rw-r--r--tests/functional/lang/eval-okay-attrs6.exp1
-rw-r--r--tests/functional/lang/eval-okay-attrs6.nix4
-rw-r--r--tests/functional/lang/eval-okay-autoargs.exp1
-rw-r--r--tests/functional/lang/eval-okay-autoargs.flags1
-rw-r--r--tests/functional/lang/eval-okay-autoargs.nix15
-rw-r--r--tests/functional/lang/eval-okay-backslash-newline-1.exp1
-rw-r--r--tests/functional/lang/eval-okay-backslash-newline-1.nix2
-rw-r--r--tests/functional/lang/eval-okay-backslash-newline-2.exp1
-rw-r--r--tests/functional/lang/eval-okay-backslash-newline-2.nix2
-rw-r--r--tests/functional/lang/eval-okay-builtins-add.exp1
-rw-r--r--tests/functional/lang/eval-okay-builtins-add.nix8
-rw-r--r--tests/functional/lang/eval-okay-builtins.exp1
-rw-r--r--tests/functional/lang/eval-okay-builtins.nix12
-rw-r--r--tests/functional/lang/eval-okay-callable-attrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-callable-attrs.nix1
-rw-r--r--tests/functional/lang/eval-okay-catattrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-catattrs.nix1
-rw-r--r--tests/functional/lang/eval-okay-closure.exp1
-rw-r--r--tests/functional/lang/eval-okay-closure.exp.xml343
-rw-r--r--tests/functional/lang/eval-okay-closure.nix13
-rw-r--r--tests/functional/lang/eval-okay-comments.exp1
-rw-r--r--tests/functional/lang/eval-okay-comments.nix59
-rw-r--r--tests/functional/lang/eval-okay-concat.exp1
-rw-r--r--tests/functional/lang/eval-okay-concat.nix1
-rw-r--r--tests/functional/lang/eval-okay-concatmap.exp1
-rw-r--r--tests/functional/lang/eval-okay-concatmap.nix5
-rw-r--r--tests/functional/lang/eval-okay-concatstringssep.exp1
-rw-r--r--tests/functional/lang/eval-okay-concatstringssep.nix8
-rw-r--r--tests/functional/lang/eval-okay-context-introspection.exp1
-rw-r--r--tests/functional/lang/eval-okay-context-introspection.nix41
-rw-r--r--tests/functional/lang/eval-okay-context.exp1
-rw-r--r--tests/functional/lang/eval-okay-context.nix6
-rw-r--r--tests/functional/lang/eval-okay-curpos.exp1
-rw-r--r--tests/functional/lang/eval-okay-curpos.nix5
-rw-r--r--tests/functional/lang/eval-okay-deepseq.exp1
-rw-r--r--tests/functional/lang/eval-okay-deepseq.nix1
-rw-r--r--tests/functional/lang/eval-okay-delayed-with-inherit.exp1
-rw-r--r--tests/functional/lang/eval-okay-delayed-with-inherit.nix24
-rw-r--r--tests/functional/lang/eval-okay-delayed-with.exp1
-rw-r--r--tests/functional/lang/eval-okay-delayed-with.nix29
-rw-r--r--tests/functional/lang/eval-okay-dynamic-attrs-2.exp1
-rw-r--r--tests/functional/lang/eval-okay-dynamic-attrs-2.nix1
-rw-r--r--tests/functional/lang/eval-okay-dynamic-attrs-bare.exp1
-rw-r--r--tests/functional/lang/eval-okay-dynamic-attrs-bare.nix17
-rw-r--r--tests/functional/lang/eval-okay-dynamic-attrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-dynamic-attrs.nix17
-rw-r--r--tests/functional/lang/eval-okay-elem.exp1
-rw-r--r--tests/functional/lang/eval-okay-elem.nix6
-rw-r--r--tests/functional/lang/eval-okay-empty-args.exp1
-rw-r--r--tests/functional/lang/eval-okay-empty-args.nix1
-rw-r--r--tests/functional/lang/eval-okay-eq-derivations.exp1
-rw-r--r--tests/functional/lang/eval-okay-eq-derivations.nix10
-rw-r--r--tests/functional/lang/eval-okay-eq.exp1
-rw-r--r--tests/functional/lang/eval-okay-eq.nix3
-rw-r--r--tests/functional/lang/eval-okay-filter.exp1
-rw-r--r--tests/functional/lang/eval-okay-filter.nix5
-rw-r--r--tests/functional/lang/eval-okay-flake-ref-to-string.exp1
-rw-r--r--tests/functional/lang/eval-okay-flake-ref-to-string.nix7
-rw-r--r--tests/functional/lang/eval-okay-flatten.exp1
-rw-r--r--tests/functional/lang/eval-okay-flatten.nix8
-rw-r--r--tests/functional/lang/eval-okay-float.exp1
-rw-r--r--tests/functional/lang/eval-okay-float.nix6
-rw-r--r--tests/functional/lang/eval-okay-floor-ceil.exp1
-rw-r--r--tests/functional/lang/eval-okay-floor-ceil.nix9
-rw-r--r--tests/functional/lang/eval-okay-foldlStrict-lazy-elements.exp1
-rw-r--r--tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix9
-rw-r--r--tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp1
-rw-r--r--tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix6
-rw-r--r--tests/functional/lang/eval-okay-foldlStrict.exp1
-rw-r--r--tests/functional/lang/eval-okay-foldlStrict.nix3
-rw-r--r--tests/functional/lang/eval-okay-fromTOML-timestamps.exp1
-rw-r--r--tests/functional/lang/eval-okay-fromTOML-timestamps.flags1
-rw-r--r--tests/functional/lang/eval-okay-fromTOML-timestamps.nix130
-rw-r--r--tests/functional/lang/eval-okay-fromTOML.exp1
-rw-r--r--tests/functional/lang/eval-okay-fromTOML.nix208
-rw-r--r--tests/functional/lang/eval-okay-fromjson-escapes.exp1
-rw-r--r--tests/functional/lang/eval-okay-fromjson-escapes.nix3
-rw-r--r--tests/functional/lang/eval-okay-fromjson.exp1
-rw-r--r--tests/functional/lang/eval-okay-fromjson.nix41
-rw-r--r--tests/functional/lang/eval-okay-functionargs.exp1
-rw-r--r--tests/functional/lang/eval-okay-functionargs.exp.xml15
-rw-r--r--tests/functional/lang/eval-okay-functionargs.nix80
-rw-r--r--tests/functional/lang/eval-okay-getattrpos-functionargs.exp1
-rw-r--r--tests/functional/lang/eval-okay-getattrpos-functionargs.nix4
-rw-r--r--tests/functional/lang/eval-okay-getattrpos-undefined.exp1
-rw-r--r--tests/functional/lang/eval-okay-getattrpos-undefined.nix1
-rw-r--r--tests/functional/lang/eval-okay-getattrpos.exp1
-rw-r--r--tests/functional/lang/eval-okay-getattrpos.nix6
-rw-r--r--tests/functional/lang/eval-okay-getenv.exp1
-rw-r--r--tests/functional/lang/eval-okay-getenv.nix1
-rw-r--r--tests/functional/lang/eval-okay-groupBy.exp1
-rw-r--r--tests/functional/lang/eval-okay-groupBy.nix5
-rw-r--r--tests/functional/lang/eval-okay-hash.exp0
-rw-r--r--tests/functional/lang/eval-okay-hashfile.exp1
-rw-r--r--tests/functional/lang/eval-okay-hashfile.nix4
-rw-r--r--tests/functional/lang/eval-okay-hashstring.exp1
-rw-r--r--tests/functional/lang/eval-okay-hashstring.nix4
-rw-r--r--tests/functional/lang/eval-okay-if.exp1
-rw-r--r--tests/functional/lang/eval-okay-if.nix1
-rw-r--r--tests/functional/lang/eval-okay-import.exp1
-rw-r--r--tests/functional/lang/eval-okay-import.nix11
-rw-r--r--tests/functional/lang/eval-okay-ind-string.exp1
-rw-r--r--tests/functional/lang/eval-okay-ind-string.nix128
-rw-r--r--tests/functional/lang/eval-okay-intersectAttrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-intersectAttrs.nix50
-rw-r--r--tests/functional/lang/eval-okay-let.exp1
-rw-r--r--tests/functional/lang/eval-okay-let.nix5
-rw-r--r--tests/functional/lang/eval-okay-list.exp1
-rw-r--r--tests/functional/lang/eval-okay-list.nix7
-rw-r--r--tests/functional/lang/eval-okay-listtoattrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-listtoattrs.nix11
-rw-r--r--tests/functional/lang/eval-okay-logic.exp1
-rw-r--r--tests/functional/lang/eval-okay-logic.nix1
-rw-r--r--tests/functional/lang/eval-okay-map.exp1
-rw-r--r--tests/functional/lang/eval-okay-map.nix3
-rw-r--r--tests/functional/lang/eval-okay-mapattrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-mapattrs.nix3
-rw-r--r--tests/functional/lang/eval-okay-merge-dynamic-attrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-merge-dynamic-attrs.nix13
-rw-r--r--tests/functional/lang/eval-okay-nested-with.exp1
-rw-r--r--tests/functional/lang/eval-okay-nested-with.nix3
-rw-r--r--tests/functional/lang/eval-okay-new-let.exp1
-rw-r--r--tests/functional/lang/eval-okay-new-let.nix14
-rw-r--r--tests/functional/lang/eval-okay-null-dynamic-attrs.exp1
-rw-r--r--tests/functional/lang/eval-okay-null-dynamic-attrs.nix1
-rw-r--r--tests/functional/lang/eval-okay-overrides.exp1
-rw-r--r--tests/functional/lang/eval-okay-overrides.nix9
-rw-r--r--tests/functional/lang/eval-okay-parse-flake-ref.exp1
-rw-r--r--tests/functional/lang/eval-okay-parse-flake-ref.nix1
-rw-r--r--tests/functional/lang/eval-okay-partition.exp1
-rw-r--r--tests/functional/lang/eval-okay-partition.nix5
-rw-r--r--tests/functional/lang/eval-okay-path-string-interpolation.exp1
-rw-r--r--tests/functional/lang/eval-okay-path-string-interpolation.nix12
-rw-r--r--tests/functional/lang/eval-okay-path.exp1
-rw-r--r--tests/functional/lang/eval-okay-path.nix7
-rw-r--r--tests/functional/lang/eval-okay-pathexists.exp1
-rw-r--r--tests/functional/lang/eval-okay-pathexists.nix29
-rw-r--r--tests/functional/lang/eval-okay-patterns.exp1
-rw-r--r--tests/functional/lang/eval-okay-patterns.nix16
-rw-r--r--tests/functional/lang/eval-okay-print.err.exp1
-rw-r--r--tests/functional/lang/eval-okay-print.exp1
-rw-r--r--tests/functional/lang/eval-okay-print.nix1
-rw-r--r--tests/functional/lang/eval-okay-readDir.exp1
-rw-r--r--tests/functional/lang/eval-okay-readDir.nix1
-rw-r--r--tests/functional/lang/eval-okay-readFileType.exp1
-rw-r--r--tests/functional/lang/eval-okay-readFileType.nix6
-rw-r--r--tests/functional/lang/eval-okay-readfile.exp1
-rw-r--r--tests/functional/lang/eval-okay-readfile.nix1
-rw-r--r--tests/functional/lang/eval-okay-redefine-builtin.exp1
-rw-r--r--tests/functional/lang/eval-okay-redefine-builtin.nix3
-rw-r--r--tests/functional/lang/eval-okay-regex-match.exp1
-rw-r--r--tests/functional/lang/eval-okay-regex-match.nix29
-rw-r--r--tests/functional/lang/eval-okay-regex-split.exp1
-rw-r--r--tests/functional/lang/eval-okay-regex-split.nix48
-rw-r--r--tests/functional/lang/eval-okay-regression-20220122.exp1
-rw-r--r--tests/functional/lang/eval-okay-regression-20220122.nix1
-rw-r--r--tests/functional/lang/eval-okay-regression-20220125.exp1
-rw-r--r--tests/functional/lang/eval-okay-regression-20220125.nix2
-rw-r--r--tests/functional/lang/eval-okay-remove.exp1
-rw-r--r--tests/functional/lang/eval-okay-remove.nix5
-rw-r--r--tests/functional/lang/eval-okay-replacestrings.exp1
-rw-r--r--tests/functional/lang/eval-okay-replacestrings.nix12
-rw-r--r--tests/functional/lang/eval-okay-scope-1.exp1
-rw-r--r--tests/functional/lang/eval-okay-scope-1.nix6
-rw-r--r--tests/functional/lang/eval-okay-scope-2.exp1
-rw-r--r--tests/functional/lang/eval-okay-scope-2.nix6
-rw-r--r--tests/functional/lang/eval-okay-scope-3.exp1
-rw-r--r--tests/functional/lang/eval-okay-scope-3.nix6
-rw-r--r--tests/functional/lang/eval-okay-scope-4.exp1
-rw-r--r--tests/functional/lang/eval-okay-scope-4.nix10
-rw-r--r--tests/functional/lang/eval-okay-scope-6.exp1
-rw-r--r--tests/functional/lang/eval-okay-scope-6.nix7
-rw-r--r--tests/functional/lang/eval-okay-scope-7.exp1
-rw-r--r--tests/functional/lang/eval-okay-scope-7.nix6
-rw-r--r--tests/functional/lang/eval-okay-search-path.exp1
-rw-r--r--tests/functional/lang/eval-okay-search-path.flags1
-rw-r--r--tests/functional/lang/eval-okay-search-path.nix10
-rw-r--r--tests/functional/lang/eval-okay-seq.exp1
-rw-r--r--tests/functional/lang/eval-okay-seq.nix1
-rw-r--r--tests/functional/lang/eval-okay-sort.exp1
-rw-r--r--tests/functional/lang/eval-okay-sort.nix20
-rw-r--r--tests/functional/lang/eval-okay-splitversion.exp1
-rw-r--r--tests/functional/lang/eval-okay-splitversion.nix1
-rw-r--r--tests/functional/lang/eval-okay-string.exp1
-rw-r--r--tests/functional/lang/eval-okay-string.nix12
-rw-r--r--tests/functional/lang/eval-okay-strings-as-attrs-names.exp1
-rw-r--r--tests/functional/lang/eval-okay-strings-as-attrs-names.nix20
-rw-r--r--tests/functional/lang/eval-okay-substring.exp1
-rw-r--r--tests/functional/lang/eval-okay-substring.nix21
-rw-r--r--tests/functional/lang/eval-okay-tail-call-1.exp-disabled1
-rw-r--r--tests/functional/lang/eval-okay-tail-call-1.nix3
-rw-r--r--tests/functional/lang/eval-okay-tojson.exp1
-rw-r--r--tests/functional/lang/eval-okay-tojson.nix13
-rw-r--r--tests/functional/lang/eval-okay-toxml.exp1
-rw-r--r--tests/functional/lang/eval-okay-toxml.nix3
-rw-r--r--tests/functional/lang/eval-okay-toxml2.exp1
-rw-r--r--tests/functional/lang/eval-okay-toxml2.nix1
-rw-r--r--tests/functional/lang/eval-okay-tryeval.exp1
-rw-r--r--tests/functional/lang/eval-okay-tryeval.nix5
-rw-r--r--tests/functional/lang/eval-okay-types.exp1
-rw-r--r--tests/functional/lang/eval-okay-types.nix37
-rw-r--r--tests/functional/lang/eval-okay-versions.exp1
-rw-r--r--tests/functional/lang/eval-okay-versions.nix43
-rw-r--r--tests/functional/lang/eval-okay-with.exp1
-rw-r--r--tests/functional/lang/eval-okay-with.nix19
-rw-r--r--tests/functional/lang/eval-okay-xml.exp.xml52
-rw-r--r--tests/functional/lang/eval-okay-xml.nix21
-rw-r--r--tests/functional/lang/eval-okay-zipAttrsWith.exp1
-rw-r--r--tests/functional/lang/eval-okay-zipAttrsWith.nix9
-rw-r--r--tests/functional/lang/framework.sh33
-rw-r--r--tests/functional/lang/imported.nix3
-rw-r--r--tests/functional/lang/imported2.nix1
-rw-r--r--tests/functional/lang/lib.nix61
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-1.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-1.nix4
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-2.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-2.nix13
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-3.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-3.nix13
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-4.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-4.nix4
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-6.err.exp1
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-7.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-dup-attrs-7.nix9
-rw-r--r--tests/functional/lang/parse-fail-dup-formals.err.exp6
-rw-r--r--tests/functional/lang/parse-fail-dup-formals.nix1
-rw-r--r--tests/functional/lang/parse-fail-eof-in-string.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-eof-in-string.nix3
-rw-r--r--tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp8
-rw-r--r--tests/functional/lang/parse-fail-mixed-nested-attrs1.nix4
-rw-r--r--tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp8
-rw-r--r--tests/functional/lang/parse-fail-mixed-nested-attrs2.nix4
-rw-r--r--tests/functional/lang/parse-fail-patterns-1.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-patterns-1.nix1
-rw-r--r--tests/functional/lang/parse-fail-regression-20060610.err.exp8
-rw-r--r--tests/functional/lang/parse-fail-regression-20060610.nix11
-rw-r--r--tests/functional/lang/parse-fail-undef-var-2.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-undef-var-2.nix7
-rw-r--r--tests/functional/lang/parse-fail-undef-var.err.exp7
-rw-r--r--tests/functional/lang/parse-fail-undef-var.nix1
-rw-r--r--tests/functional/lang/parse-fail-utf8.err.exp6
-rw-r--r--tests/functional/lang/parse-fail-utf8.nix1
-rw-r--r--tests/functional/lang/parse-okay-1.exp1
-rw-r--r--tests/functional/lang/parse-okay-1.nix1
-rw-r--r--tests/functional/lang/parse-okay-crlf.exp1
-rw-r--r--tests/functional/lang/parse-okay-crlf.nix17
-rw-r--r--tests/functional/lang/parse-okay-dup-attrs-5.exp1
-rw-r--r--tests/functional/lang/parse-okay-dup-attrs-5.nix4
-rw-r--r--tests/functional/lang/parse-okay-dup-attrs-6.exp1
-rw-r--r--tests/functional/lang/parse-okay-dup-attrs-6.nix4
-rw-r--r--tests/functional/lang/parse-okay-mixed-nested-attrs-1.exp1
-rw-r--r--tests/functional/lang/parse-okay-mixed-nested-attrs-1.nix4
-rw-r--r--tests/functional/lang/parse-okay-mixed-nested-attrs-2.exp1
-rw-r--r--tests/functional/lang/parse-okay-mixed-nested-attrs-2.nix4
-rw-r--r--tests/functional/lang/parse-okay-mixed-nested-attrs-3.exp1
-rw-r--r--tests/functional/lang/parse-okay-mixed-nested-attrs-3.nix7
-rw-r--r--tests/functional/lang/parse-okay-regression-20041027.exp1
-rw-r--r--tests/functional/lang/parse-okay-regression-20041027.nix11
-rw-r--r--tests/functional/lang/parse-okay-regression-751.exp1
-rw-r--r--tests/functional/lang/parse-okay-regression-751.nix2
-rw-r--r--tests/functional/lang/parse-okay-subversion.exp1
-rw-r--r--tests/functional/lang/parse-okay-subversion.nix43
-rw-r--r--tests/functional/lang/parse-okay-url.exp1
-rw-r--r--tests/functional/lang/parse-okay-url.nix8
-rw-r--r--tests/functional/lang/readDir/bar0
-rw-r--r--tests/functional/lang/readDir/foo/git-hates-directories0
l---------tests/functional/lang/readDir/ldir1
l---------tests/functional/lang/readDir/linked1
349 files changed, 3270 insertions, 0 deletions
diff --git a/tests/functional/lang/binary-data b/tests/functional/lang/binary-data
new file mode 100644
index 000000000..06d740502
--- /dev/null
+++ b/tests/functional/lang/binary-data
Binary files differ
diff --git a/tests/functional/lang/data b/tests/functional/lang/data
new file mode 100644
index 000000000..257cc5642
--- /dev/null
+++ b/tests/functional/lang/data
@@ -0,0 +1 @@
+foo
diff --git a/tests/functional/lang/dir1/a.nix b/tests/functional/lang/dir1/a.nix
new file mode 100644
index 000000000..231f150c5
--- /dev/null
+++ b/tests/functional/lang/dir1/a.nix
@@ -0,0 +1 @@
+"a"
diff --git a/tests/functional/lang/dir2/a.nix b/tests/functional/lang/dir2/a.nix
new file mode 100644
index 000000000..170df520a
--- /dev/null
+++ b/tests/functional/lang/dir2/a.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tests/functional/lang/dir2/b.nix b/tests/functional/lang/dir2/b.nix
new file mode 100644
index 000000000..19010cc35
--- /dev/null
+++ b/tests/functional/lang/dir2/b.nix
@@ -0,0 +1 @@
+"b"
diff --git a/tests/functional/lang/dir3/a.nix b/tests/functional/lang/dir3/a.nix
new file mode 100644
index 000000000..170df520a
--- /dev/null
+++ b/tests/functional/lang/dir3/a.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tests/functional/lang/dir3/b.nix b/tests/functional/lang/dir3/b.nix
new file mode 100644
index 000000000..170df520a
--- /dev/null
+++ b/tests/functional/lang/dir3/b.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tests/functional/lang/dir3/c.nix b/tests/functional/lang/dir3/c.nix
new file mode 100644
index 000000000..cdf158597
--- /dev/null
+++ b/tests/functional/lang/dir3/c.nix
@@ -0,0 +1 @@
+"c"
diff --git a/tests/functional/lang/dir4/a.nix b/tests/functional/lang/dir4/a.nix
new file mode 100644
index 000000000..170df520a
--- /dev/null
+++ b/tests/functional/lang/dir4/a.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tests/functional/lang/dir4/c.nix b/tests/functional/lang/dir4/c.nix
new file mode 100644
index 000000000..170df520a
--- /dev/null
+++ b/tests/functional/lang/dir4/c.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tests/functional/lang/empty.exp b/tests/functional/lang/empty.exp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/functional/lang/empty.exp
diff --git a/tests/functional/lang/eval-fail-abort.err.exp b/tests/functional/lang/eval-fail-abort.err.exp
new file mode 100644
index 000000000..345232d3f
--- /dev/null
+++ b/tests/functional/lang/eval-fail-abort.err.exp
@@ -0,0 +1,10 @@
+error:
+ … while calling the 'abort' builtin
+
+ at /pwd/lang/eval-fail-abort.nix:1:14:
+
+ 1| if true then abort "this should fail" else 1
+ | ^
+ 2|
+
+ error: evaluation aborted with the following error message: 'this should fail'
diff --git a/tests/functional/lang/eval-fail-abort.nix b/tests/functional/lang/eval-fail-abort.nix
new file mode 100644
index 000000000..75c51bceb
--- /dev/null
+++ b/tests/functional/lang/eval-fail-abort.nix
@@ -0,0 +1 @@
+if true then abort "this should fail" else 1
diff --git a/tests/functional/lang/eval-fail-antiquoted-path.err.exp b/tests/functional/lang/eval-fail-antiquoted-path.err.exp
new file mode 100644
index 000000000..425deba42
--- /dev/null
+++ b/tests/functional/lang/eval-fail-antiquoted-path.err.exp
@@ -0,0 +1 @@
+error: getting attributes of path ‘PWD/lang/fnord’: No such file or directory
diff --git a/tests/functional/lang/eval-fail-assert.err.exp b/tests/functional/lang/eval-fail-assert.err.exp
new file mode 100644
index 000000000..aeecd8167
--- /dev/null
+++ b/tests/functional/lang/eval-fail-assert.err.exp
@@ -0,0 +1,36 @@
+error:
+ … while evaluating the attribute 'body'
+
+ at /pwd/lang/eval-fail-assert.nix:4:3:
+
+ 3|
+ 4| body = x "x";
+ | ^
+ 5| }
+
+ … from call site
+
+ at /pwd/lang/eval-fail-assert.nix:4:10:
+
+ 3|
+ 4| body = x "x";
+ | ^
+ 5| }
+
+ … while calling 'x'
+
+ at /pwd/lang/eval-fail-assert.nix:2:7:
+
+ 1| let {
+ 2| x = arg: assert arg == "y"; 123;
+ | ^
+ 3|
+
+ error: assertion '(arg == "y")' failed
+
+ at /pwd/lang/eval-fail-assert.nix:2:12:
+
+ 1| let {
+ 2| x = arg: assert arg == "y"; 123;
+ | ^
+ 3|
diff --git a/tests/functional/lang/eval-fail-assert.nix b/tests/functional/lang/eval-fail-assert.nix
new file mode 100644
index 000000000..3b7a1e8bf
--- /dev/null
+++ b/tests/functional/lang/eval-fail-assert.nix
@@ -0,0 +1,5 @@
+let {
+ x = arg: assert arg == "y"; 123;
+
+ body = x "x";
+} \ No newline at end of file
diff --git a/tests/functional/lang/eval-fail-bad-antiquote-1.err.exp b/tests/functional/lang/eval-fail-bad-antiquote-1.err.exp
new file mode 100644
index 000000000..cf94f53bc
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-antiquote-1.err.exp
@@ -0,0 +1,10 @@
+error:
+ … while evaluating a path segment
+
+ at /pwd/lang/eval-fail-bad-antiquote-1.nix:1:2:
+
+ 1| "${x: x}"
+ | ^
+ 2|
+
+ error: cannot coerce a function to a string
diff --git a/tests/functional/lang/eval-fail-bad-antiquote-2.err.exp b/tests/functional/lang/eval-fail-bad-antiquote-2.err.exp
new file mode 100644
index 000000000..c8fe39d12
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-antiquote-2.err.exp
@@ -0,0 +1 @@
+error: operation 'addToStoreFromDump' is not supported by store 'dummy'
diff --git a/tests/functional/lang/eval-fail-bad-antiquote-3.err.exp b/tests/functional/lang/eval-fail-bad-antiquote-3.err.exp
new file mode 100644
index 000000000..fbefbc826
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-antiquote-3.err.exp
@@ -0,0 +1,10 @@
+error:
+ … while evaluating a path segment
+
+ at /pwd/lang/eval-fail-bad-antiquote-3.nix:1:3:
+
+ 1| ''${x: x}''
+ | ^
+ 2|
+
+ error: cannot coerce a function to a string
diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-1.err.exp b/tests/functional/lang/eval-fail-bad-string-interpolation-1.err.exp
new file mode 100644
index 000000000..eb73e9a52
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-string-interpolation-1.err.exp
@@ -0,0 +1,10 @@
+error:
+ … while evaluating a path segment
+
+ at /pwd/lang/eval-fail-bad-string-interpolation-1.nix:1:2:
+
+ 1| "${x: x}"
+ | ^
+ 2|
+
+ error: cannot coerce a function to a string
diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-1.nix b/tests/functional/lang/eval-fail-bad-string-interpolation-1.nix
new file mode 100644
index 000000000..ffe9c983c
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-string-interpolation-1.nix
@@ -0,0 +1 @@
+"${x: x}"
diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-2.err.exp b/tests/functional/lang/eval-fail-bad-string-interpolation-2.err.exp
new file mode 100644
index 000000000..c8fe39d12
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-string-interpolation-2.err.exp
@@ -0,0 +1 @@
+error: operation 'addToStoreFromDump' is not supported by store 'dummy'
diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-2.nix b/tests/functional/lang/eval-fail-bad-string-interpolation-2.nix
new file mode 100644
index 000000000..3745235ce
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-string-interpolation-2.nix
@@ -0,0 +1 @@
+"${./fnord}"
diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-3.err.exp b/tests/functional/lang/eval-fail-bad-string-interpolation-3.err.exp
new file mode 100644
index 000000000..ac14f329b
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-string-interpolation-3.err.exp
@@ -0,0 +1,10 @@
+error:
+ … while evaluating a path segment
+
+ at /pwd/lang/eval-fail-bad-string-interpolation-3.nix:1:3:
+
+ 1| ''${x: x}''
+ | ^
+ 2|
+
+ error: cannot coerce a function to a string
diff --git a/tests/functional/lang/eval-fail-bad-string-interpolation-3.nix b/tests/functional/lang/eval-fail-bad-string-interpolation-3.nix
new file mode 100644
index 000000000..65b9d4f50
--- /dev/null
+++ b/tests/functional/lang/eval-fail-bad-string-interpolation-3.nix
@@ -0,0 +1 @@
+''${x: x}''
diff --git a/tests/functional/lang/eval-fail-blackhole.err.exp b/tests/functional/lang/eval-fail-blackhole.err.exp
new file mode 100644
index 000000000..f0618d8ac
--- /dev/null
+++ b/tests/functional/lang/eval-fail-blackhole.err.exp
@@ -0,0 +1,18 @@
+error:
+ … while evaluating the attribute 'body'
+
+ at /pwd/lang/eval-fail-blackhole.nix:2:3:
+
+ 1| let {
+ 2| body = x;
+ | ^
+ 3| x = y;
+
+ error: infinite recursion encountered
+
+ at /pwd/lang/eval-fail-blackhole.nix:3:7:
+
+ 2| body = x;
+ 3| x = y;
+ | ^
+ 4| y = x;
diff --git a/tests/functional/lang/eval-fail-blackhole.nix b/tests/functional/lang/eval-fail-blackhole.nix
new file mode 100644
index 000000000..81133b511
--- /dev/null
+++ b/tests/functional/lang/eval-fail-blackhole.nix
@@ -0,0 +1,5 @@
+let {
+ body = x;
+ x = y;
+ y = x;
+}
diff --git a/tests/functional/lang/eval-fail-deepseq.err.exp b/tests/functional/lang/eval-fail-deepseq.err.exp
new file mode 100644
index 000000000..5e204ba73
--- /dev/null
+++ b/tests/functional/lang/eval-fail-deepseq.err.exp
@@ -0,0 +1,26 @@
+error:
+ … while calling the 'deepSeq' builtin
+
+ at /pwd/lang/eval-fail-deepseq.nix:1:1:
+
+ 1| builtins.deepSeq { x = abort "foo"; } 456
+ | ^
+ 2|
+
+ … while evaluating the attribute 'x'
+
+ at /pwd/lang/eval-fail-deepseq.nix:1:20:
+
+ 1| builtins.deepSeq { x = abort "foo"; } 456
+ | ^
+ 2|
+
+ … while calling the 'abort' builtin
+
+ at /pwd/lang/eval-fail-deepseq.nix:1:24:
+
+ 1| builtins.deepSeq { x = abort "foo"; } 456
+ | ^
+ 2|
+
+ error: evaluation aborted with the following error message: 'foo'
diff --git a/tests/functional/lang/eval-fail-deepseq.nix b/tests/functional/lang/eval-fail-deepseq.nix
new file mode 100644
index 000000000..9baa49b06
--- /dev/null
+++ b/tests/functional/lang/eval-fail-deepseq.nix
@@ -0,0 +1 @@
+builtins.deepSeq { x = abort "foo"; } 456
diff --git a/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp b/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp
new file mode 100644
index 000000000..e01f8e6d0
--- /dev/null
+++ b/tests/functional/lang/eval-fail-dup-dynamic-attrs.err.exp
@@ -0,0 +1,8 @@
+error: dynamic attribute 'b' already defined at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:2:11
+
+ at /pwd/lang/eval-fail-dup-dynamic-attrs.nix:3:11:
+
+ 2| set = { "${"" + "b"}" = 1; };
+ 3| set = { "${"b" + ""}" = 2; };
+ | ^
+ 4| }
diff --git a/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix b/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix
new file mode 100644
index 000000000..7ea17f6c8
--- /dev/null
+++ b/tests/functional/lang/eval-fail-dup-dynamic-attrs.nix
@@ -0,0 +1,4 @@
+{
+ set = { "${"" + "b"}" = 1; };
+ set = { "${"b" + ""}" = 2; };
+}
diff --git a/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp
new file mode 100644
index 000000000..0069285fb
--- /dev/null
+++ b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.err.exp
@@ -0,0 +1,38 @@
+error:
+ … while calling the 'foldl'' builtin
+
+ at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:2:1:
+
+ 1| # Tests that the result of applying op is forced even if the value is never used
+ 2| builtins.foldl'
+ | ^
+ 3| (_: f: f null)
+
+ … while calling anonymous lambda
+
+ at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:7:
+
+ 2| builtins.foldl'
+ 3| (_: f: f null)
+ | ^
+ 4| null
+
+ … from call site
+
+ at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:3:10:
+
+ 2| builtins.foldl'
+ 3| (_: f: f null)
+ | ^
+ 4| null
+
+ … while calling anonymous lambda
+
+ at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:5:6:
+
+ 4| null
+ 5| [ (_: throw "Not the final value, but is still forced!") (_: 23) ]
+ | ^
+ 6|
+
+ error: Not the final value, but is still forced!
diff --git a/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix
new file mode 100644
index 000000000..1620cc76e
--- /dev/null
+++ b/tests/functional/lang/eval-fail-foldlStrict-strict-op-application.nix
@@ -0,0 +1,5 @@
+# Tests that the result of applying op is forced even if the value is never used
+builtins.foldl'
+ (_: f: f null)
+ null
+ [ (_: throw "Not the final value, but is still forced!") (_: 23) ]
diff --git a/tests/functional/lang/eval-fail-fromTOML-timestamps.err.exp b/tests/functional/lang/eval-fail-fromTOML-timestamps.err.exp
new file mode 100644
index 000000000..f6bd19f5a
--- /dev/null
+++ b/tests/functional/lang/eval-fail-fromTOML-timestamps.err.exp
@@ -0,0 +1,12 @@
+error:
+ … while calling the 'fromTOML' builtin
+
+ at /pwd/lang/eval-fail-fromTOML-timestamps.nix:1:1:
+
+ 1| builtins.fromTOML ''
+ | ^
+ 2| key = "value"
+
+ error: while parsing a TOML string: Dates and times are not supported
+
+ at «none»:0: (source not available)
diff --git a/tests/functional/lang/eval-fail-fromTOML-timestamps.nix b/tests/functional/lang/eval-fail-fromTOML-timestamps.nix
new file mode 100644
index 000000000..74cff9470
--- /dev/null
+++ b/tests/functional/lang/eval-fail-fromTOML-timestamps.nix
@@ -0,0 +1,130 @@
+builtins.fromTOML ''
+ key = "value"
+ bare_key = "value"
+ bare-key = "value"
+ 1234 = "value"
+
+ "127.0.0.1" = "value"
+ "character encoding" = "value"
+ "ʎǝʞ" = "value"
+ 'key2' = "value"
+ 'quoted "value"' = "value"
+
+ name = "Orange"
+
+ physical.color = "orange"
+ physical.shape = "round"
+ site."google.com" = true
+
+ # This is legal according to the spec, but cpptoml doesn't handle it.
+ #a.b.c = 1
+ #a.d = 2
+
+ str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
+
+ int1 = +99
+ int2 = 42
+ int3 = 0
+ int4 = -17
+ int5 = 1_000
+ int6 = 5_349_221
+ int7 = 1_2_3_4_5
+
+ hex1 = 0xDEADBEEF
+ hex2 = 0xdeadbeef
+ hex3 = 0xdead_beef
+
+ oct1 = 0o01234567
+ oct2 = 0o755
+
+ bin1 = 0b11010110
+
+ flt1 = +1.0
+ flt2 = 3.1415
+ flt3 = -0.01
+ flt4 = 5e+22
+ flt5 = 1e6
+ flt6 = -2E-2
+ flt7 = 6.626e-34
+ flt8 = 9_224_617.445_991_228_313
+
+ bool1 = true
+ bool2 = false
+
+ odt1 = 1979-05-27T07:32:00Z
+ odt2 = 1979-05-27T00:32:00-07:00
+ odt3 = 1979-05-27T00:32:00.999999-07:00
+ odt4 = 1979-05-27 07:32:00Z
+ ldt1 = 1979-05-27T07:32:00
+ ldt2 = 1979-05-27T00:32:00.999999
+ ld1 = 1979-05-27
+ lt1 = 07:32:00
+ lt2 = 00:32:00.999999
+
+ arr1 = [ 1, 2, 3 ]
+ arr2 = [ "red", "yellow", "green" ]
+ arr3 = [ [ 1, 2 ], [3, 4, 5] ]
+ arr4 = [ "all", 'strings', """are the same""", ''''type'''']
+ arr5 = [ [ 1, 2 ], ["a", "b", "c"] ]
+
+ arr7 = [
+ 1, 2, 3
+ ]
+
+ arr8 = [
+ 1,
+ 2, # this is ok
+ ]
+
+ [table-1]
+ key1 = "some string"
+ key2 = 123
+
+
+ [table-2]
+ key1 = "another string"
+ key2 = 456
+
+ [dog."tater.man"]
+ type.name = "pug"
+
+ [a.b.c]
+ [ d.e.f ]
+ [ g . h . i ]
+ [ j . "ʞ" . 'l' ]
+ [x.y.z.w]
+
+ name = { first = "Tom", last = "Preston-Werner" }
+ point = { x = 1, y = 2 }
+ animal = { type.name = "pug" }
+
+ [[products]]
+ name = "Hammer"
+ sku = 738594937
+
+ [[products]]
+
+ [[products]]
+ name = "Nail"
+ sku = 284758393
+ color = "gray"
+
+ [[fruit]]
+ name = "apple"
+
+ [fruit.physical]
+ color = "red"
+ shape = "round"
+
+ [[fruit.variety]]
+ name = "red delicious"
+
+ [[fruit.variety]]
+ name = "granny smith"
+
+ [[fruit]]
+ name = "banana"
+
+ [[fruit.variety]]
+ name = "plantain"
+''
diff --git a/tests/functional/lang/eval-fail-hashfile-missing.err.exp b/tests/functional/lang/eval-fail-hashfile-missing.err.exp
new file mode 100644
index 000000000..8e77dec1e
--- /dev/null
+++ b/tests/functional/lang/eval-fail-hashfile-missing.err.exp
@@ -0,0 +1,19 @@
+error:
+ … while calling the 'toString' builtin
+
+ at /pwd/lang/eval-fail-hashfile-missing.nix:4:3:
+
+ 3| in
+ 4| toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"]))
+ | ^
+ 5|
+
+ … while evaluating the first argument passed to builtins.toString
+
+ at «none»:0: (source not available)
+
+ … while calling the 'hashFile' builtin
+
+ at «none»:0: (source not available)
+
+ error: opening file '/pwd/lang/this-file-is-definitely-not-there-7392097': No such file or directory
diff --git a/tests/functional/lang/eval-fail-hashfile-missing.nix b/tests/functional/lang/eval-fail-hashfile-missing.nix
new file mode 100644
index 000000000..ce098b823
--- /dev/null
+++ b/tests/functional/lang/eval-fail-hashfile-missing.nix
@@ -0,0 +1,5 @@
+let
+ paths = [ ./this-file-is-definitely-not-there-7392097 "/and/neither/is/this/37293620" ];
+in
+ toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"]))
+
diff --git a/tests/functional/lang/eval-fail-list.err.exp b/tests/functional/lang/eval-fail-list.err.exp
new file mode 100644
index 000000000..24d682118
--- /dev/null
+++ b/tests/functional/lang/eval-fail-list.err.exp
@@ -0,0 +1,10 @@
+error:
+ … while evaluating one of the elements to concatenate
+
+ at /pwd/lang/eval-fail-list.nix:1:2:
+
+ 1| 8++1
+ | ^
+ 2|
+
+ error: value is an integer while a list was expected
diff --git a/tests/functional/lang/eval-fail-list.nix b/tests/functional/lang/eval-fail-list.nix
new file mode 100644
index 000000000..fa749f2f7
--- /dev/null
+++ b/tests/functional/lang/eval-fail-list.nix
@@ -0,0 +1 @@
+8++1
diff --git a/tests/functional/lang/eval-fail-missing-arg.err.exp b/tests/functional/lang/eval-fail-missing-arg.err.exp
new file mode 100644
index 000000000..61fabf0d5
--- /dev/null
+++ b/tests/functional/lang/eval-fail-missing-arg.err.exp
@@ -0,0 +1,16 @@
+error:
+ … from call site
+
+ at /pwd/lang/eval-fail-missing-arg.nix:1:1:
+
+ 1| ({x, y, z}: x + y + z) {x = "foo"; z = "bar";}
+ | ^
+ 2|
+
+ error: function 'anonymous lambda' called without required argument 'y'
+
+ at /pwd/lang/eval-fail-missing-arg.nix:1:2:
+
+ 1| ({x, y, z}: x + y + z) {x = "foo"; z = "bar";}
+ | ^
+ 2|
diff --git a/tests/functional/lang/eval-fail-missing-arg.nix b/tests/functional/lang/eval-fail-missing-arg.nix
new file mode 100644
index 000000000..c4be9797c
--- /dev/null
+++ b/tests/functional/lang/eval-fail-missing-arg.nix
@@ -0,0 +1 @@
+({x, y, z}: x + y + z) {x = "foo"; z = "bar";}
diff --git a/tests/functional/lang/eval-fail-nonexist-path.err.exp b/tests/functional/lang/eval-fail-nonexist-path.err.exp
new file mode 100644
index 000000000..c8fe39d12
--- /dev/null
+++ b/tests/functional/lang/eval-fail-nonexist-path.err.exp
@@ -0,0 +1 @@
+error: operation 'addToStoreFromDump' is not supported by store 'dummy'
diff --git a/tests/functional/lang/eval-fail-nonexist-path.nix b/tests/functional/lang/eval-fail-nonexist-path.nix
new file mode 100644
index 000000000..f2f08107b
--- /dev/null
+++ b/tests/functional/lang/eval-fail-nonexist-path.nix
@@ -0,0 +1,4 @@
+# This must fail to evaluate, since ./fnord doesn't exist. If it did
+# exist, it would produce "/nix/store/<hash>-fnord/xyzzy" (with an
+# appropriate context).
+"${./fnord}/xyzzy"
diff --git a/tests/functional/lang/eval-fail-path-slash.err.exp b/tests/functional/lang/eval-fail-path-slash.err.exp
new file mode 100644
index 000000000..f0011c97f
--- /dev/null
+++ b/tests/functional/lang/eval-fail-path-slash.err.exp
@@ -0,0 +1,8 @@
+error: path has a trailing slash
+
+ at /pwd/lang/eval-fail-path-slash.nix:6:12:
+
+ 5| # and https://nixos.org/nix-dev/2016-June/020829.html
+ 6| /nix/store/
+ | ^
+ 7|
diff --git a/tests/functional/lang/eval-fail-path-slash.nix b/tests/functional/lang/eval-fail-path-slash.nix
new file mode 100644
index 000000000..8c2e104c7
--- /dev/null
+++ b/tests/functional/lang/eval-fail-path-slash.nix
@@ -0,0 +1,6 @@
+# Trailing slashes in paths are not allowed.
+# This restriction could be lifted sometime,
+# for example if we make '/' a path concatenation operator.
+# See https://github.com/NixOS/nix/issues/1138
+# and https://nixos.org/nix-dev/2016-June/020829.html
+/nix/store/
diff --git a/tests/functional/lang/eval-fail-recursion.err.exp b/tests/functional/lang/eval-fail-recursion.err.exp
new file mode 100644
index 000000000..af64133cb
--- /dev/null
+++ b/tests/functional/lang/eval-fail-recursion.err.exp
@@ -0,0 +1,16 @@
+error:
+ … in the right operand of the update (//) operator
+
+ at /pwd/lang/eval-fail-recursion.nix:1:12:
+
+ 1| let a = {} // a; in a.foo
+ | ^
+ 2|
+
+ error: infinite recursion encountered
+
+ at /pwd/lang/eval-fail-recursion.nix:1:15:
+
+ 1| let a = {} // a; in a.foo
+ | ^
+ 2|
diff --git a/tests/functional/lang/eval-fail-recursion.nix b/tests/functional/lang/eval-fail-recursion.nix
new file mode 100644
index 000000000..075b5ed06
--- /dev/null
+++ b/tests/functional/lang/eval-fail-recursion.nix
@@ -0,0 +1 @@
+let a = {} // a; in a.foo
diff --git a/tests/functional/lang/eval-fail-remove.err.exp b/tests/functional/lang/eval-fail-remove.err.exp
new file mode 100644
index 000000000..e82cdac98
--- /dev/null
+++ b/tests/functional/lang/eval-fail-remove.err.exp
@@ -0,0 +1,19 @@
+error:
+ … while evaluating the attribute 'body'
+
+ at /pwd/lang/eval-fail-remove.nix:4:3:
+
+ 3|
+ 4| body = (removeAttrs attrs ["x"]).x;
+ | ^
+ 5| }
+
+ error: attribute 'x' missing
+
+ at /pwd/lang/eval-fail-remove.nix:4:10:
+
+ 3|
+ 4| body = (removeAttrs attrs ["x"]).x;
+ | ^
+ 5| }
+ Did you mean y?
diff --git a/tests/functional/lang/eval-fail-remove.nix b/tests/functional/lang/eval-fail-remove.nix
new file mode 100644
index 000000000..539e0eb0a
--- /dev/null
+++ b/tests/functional/lang/eval-fail-remove.nix
@@ -0,0 +1,5 @@
+let {
+ attrs = {x = 123; y = 456;};
+
+ body = (removeAttrs attrs ["x"]).x;
+} \ No newline at end of file
diff --git a/tests/functional/lang/eval-fail-scope-5.err.exp b/tests/functional/lang/eval-fail-scope-5.err.exp
new file mode 100644
index 000000000..22b6166f8
--- /dev/null
+++ b/tests/functional/lang/eval-fail-scope-5.err.exp
@@ -0,0 +1,36 @@
+error:
+ … while evaluating the attribute 'body'
+
+ at /pwd/lang/eval-fail-scope-5.nix:8:3:
+
+ 7|
+ 8| body = f {};
+ | ^
+ 9|
+
+ … from call site
+
+ at /pwd/lang/eval-fail-scope-5.nix:8:10:
+
+ 7|
+ 8| body = f {};
+ | ^
+ 9|
+
+ … while calling 'f'
+
+ at /pwd/lang/eval-fail-scope-5.nix:6:7:
+
+ 5|
+ 6| f = {x ? y, y ? x}: x + y;
+ | ^
+ 7|
+
+ error: infinite recursion encountered
+
+ at /pwd/lang/eval-fail-scope-5.nix:6:12:
+
+ 5|
+ 6| f = {x ? y, y ? x}: x + y;
+ | ^
+ 7|
diff --git a/tests/functional/lang/eval-fail-scope-5.nix b/tests/functional/lang/eval-fail-scope-5.nix
new file mode 100644
index 000000000..f89a65a99
--- /dev/null
+++ b/tests/functional/lang/eval-fail-scope-5.nix
@@ -0,0 +1,10 @@
+let {
+
+ x = "a";
+ y = "b";
+
+ f = {x ? y, y ? x}: x + y;
+
+ body = f {};
+
+}
diff --git a/tests/functional/lang/eval-fail-seq.err.exp b/tests/functional/lang/eval-fail-seq.err.exp
new file mode 100644
index 000000000..33a7e9491
--- /dev/null
+++ b/tests/functional/lang/eval-fail-seq.err.exp
@@ -0,0 +1,18 @@
+error:
+ … while calling the 'seq' builtin
+
+ at /pwd/lang/eval-fail-seq.nix:1:1:
+
+ 1| builtins.seq (abort "foo") 2
+ | ^
+ 2|
+
+ … while calling the 'abort' builtin
+
+ at /pwd/lang/eval-fail-seq.nix:1:15:
+
+ 1| builtins.seq (abort "foo") 2
+ | ^
+ 2|
+
+ error: evaluation aborted with the following error message: 'foo'
diff --git a/tests/functional/lang/eval-fail-seq.nix b/tests/functional/lang/eval-fail-seq.nix
new file mode 100644
index 000000000..cddbbfd32
--- /dev/null
+++ b/tests/functional/lang/eval-fail-seq.nix
@@ -0,0 +1 @@
+builtins.seq (abort "foo") 2
diff --git a/tests/functional/lang/eval-fail-set-override.err.exp b/tests/functional/lang/eval-fail-set-override.err.exp
new file mode 100644
index 000000000..beb29d678
--- /dev/null
+++ b/tests/functional/lang/eval-fail-set-override.err.exp
@@ -0,0 +1,6 @@
+error:
+ … while evaluating the `__overrides` attribute
+
+ at «none»:0: (source not available)
+
+ error: value is an integer while a set was expected
diff --git a/tests/functional/lang/eval-fail-set-override.nix b/tests/functional/lang/eval-fail-set-override.nix
new file mode 100644
index 000000000..03551c186
--- /dev/null
+++ b/tests/functional/lang/eval-fail-set-override.nix
@@ -0,0 +1 @@
+rec { __overrides = 1; }
diff --git a/tests/functional/lang/eval-fail-set.err.exp b/tests/functional/lang/eval-fail-set.err.exp
new file mode 100644
index 000000000..0d0140508
--- /dev/null
+++ b/tests/functional/lang/eval-fail-set.err.exp
@@ -0,0 +1,7 @@
+error: undefined variable 'x'
+
+ at /pwd/lang/eval-fail-set.nix:1:3:
+
+ 1| 8.x
+ | ^
+ 2|
diff --git a/tests/functional/lang/eval-fail-set.nix b/tests/functional/lang/eval-fail-set.nix
new file mode 100644
index 000000000..c6b7980b6
--- /dev/null
+++ b/tests/functional/lang/eval-fail-set.nix
@@ -0,0 +1 @@
+8.x
diff --git a/tests/functional/lang/eval-fail-substring.err.exp b/tests/functional/lang/eval-fail-substring.err.exp
new file mode 100644
index 000000000..dc26a00bd
--- /dev/null
+++ b/tests/functional/lang/eval-fail-substring.err.exp
@@ -0,0 +1,12 @@
+error:
+ … while calling the 'substring' builtin
+
+ at /pwd/lang/eval-fail-substring.nix:1:1:
+
+ 1| builtins.substring (builtins.sub 0 1) 1 "x"
+ | ^
+ 2|
+
+ error: negative start position in 'substring'
+
+ at «none»:0: (source not available)
diff --git a/tests/functional/lang/eval-fail-substring.nix b/tests/functional/lang/eval-fail-substring.nix
new file mode 100644
index 000000000..f37c2bc0a
--- /dev/null
+++ b/tests/functional/lang/eval-fail-substring.nix
@@ -0,0 +1 @@
+builtins.substring (builtins.sub 0 1) 1 "x"
diff --git a/tests/functional/lang/eval-fail-to-path.err.exp b/tests/functional/lang/eval-fail-to-path.err.exp
new file mode 100644
index 000000000..43ed2bdfc
--- /dev/null
+++ b/tests/functional/lang/eval-fail-to-path.err.exp
@@ -0,0 +1,14 @@
+error:
+ … while calling the 'toPath' builtin
+
+ at /pwd/lang/eval-fail-to-path.nix:1:1:
+
+ 1| builtins.toPath "foo/bar"
+ | ^
+ 2|
+
+ … while evaluating the first argument passed to builtins.toPath
+
+ at «none»:0: (source not available)
+
+ error: string 'foo/bar' doesn't represent an absolute path
diff --git a/tests/functional/lang/eval-fail-to-path.nix b/tests/functional/lang/eval-fail-to-path.nix
new file mode 100644
index 000000000..5e322bc31
--- /dev/null
+++ b/tests/functional/lang/eval-fail-to-path.nix
@@ -0,0 +1 @@
+builtins.toPath "foo/bar"
diff --git a/tests/functional/lang/eval-fail-toJSON.err.exp b/tests/functional/lang/eval-fail-toJSON.err.exp
new file mode 100644
index 000000000..4e618c203
--- /dev/null
+++ b/tests/functional/lang/eval-fail-toJSON.err.exp
@@ -0,0 +1,57 @@
+error:
+ … while calling the 'toJSON' builtin
+
+ at /pwd/lang/eval-fail-toJSON.nix:1:1:
+
+ 1| builtins.toJSON {
+ | ^
+ 2| a.b = [
+
+ … while evaluating attribute 'a'
+
+ at /pwd/lang/eval-fail-toJSON.nix:2:3:
+
+ 1| builtins.toJSON {
+ 2| a.b = [
+ | ^
+ 3| true
+
+ … while evaluating attribute 'b'
+
+ at /pwd/lang/eval-fail-toJSON.nix:2:3:
+
+ 1| builtins.toJSON {
+ 2| a.b = [
+ | ^
+ 3| true
+
+ … while evaluating list element at index 3
+
+ … while evaluating attribute 'c'
+
+ at /pwd/lang/eval-fail-toJSON.nix:7:7:
+
+ 6| {
+ 7| c.d = throw "hah no";
+ | ^
+ 8| }
+
+ … while evaluating attribute 'd'
+
+ at /pwd/lang/eval-fail-toJSON.nix:7:7:
+
+ 6| {
+ 7| c.d = throw "hah no";
+ | ^
+ 8| }
+
+ … while calling the 'throw' builtin
+
+ at /pwd/lang/eval-fail-toJSON.nix:7:13:
+
+ 6| {
+ 7| c.d = throw "hah no";
+ | ^
+ 8| }
+
+ error: hah no
diff --git a/tests/functional/lang/eval-fail-toJSON.nix b/tests/functional/lang/eval-fail-toJSON.nix
new file mode 100644
index 000000000..8112e1c1f
--- /dev/null
+++ b/tests/functional/lang/eval-fail-toJSON.nix
@@ -0,0 +1,10 @@
+builtins.toJSON {
+ a.b = [
+ true
+ false
+ "it's a bird"
+ {
+ c.d = throw "hah no";
+ }
+ ];
+}
diff --git a/tests/functional/lang/eval-fail-undeclared-arg.err.exp b/tests/functional/lang/eval-fail-undeclared-arg.err.exp
new file mode 100644
index 000000000..30db743c7
--- /dev/null
+++ b/tests/functional/lang/eval-fail-undeclared-arg.err.exp
@@ -0,0 +1,17 @@
+error:
+ … from call site
+
+ at /pwd/lang/eval-fail-undeclared-arg.nix:1:1:
+
+ 1| ({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";}
+ | ^
+ 2|
+
+ error: function 'anonymous lambda' called with unexpected argument 'y'
+
+ at /pwd/lang/eval-fail-undeclared-arg.nix:1:2:
+
+ 1| ({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";}
+ | ^
+ 2|
+ Did you mean one of x or z?
diff --git a/tests/functional/lang/eval-fail-undeclared-arg.nix b/tests/functional/lang/eval-fail-undeclared-arg.nix
new file mode 100644
index 000000000..cafdf1636
--- /dev/null
+++ b/tests/functional/lang/eval-fail-undeclared-arg.nix
@@ -0,0 +1 @@
+({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";}
diff --git a/tests/functional/lang/eval-okay-any-all.exp b/tests/functional/lang/eval-okay-any-all.exp
new file mode 100644
index 000000000..eb273f45b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-any-all.exp
@@ -0,0 +1 @@
+[ false false true true true true false true ]
diff --git a/tests/functional/lang/eval-okay-any-all.nix b/tests/functional/lang/eval-okay-any-all.nix
new file mode 100644
index 000000000..a3f26ea2a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-any-all.nix
@@ -0,0 +1,11 @@
+with builtins;
+
+[ (any (x: x == 1) [])
+ (any (x: x == 1) [2 3 4])
+ (any (x: x == 1) [1 2 3 4])
+ (any (x: x == 1) [4 3 2 1])
+ (all (x: x == 1) [])
+ (all (x: x == 1) [1])
+ (all (x: x == 1) [1 2 3])
+ (all (x: x == 1) [1 1 1])
+]
diff --git a/tests/functional/lang/eval-okay-arithmetic.exp b/tests/functional/lang/eval-okay-arithmetic.exp
new file mode 100644
index 000000000..5c54d10b7
--- /dev/null
+++ b/tests/functional/lang/eval-okay-arithmetic.exp
@@ -0,0 +1 @@
+2216
diff --git a/tests/functional/lang/eval-okay-arithmetic.nix b/tests/functional/lang/eval-okay-arithmetic.nix
new file mode 100644
index 000000000..7e9e6a0b6
--- /dev/null
+++ b/tests/functional/lang/eval-okay-arithmetic.nix
@@ -0,0 +1,59 @@
+with import ./lib.nix;
+
+let {
+
+ /* Supposedly tail recursive version:
+
+ range_ = accum: first: last:
+ if first == last then ([first] ++ accum)
+ else range_ ([first] ++ accum) (builtins.add first 1) last;
+
+ range = range_ [];
+ */
+
+ x = 12;
+
+ err = abort "urgh";
+
+ body = sum
+ [ (sum (range 1 50))
+ (123 + 456)
+ (0 + -10 + -(-11) + -x)
+ (10 - 7 - -2)
+ (10 - (6 - -1))
+ (10 - 1 + 2)
+ (3 * 4 * 5)
+ (56088 / 123 / 2)
+ (3 + 4 * const 5 0 - 6 / id 2)
+
+ (builtins.bitAnd 12 10) # 0b1100 & 0b1010 = 8
+ (builtins.bitOr 12 10) # 0b1100 | 0b1010 = 14
+ (builtins.bitXor 12 10) # 0b1100 ^ 0b1010 = 6
+
+ (if 3 < 7 then 1 else err)
+ (if 7 < 3 then err else 1)
+ (if 3 < 3 then err else 1)
+
+ (if 3 <= 7 then 1 else err)
+ (if 7 <= 3 then err else 1)
+ (if 3 <= 3 then 1 else err)
+
+ (if 3 > 7 then err else 1)
+ (if 7 > 3 then 1 else err)
+ (if 3 > 3 then err else 1)
+
+ (if 3 >= 7 then err else 1)
+ (if 7 >= 3 then 1 else err)
+ (if 3 >= 3 then 1 else err)
+
+ (if 2 > 1 == 1 < 2 then 1 else err)
+ (if 1 + 2 * 3 >= 7 then 1 else err)
+ (if 1 + 2 * 3 < 7 then err else 1)
+
+ # Not integer, but so what.
+ (if "aa" < "ab" then 1 else err)
+ (if "aa" < "aa" then err else 1)
+ (if "foo" < "foobar" then 1 else err)
+ ];
+
+}
diff --git a/tests/functional/lang/eval-okay-attrnames.exp b/tests/functional/lang/eval-okay-attrnames.exp
new file mode 100644
index 000000000..b4aa387e0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrnames.exp
@@ -0,0 +1 @@
+"newxfoonewxy"
diff --git a/tests/functional/lang/eval-okay-attrnames.nix b/tests/functional/lang/eval-okay-attrnames.nix
new file mode 100644
index 000000000..e5b26e9f2
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrnames.nix
@@ -0,0 +1,11 @@
+with import ./lib.nix;
+
+let
+
+ attrs = {y = "y"; x = "x"; foo = "foo";} // rec {x = "newx"; bar = x;};
+
+ names = builtins.attrNames attrs;
+
+ values = map (name: builtins.getAttr name attrs) names;
+
+in assert values == builtins.attrValues attrs; concat values
diff --git a/tests/functional/lang/eval-okay-attrs.exp b/tests/functional/lang/eval-okay-attrs.exp
new file mode 100644
index 000000000..45b0f829e
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs.exp
@@ -0,0 +1 @@
+987
diff --git a/tests/functional/lang/eval-okay-attrs.nix b/tests/functional/lang/eval-okay-attrs.nix
new file mode 100644
index 000000000..810b31a5d
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs.nix
@@ -0,0 +1,5 @@
+let {
+ as = { x = 123; y = 456; } // { z = 789; } // { z = 987; };
+
+ body = if as ? a then as.a else assert as ? z; as.z;
+}
diff --git a/tests/functional/lang/eval-okay-attrs2.exp b/tests/functional/lang/eval-okay-attrs2.exp
new file mode 100644
index 000000000..45b0f829e
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs2.exp
@@ -0,0 +1 @@
+987
diff --git a/tests/functional/lang/eval-okay-attrs2.nix b/tests/functional/lang/eval-okay-attrs2.nix
new file mode 100644
index 000000000..9e06b83ac
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs2.nix
@@ -0,0 +1,10 @@
+let {
+ as = { x = 123; y = 456; } // { z = 789; } // { z = 987; };
+
+ A = "a";
+ Z = "z";
+
+ body = if builtins.hasAttr A as
+ then builtins.getAttr A as
+ else assert builtins.hasAttr Z as; builtins.getAttr Z as;
+}
diff --git a/tests/functional/lang/eval-okay-attrs3.exp b/tests/functional/lang/eval-okay-attrs3.exp
new file mode 100644
index 000000000..19de4fdf7
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs3.exp
@@ -0,0 +1 @@
+"foo 22 80 itchyxac"
diff --git a/tests/functional/lang/eval-okay-attrs3.nix b/tests/functional/lang/eval-okay-attrs3.nix
new file mode 100644
index 000000000..f29de11fe
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs3.nix
@@ -0,0 +1,22 @@
+let
+
+ config =
+ {
+ services.sshd.enable = true;
+ services.sshd.port = 22;
+ services.httpd.port = 80;
+ hostName = "itchy";
+ a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = "x";
+ foo = {
+ a = "a";
+ b.c = "c";
+ };
+ };
+
+in
+ if config.services.sshd.enable
+ then "foo ${toString config.services.sshd.port} ${toString config.services.httpd.port} ${config.hostName}"
+ + "${config.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z}"
+ + "${config.foo.a}"
+ + "${config.foo.b.c}"
+ else "bar"
diff --git a/tests/functional/lang/eval-okay-attrs4.exp b/tests/functional/lang/eval-okay-attrs4.exp
new file mode 100644
index 000000000..185173144
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs4.exp
@@ -0,0 +1 @@
+[ true false true false false true false false ]
diff --git a/tests/functional/lang/eval-okay-attrs4.nix b/tests/functional/lang/eval-okay-attrs4.nix
new file mode 100644
index 000000000..43ec81210
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs4.nix
@@ -0,0 +1,7 @@
+let
+
+ as = { x.y.z = 123; a.b.c = 456; };
+
+ bs = null;
+
+in [ (as ? x) (as ? y) (as ? x.y.z) (as ? x.y.z.a) (as ? x.y.a) (as ? a.b.c) (bs ? x) (bs ? x.y.z) ]
diff --git a/tests/functional/lang/eval-okay-attrs5.exp b/tests/functional/lang/eval-okay-attrs5.exp
new file mode 100644
index 000000000..ce0430d78
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs5.exp
@@ -0,0 +1 @@
+[ 123 "foo" 456 456 "foo" "xyzzy" "xyzzy" true ]
diff --git a/tests/functional/lang/eval-okay-attrs5.nix b/tests/functional/lang/eval-okay-attrs5.nix
new file mode 100644
index 000000000..a4584cd3b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs5.nix
@@ -0,0 +1,21 @@
+with import ./lib.nix;
+
+let
+
+ as = { x.y.z = 123; a.b.c = 456; };
+
+ bs = { f-o-o.bar = "foo"; };
+
+ or = x: y: x || y;
+
+in
+ [ as.x.y.z
+ as.foo or "foo"
+ as.x.y.bla or as.a.b.c
+ as.a.b.c or as.x.y.z
+ as.x.y.bla or bs.f-o-o.bar or "xyzzy"
+ as.x.y.bla or bs.bar.foo or "xyzzy"
+ (123).bla or null.foo or "xyzzy"
+ # Backwards compatibility test.
+ (fold or [] [true false false])
+ ]
diff --git a/tests/functional/lang/eval-okay-attrs6.exp b/tests/functional/lang/eval-okay-attrs6.exp
new file mode 100644
index 000000000..b46938032
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs6.exp
@@ -0,0 +1 @@
+{ __overrides = { bar = "qux"; }; bar = "qux"; foo = "bar"; }
diff --git a/tests/functional/lang/eval-okay-attrs6.nix b/tests/functional/lang/eval-okay-attrs6.nix
new file mode 100644
index 000000000..2e5c85483
--- /dev/null
+++ b/tests/functional/lang/eval-okay-attrs6.nix
@@ -0,0 +1,4 @@
+rec {
+ "${"foo"}" = "bar";
+ __overrides = { bar = "qux"; };
+}
diff --git a/tests/functional/lang/eval-okay-autoargs.exp b/tests/functional/lang/eval-okay-autoargs.exp
new file mode 100644
index 000000000..7a8391786
--- /dev/null
+++ b/tests/functional/lang/eval-okay-autoargs.exp
@@ -0,0 +1 @@
+"xyzzy!xyzzy!foobar"
diff --git a/tests/functional/lang/eval-okay-autoargs.flags b/tests/functional/lang/eval-okay-autoargs.flags
new file mode 100644
index 000000000..ae3762254
--- /dev/null
+++ b/tests/functional/lang/eval-okay-autoargs.flags
@@ -0,0 +1 @@
+--arg lib import(lang/lib.nix) --argstr xyzzy xyzzy! -A result
diff --git a/tests/functional/lang/eval-okay-autoargs.nix b/tests/functional/lang/eval-okay-autoargs.nix
new file mode 100644
index 000000000..815f51b1d
--- /dev/null
+++ b/tests/functional/lang/eval-okay-autoargs.nix
@@ -0,0 +1,15 @@
+let
+
+ foobar = "foobar";
+
+in
+
+{ xyzzy2 ? xyzzy # mutually recursive args
+, xyzzy ? "blaat" # will be overridden by --argstr
+, fb ? foobar
+, lib # will be set by --arg
+}:
+
+{
+ result = lib.concat [xyzzy xyzzy2 fb];
+}
diff --git a/tests/functional/lang/eval-okay-backslash-newline-1.exp b/tests/functional/lang/eval-okay-backslash-newline-1.exp
new file mode 100644
index 000000000..3e754364c
--- /dev/null
+++ b/tests/functional/lang/eval-okay-backslash-newline-1.exp
@@ -0,0 +1 @@
+"a\nb"
diff --git a/tests/functional/lang/eval-okay-backslash-newline-1.nix b/tests/functional/lang/eval-okay-backslash-newline-1.nix
new file mode 100644
index 000000000..7fef3dddd
--- /dev/null
+++ b/tests/functional/lang/eval-okay-backslash-newline-1.nix
@@ -0,0 +1,2 @@
+"a\
+b"
diff --git a/tests/functional/lang/eval-okay-backslash-newline-2.exp b/tests/functional/lang/eval-okay-backslash-newline-2.exp
new file mode 100644
index 000000000..3e754364c
--- /dev/null
+++ b/tests/functional/lang/eval-okay-backslash-newline-2.exp
@@ -0,0 +1 @@
+"a\nb"
diff --git a/tests/functional/lang/eval-okay-backslash-newline-2.nix b/tests/functional/lang/eval-okay-backslash-newline-2.nix
new file mode 100644
index 000000000..35ddf495c
--- /dev/null
+++ b/tests/functional/lang/eval-okay-backslash-newline-2.nix
@@ -0,0 +1,2 @@
+''a''\
+b''
diff --git a/tests/functional/lang/eval-okay-builtins-add.exp b/tests/functional/lang/eval-okay-builtins-add.exp
new file mode 100644
index 000000000..0350b518a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-builtins-add.exp
@@ -0,0 +1 @@
+[ 5 4 "int" "tt" "float" 4 ]
diff --git a/tests/functional/lang/eval-okay-builtins-add.nix b/tests/functional/lang/eval-okay-builtins-add.nix
new file mode 100644
index 000000000..c84181622
--- /dev/null
+++ b/tests/functional/lang/eval-okay-builtins-add.nix
@@ -0,0 +1,8 @@
+[
+(builtins.add 2 3)
+(builtins.add 2 2)
+(builtins.typeOf (builtins.add 2 2))
+("t" + "t")
+(builtins.typeOf (builtins.add 2.0 2))
+(builtins.add 2.0 2)
+]
diff --git a/tests/functional/lang/eval-okay-builtins.exp b/tests/functional/lang/eval-okay-builtins.exp
new file mode 100644
index 000000000..0661686d6
--- /dev/null
+++ b/tests/functional/lang/eval-okay-builtins.exp
@@ -0,0 +1 @@
+/foo
diff --git a/tests/functional/lang/eval-okay-builtins.nix b/tests/functional/lang/eval-okay-builtins.nix
new file mode 100644
index 000000000..e9d65e88a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-builtins.nix
@@ -0,0 +1,12 @@
+assert builtins ? currentSystem;
+assert !builtins ? __currentSystem;
+
+let {
+
+ x = if builtins ? dirOf then builtins.dirOf /foo/bar else "";
+
+ y = if builtins ? fnord then builtins.fnord "foo" else "";
+
+ body = x + y;
+
+}
diff --git a/tests/functional/lang/eval-okay-callable-attrs.exp b/tests/functional/lang/eval-okay-callable-attrs.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-callable-attrs.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-callable-attrs.nix b/tests/functional/lang/eval-okay-callable-attrs.nix
new file mode 100644
index 000000000..310a030df
--- /dev/null
+++ b/tests/functional/lang/eval-okay-callable-attrs.nix
@@ -0,0 +1 @@
+({ __functor = self: x: self.foo && x; foo = false; } // { foo = true; }) true
diff --git a/tests/functional/lang/eval-okay-catattrs.exp b/tests/functional/lang/eval-okay-catattrs.exp
new file mode 100644
index 000000000..b4a1e66d6
--- /dev/null
+++ b/tests/functional/lang/eval-okay-catattrs.exp
@@ -0,0 +1 @@
+[ 1 2 ]
diff --git a/tests/functional/lang/eval-okay-catattrs.nix b/tests/functional/lang/eval-okay-catattrs.nix
new file mode 100644
index 000000000..2c3dc10da
--- /dev/null
+++ b/tests/functional/lang/eval-okay-catattrs.nix
@@ -0,0 +1 @@
+builtins.catAttrs "a" [ { a = 1; } { b = 0; } { a = 2; } ]
diff --git a/tests/functional/lang/eval-okay-closure.exp b/tests/functional/lang/eval-okay-closure.exp
new file mode 100644
index 000000000..e7dbf9781
--- /dev/null
+++ b/tests/functional/lang/eval-okay-closure.exp
@@ -0,0 +1 @@
+[ { foo = true; key = -13; } { foo = true; key = -12; } { foo = true; key = -11; } { foo = true; key = -9; } { foo = true; key = -8; } { foo = true; key = -7; } { foo = true; key = -5; } { foo = true; key = -4; } { foo = true; key = -3; } { key = -1; } { foo = true; key = 0; } { foo = true; key = 1; } { foo = true; key = 2; } { foo = true; key = 4; } { foo = true; key = 5; } { foo = true; key = 6; } { key = 8; } { foo = true; key = 9; } { foo = true; key = 10; } { foo = true; key = 13; } { foo = true; key = 14; } { foo = true; key = 15; } { key = 17; } { foo = true; key = 18; } { foo = true; key = 19; } { foo = true; key = 22; } { foo = true; key = 23; } { key = 26; } { foo = true; key = 27; } { foo = true; key = 28; } { foo = true; key = 31; } { foo = true; key = 32; } { key = 35; } { foo = true; key = 36; } { foo = true; key = 40; } { foo = true; key = 41; } { key = 44; } { foo = true; key = 45; } { foo = true; key = 49; } { key = 53; } { foo = true; key = 54; } { foo = true; key = 58; } { key = 62; } { foo = true; key = 67; } { key = 71; } { key = 80; } ]
diff --git a/tests/functional/lang/eval-okay-closure.exp.xml b/tests/functional/lang/eval-okay-closure.exp.xml
new file mode 100644
index 000000000..dffc03a99
--- /dev/null
+++ b/tests/functional/lang/eval-okay-closure.exp.xml
@@ -0,0 +1,343 @@
+<?xml version='1.0' encoding='utf-8'?>
+<expr>
+ <list>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-13" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-12" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-11" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-9" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-8" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-7" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-5" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-4" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="-3" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="-1" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="0" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="1" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="2" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="4" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="5" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="6" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="8" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="9" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="10" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="13" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="14" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="15" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="17" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="18" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="19" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="22" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="23" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="26" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="27" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="28" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="31" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="32" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="35" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="36" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="40" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="41" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="44" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="45" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="49" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="53" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="54" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="58" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="62" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="foo">
+ <bool value="true" />
+ </attr>
+ <attr name="key">
+ <int value="67" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="71" />
+ </attr>
+ </attrs>
+ <attrs>
+ <attr name="key">
+ <int value="80" />
+ </attr>
+ </attrs>
+ </list>
+</expr>
diff --git a/tests/functional/lang/eval-okay-closure.nix b/tests/functional/lang/eval-okay-closure.nix
new file mode 100644
index 000000000..cccd4dc35
--- /dev/null
+++ b/tests/functional/lang/eval-okay-closure.nix
@@ -0,0 +1,13 @@
+let
+
+ closure = builtins.genericClosure {
+ startSet = [{key = 80;}];
+ operator = {key, foo ? false}:
+ if builtins.lessThan key 0
+ then []
+ else [{key = builtins.sub key 9;} {key = builtins.sub key 13; foo = true;}];
+ };
+
+ sort = (import ./lib.nix).sortBy (a: b: builtins.lessThan a.key b.key);
+
+in sort closure
diff --git a/tests/functional/lang/eval-okay-comments.exp b/tests/functional/lang/eval-okay-comments.exp
new file mode 100644
index 000000000..7182dc2f9
--- /dev/null
+++ b/tests/functional/lang/eval-okay-comments.exp
@@ -0,0 +1 @@
+"abcdefghijklmnopqrstuvwxyz"
diff --git a/tests/functional/lang/eval-okay-comments.nix b/tests/functional/lang/eval-okay-comments.nix
new file mode 100644
index 000000000..cb2cce218
--- /dev/null
+++ b/tests/functional/lang/eval-okay-comments.nix
@@ -0,0 +1,59 @@
+# A simple comment
+"a"+ # And another
+## A double comment
+"b"+ ## And another
+# Nested # comments #
+"c"+ # and # some # other #
+# An empty line, following here:
+
+"d"+ # and a comment not starting the line !
+
+"e"+
+/* multiline comments */
+"f" +
+/* multiline
+ comments,
+ on
+ multiple
+ lines
+*/
+"g" +
+# Small, tricky comments
+/**/ "h"+ /*/*/ "i"+ /***/ "j"+ /* /*/ "k"+ /*/* /*/ "l"+
+# Comments with an even number of ending '*' used to fail:
+"m"+
+/* */ /* **/ /* ***/ /* ****/ "n"+
+/* */ /** */ /*** */ /**** */ "o"+
+/** **/ /*** ***/ /**** ****/ "p"+
+/* * ** *** **** ***** */ "q"+
+# Random comments
+/* ***** ////// * / * / /* */ "r"+
+# Mixed comments
+/* # */
+"s"+
+# /* #
+"t"+
+# /* # */
+"u"+
+# /*********/
+"v"+
+## */*
+"w"+
+/*
+ * Multiline, decorated comments
+ * # This ain't a nest'd comm'nt
+ */
+"x"+
+''${/** with **/"y"
+ # real
+ /* comments
+ inside ! # */
+
+ # (and empty lines)
+
+}''+ /* And a multiline comment,
+ on the same line,
+ after some spaces
+*/ # followed by a one-line comment
+"z"
+/* EOF */
diff --git a/tests/functional/lang/eval-okay-concat.exp b/tests/functional/lang/eval-okay-concat.exp
new file mode 100644
index 000000000..bb4bbd577
--- /dev/null
+++ b/tests/functional/lang/eval-okay-concat.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 5 6 7 8 9 ]
diff --git a/tests/functional/lang/eval-okay-concat.nix b/tests/functional/lang/eval-okay-concat.nix
new file mode 100644
index 000000000..d158a9bf0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-concat.nix
@@ -0,0 +1 @@
+[1 2 3] ++ [4 5 6] ++ [7 8 9]
diff --git a/tests/functional/lang/eval-okay-concatmap.exp b/tests/functional/lang/eval-okay-concatmap.exp
new file mode 100644
index 000000000..3b8be7739
--- /dev/null
+++ b/tests/functional/lang/eval-okay-concatmap.exp
@@ -0,0 +1 @@
+[ [ 1 3 5 7 9 ] [ "a" "z" "b" "z" ] ]
diff --git a/tests/functional/lang/eval-okay-concatmap.nix b/tests/functional/lang/eval-okay-concatmap.nix
new file mode 100644
index 000000000..97da5d37a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-concatmap.nix
@@ -0,0 +1,5 @@
+with import ./lib.nix;
+
+[ (builtins.concatMap (x: if x / 2 * 2 == x then [] else [ x ]) (range 0 10))
+ (builtins.concatMap (x: [x] ++ ["z"]) ["a" "b"])
+]
diff --git a/tests/functional/lang/eval-okay-concatstringssep.exp b/tests/functional/lang/eval-okay-concatstringssep.exp
new file mode 100644
index 000000000..93987647f
--- /dev/null
+++ b/tests/functional/lang/eval-okay-concatstringssep.exp
@@ -0,0 +1 @@
+[ "" "foobarxyzzy" "foo, bar, xyzzy" "foo" "" ]
diff --git a/tests/functional/lang/eval-okay-concatstringssep.nix b/tests/functional/lang/eval-okay-concatstringssep.nix
new file mode 100644
index 000000000..adc4c41bd
--- /dev/null
+++ b/tests/functional/lang/eval-okay-concatstringssep.nix
@@ -0,0 +1,8 @@
+with builtins;
+
+[ (concatStringsSep "" [])
+ (concatStringsSep "" ["foo" "bar" "xyzzy"])
+ (concatStringsSep ", " ["foo" "bar" "xyzzy"])
+ (concatStringsSep ", " ["foo"])
+ (concatStringsSep ", " [])
+]
diff --git a/tests/functional/lang/eval-okay-context-introspection.exp b/tests/functional/lang/eval-okay-context-introspection.exp
new file mode 100644
index 000000000..03b400cc8
--- /dev/null
+++ b/tests/functional/lang/eval-okay-context-introspection.exp
@@ -0,0 +1 @@
+[ true true true true true true ]
diff --git a/tests/functional/lang/eval-okay-context-introspection.nix b/tests/functional/lang/eval-okay-context-introspection.nix
new file mode 100644
index 000000000..50a78d946
--- /dev/null
+++ b/tests/functional/lang/eval-okay-context-introspection.nix
@@ -0,0 +1,41 @@
+let
+ drv = derivation {
+ name = "fail";
+ builder = "/bin/false";
+ system = "x86_64-linux";
+ outputs = [ "out" "foo" ];
+ };
+
+ path = "${./eval-okay-context-introspection.nix}";
+
+ desired-context = {
+ "${builtins.unsafeDiscardStringContext path}" = {
+ path = true;
+ };
+ "${builtins.unsafeDiscardStringContext drv.drvPath}" = {
+ outputs = [ "foo" "out" ];
+ allOutputs = true;
+ };
+ };
+
+ combo-path = "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}";
+ legit-context = builtins.getContext combo-path;
+
+ reconstructed-path = builtins.appendContext
+ (builtins.unsafeDiscardStringContext combo-path)
+ desired-context;
+
+ # Eta rule for strings with context.
+ etaRule = str:
+ str == builtins.appendContext
+ (builtins.unsafeDiscardStringContext str)
+ (builtins.getContext str);
+
+in [
+ (legit-context == desired-context)
+ (reconstructed-path == combo-path)
+ (etaRule "foo")
+ (etaRule drv.drvPath)
+ (etaRule drv.foo.outPath)
+ (etaRule (builtins.unsafeDiscardOutputDependency drv.drvPath))
+]
diff --git a/tests/functional/lang/eval-okay-context.exp b/tests/functional/lang/eval-okay-context.exp
new file mode 100644
index 000000000..2f535bdbc
--- /dev/null
+++ b/tests/functional/lang/eval-okay-context.exp
@@ -0,0 +1 @@
+"foo eval-okay-context.nix bar"
diff --git a/tests/functional/lang/eval-okay-context.nix b/tests/functional/lang/eval-okay-context.nix
new file mode 100644
index 000000000..7b9531cfe
--- /dev/null
+++ b/tests/functional/lang/eval-okay-context.nix
@@ -0,0 +1,6 @@
+let s = "foo ${builtins.substring 33 100 (baseNameOf "${./eval-okay-context.nix}")} bar";
+in
+ if s != "foo eval-okay-context.nix bar"
+ then abort "context not discarded"
+ else builtins.unsafeDiscardStringContext s
+
diff --git a/tests/functional/lang/eval-okay-curpos.exp b/tests/functional/lang/eval-okay-curpos.exp
new file mode 100644
index 000000000..65fd65b4d
--- /dev/null
+++ b/tests/functional/lang/eval-okay-curpos.exp
@@ -0,0 +1 @@
+[ 3 7 4 9 ]
diff --git a/tests/functional/lang/eval-okay-curpos.nix b/tests/functional/lang/eval-okay-curpos.nix
new file mode 100644
index 000000000..b79553df0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-curpos.nix
@@ -0,0 +1,5 @@
+# Bla
+let
+ x = __curPos;
+ y = __curPos;
+in [ x.line x.column y.line y.column ]
diff --git a/tests/functional/lang/eval-okay-deepseq.exp b/tests/functional/lang/eval-okay-deepseq.exp
new file mode 100644
index 000000000..8d38505c1
--- /dev/null
+++ b/tests/functional/lang/eval-okay-deepseq.exp
@@ -0,0 +1 @@
+456
diff --git a/tests/functional/lang/eval-okay-deepseq.nix b/tests/functional/lang/eval-okay-deepseq.nix
new file mode 100644
index 000000000..53aa4b1dc
--- /dev/null
+++ b/tests/functional/lang/eval-okay-deepseq.nix
@@ -0,0 +1 @@
+builtins.deepSeq (let as = { x = 123; y = as; }; in as) 456
diff --git a/tests/functional/lang/eval-okay-delayed-with-inherit.exp b/tests/functional/lang/eval-okay-delayed-with-inherit.exp
new file mode 100644
index 000000000..eaacb55c1
--- /dev/null
+++ b/tests/functional/lang/eval-okay-delayed-with-inherit.exp
@@ -0,0 +1 @@
+"b-overridden"
diff --git a/tests/functional/lang/eval-okay-delayed-with-inherit.nix b/tests/functional/lang/eval-okay-delayed-with-inherit.nix
new file mode 100644
index 000000000..84b388c27
--- /dev/null
+++ b/tests/functional/lang/eval-okay-delayed-with-inherit.nix
@@ -0,0 +1,24 @@
+let
+ pkgs_ = with pkgs; {
+ a = derivation {
+ name = "a";
+ system = builtins.currentSystem;
+ builder = "/bin/sh";
+ args = [ "-c" "touch $out" ];
+ inherit b;
+ };
+
+ inherit b;
+ };
+
+ packageOverrides = p: {
+ b = derivation {
+ name = "b-overridden";
+ system = builtins.currentSystem;
+ builder = "/bin/sh";
+ args = [ "-c" "touch $out" ];
+ };
+ };
+
+ pkgs = pkgs_ // (packageOverrides pkgs_);
+in pkgs.a.b.name
diff --git a/tests/functional/lang/eval-okay-delayed-with.exp b/tests/functional/lang/eval-okay-delayed-with.exp
new file mode 100644
index 000000000..8e7c61ab8
--- /dev/null
+++ b/tests/functional/lang/eval-okay-delayed-with.exp
@@ -0,0 +1 @@
+"b-overridden b-overridden a"
diff --git a/tests/functional/lang/eval-okay-delayed-with.nix b/tests/functional/lang/eval-okay-delayed-with.nix
new file mode 100644
index 000000000..3fb023e1c
--- /dev/null
+++ b/tests/functional/lang/eval-okay-delayed-with.nix
@@ -0,0 +1,29 @@
+let
+
+ pkgs_ = with pkgs; {
+ a = derivation {
+ name = "a";
+ system = builtins.currentSystem;
+ builder = "/bin/sh";
+ args = [ "-c" "touch $out" ];
+ inherit b;
+ };
+
+ b = derivation {
+ name = "b";
+ system = builtins.currentSystem;
+ builder = "/bin/sh";
+ args = [ "-c" "touch $out" ];
+ inherit a;
+ };
+
+ c = b;
+ };
+
+ packageOverrides = pkgs: with pkgs; {
+ b = derivation (b.drvAttrs // { name = "${b.name}-overridden"; });
+ };
+
+ pkgs = pkgs_ // (packageOverrides pkgs_);
+
+in "${pkgs.a.b.name} ${pkgs.c.name} ${pkgs.b.a.name}"
diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-2.exp b/tests/functional/lang/eval-okay-dynamic-attrs-2.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-dynamic-attrs-2.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-2.nix b/tests/functional/lang/eval-okay-dynamic-attrs-2.nix
new file mode 100644
index 000000000..6d57bf854
--- /dev/null
+++ b/tests/functional/lang/eval-okay-dynamic-attrs-2.nix
@@ -0,0 +1 @@
+{ a."${"b"}" = true; a."${"c"}" = false; }.a.b
diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-bare.exp b/tests/functional/lang/eval-okay-dynamic-attrs-bare.exp
new file mode 100644
index 000000000..df8750afc
--- /dev/null
+++ b/tests/functional/lang/eval-okay-dynamic-attrs-bare.exp
@@ -0,0 +1 @@
+{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; }
diff --git a/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix b/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix
new file mode 100644
index 000000000..0dbe15e63
--- /dev/null
+++ b/tests/functional/lang/eval-okay-dynamic-attrs-bare.nix
@@ -0,0 +1,17 @@
+let
+ aString = "a";
+
+ bString = "b";
+in {
+ hasAttrs = { a.b = null; } ? ${aString}.b;
+
+ selectAttrs = { a.b = true; }.a.${bString};
+
+ selectOrAttrs = { }.${aString} or true;
+
+ binds = { ${aString}."${bString}c" = true; }.a.bc;
+
+ recBinds = rec { ${bString} = a; a = true; }.b;
+
+ multiAttrs = { ${aString} = true; ${bString} = false; }.a;
+}
diff --git a/tests/functional/lang/eval-okay-dynamic-attrs.exp b/tests/functional/lang/eval-okay-dynamic-attrs.exp
new file mode 100644
index 000000000..df8750afc
--- /dev/null
+++ b/tests/functional/lang/eval-okay-dynamic-attrs.exp
@@ -0,0 +1 @@
+{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; }
diff --git a/tests/functional/lang/eval-okay-dynamic-attrs.nix b/tests/functional/lang/eval-okay-dynamic-attrs.nix
new file mode 100644
index 000000000..ee02ac7e6
--- /dev/null
+++ b/tests/functional/lang/eval-okay-dynamic-attrs.nix
@@ -0,0 +1,17 @@
+let
+ aString = "a";
+
+ bString = "b";
+in {
+ hasAttrs = { a.b = null; } ? "${aString}".b;
+
+ selectAttrs = { a.b = true; }.a."${bString}";
+
+ selectOrAttrs = { }."${aString}" or true;
+
+ binds = { "${aString}"."${bString}c" = true; }.a.bc;
+
+ recBinds = rec { "${bString}" = a; a = true; }.b;
+
+ multiAttrs = { "${aString}" = true; "${bString}" = false; }.a;
+}
diff --git a/tests/functional/lang/eval-okay-elem.exp b/tests/functional/lang/eval-okay-elem.exp
new file mode 100644
index 000000000..3cf6c0e96
--- /dev/null
+++ b/tests/functional/lang/eval-okay-elem.exp
@@ -0,0 +1 @@
+[ true false 30 ]
diff --git a/tests/functional/lang/eval-okay-elem.nix b/tests/functional/lang/eval-okay-elem.nix
new file mode 100644
index 000000000..71ea7a4ed
--- /dev/null
+++ b/tests/functional/lang/eval-okay-elem.nix
@@ -0,0 +1,6 @@
+with import ./lib.nix;
+
+let xs = range 10 40; in
+
+[ (builtins.elem 23 xs) (builtins.elem 42 xs) (builtins.elemAt xs 20) ]
+
diff --git a/tests/functional/lang/eval-okay-empty-args.exp b/tests/functional/lang/eval-okay-empty-args.exp
new file mode 100644
index 000000000..cb5537d5d
--- /dev/null
+++ b/tests/functional/lang/eval-okay-empty-args.exp
@@ -0,0 +1 @@
+"ab"
diff --git a/tests/functional/lang/eval-okay-empty-args.nix b/tests/functional/lang/eval-okay-empty-args.nix
new file mode 100644
index 000000000..78c133afd
--- /dev/null
+++ b/tests/functional/lang/eval-okay-empty-args.nix
@@ -0,0 +1 @@
+({}: {x,y,}: "${x}${y}") {} {x = "a"; y = "b";}
diff --git a/tests/functional/lang/eval-okay-eq-derivations.exp b/tests/functional/lang/eval-okay-eq-derivations.exp
new file mode 100644
index 000000000..ec04aab6a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-eq-derivations.exp
@@ -0,0 +1 @@
+[ true true true false ]
diff --git a/tests/functional/lang/eval-okay-eq-derivations.nix b/tests/functional/lang/eval-okay-eq-derivations.nix
new file mode 100644
index 000000000..d526cb4a2
--- /dev/null
+++ b/tests/functional/lang/eval-okay-eq-derivations.nix
@@ -0,0 +1,10 @@
+let
+
+ drvA1 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; };
+ drvA2 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; };
+ drvA3 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; } // { dummy = 1; };
+
+ drvC1 = derivation { name = "c"; builder = "/foo"; system = "i686-linux"; };
+ drvC2 = derivation { name = "c"; builder = "/bar"; system = "i686-linux"; };
+
+in [ (drvA1 == drvA1) (drvA1 == drvA2) (drvA1 == drvA3) (drvC1 == drvC2) ]
diff --git a/tests/functional/lang/eval-okay-eq.exp b/tests/functional/lang/eval-okay-eq.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-eq.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-eq.nix b/tests/functional/lang/eval-okay-eq.nix
new file mode 100644
index 000000000..73d200b38
--- /dev/null
+++ b/tests/functional/lang/eval-okay-eq.nix
@@ -0,0 +1,3 @@
+["foobar" (rec {x = 1; y = x;})]
+==
+[("foo" + "bar") ({x = 1; y = 1;})]
diff --git a/tests/functional/lang/eval-okay-filter.exp b/tests/functional/lang/eval-okay-filter.exp
new file mode 100644
index 000000000..355d51c27
--- /dev/null
+++ b/tests/functional/lang/eval-okay-filter.exp
@@ -0,0 +1 @@
+[ 0 2 4 6 8 10 100 102 104 106 108 110 ]
diff --git a/tests/functional/lang/eval-okay-filter.nix b/tests/functional/lang/eval-okay-filter.nix
new file mode 100644
index 000000000..85109b0d0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-filter.nix
@@ -0,0 +1,5 @@
+with import ./lib.nix;
+
+builtins.filter
+ (x: x / 2 * 2 == x)
+ (builtins.concatLists [ (range 0 10) (range 100 110) ])
diff --git a/tests/functional/lang/eval-okay-flake-ref-to-string.exp b/tests/functional/lang/eval-okay-flake-ref-to-string.exp
new file mode 100644
index 000000000..110f8442d
--- /dev/null
+++ b/tests/functional/lang/eval-okay-flake-ref-to-string.exp
@@ -0,0 +1 @@
+"github:NixOS/nixpkgs/23.05?dir=lib"
diff --git a/tests/functional/lang/eval-okay-flake-ref-to-string.nix b/tests/functional/lang/eval-okay-flake-ref-to-string.nix
new file mode 100644
index 000000000..dbb4e5b2a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-flake-ref-to-string.nix
@@ -0,0 +1,7 @@
+builtins.flakeRefToString {
+ type = "github";
+ owner = "NixOS";
+ repo = "nixpkgs";
+ ref = "23.05";
+ dir = "lib";
+}
diff --git a/tests/functional/lang/eval-okay-flatten.exp b/tests/functional/lang/eval-okay-flatten.exp
new file mode 100644
index 000000000..b979b2b8b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-flatten.exp
@@ -0,0 +1 @@
+"1234567"
diff --git a/tests/functional/lang/eval-okay-flatten.nix b/tests/functional/lang/eval-okay-flatten.nix
new file mode 100644
index 000000000..fe911e968
--- /dev/null
+++ b/tests/functional/lang/eval-okay-flatten.nix
@@ -0,0 +1,8 @@
+with import ./lib.nix;
+
+let {
+
+ l = ["1" "2" ["3" ["4"] ["5" "6"]] "7"];
+
+ body = concat (flatten l);
+}
diff --git a/tests/functional/lang/eval-okay-float.exp b/tests/functional/lang/eval-okay-float.exp
new file mode 100644
index 000000000..3c50a8adc
--- /dev/null
+++ b/tests/functional/lang/eval-okay-float.exp
@@ -0,0 +1 @@
+[ 3.4 3.5 2.5 1.5 ]
diff --git a/tests/functional/lang/eval-okay-float.nix b/tests/functional/lang/eval-okay-float.nix
new file mode 100644
index 000000000..b2702c7b1
--- /dev/null
+++ b/tests/functional/lang/eval-okay-float.nix
@@ -0,0 +1,6 @@
+[
+ (1.1 + 2.3)
+ (builtins.add (0.5 + 0.5) (2.0 + 0.5))
+ ((0.5 + 0.5) * (2.0 + 0.5))
+ ((1.5 + 1.5) / (0.5 * 4.0))
+]
diff --git a/tests/functional/lang/eval-okay-floor-ceil.exp b/tests/functional/lang/eval-okay-floor-ceil.exp
new file mode 100644
index 000000000..81f80420b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-floor-ceil.exp
@@ -0,0 +1 @@
+"23;24;23;23"
diff --git a/tests/functional/lang/eval-okay-floor-ceil.nix b/tests/functional/lang/eval-okay-floor-ceil.nix
new file mode 100644
index 000000000..d76a0d86e
--- /dev/null
+++ b/tests/functional/lang/eval-okay-floor-ceil.nix
@@ -0,0 +1,9 @@
+with import ./lib.nix;
+
+let
+ n1 = builtins.floor 23.5;
+ n2 = builtins.ceil 23.5;
+ n3 = builtins.floor 23;
+ n4 = builtins.ceil 23;
+in
+ builtins.concatStringsSep ";" (map toString [ n1 n2 n3 n4 ])
diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.exp b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.exp
new file mode 100644
index 000000000..d81cc0710
--- /dev/null
+++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.exp
@@ -0,0 +1 @@
+42
diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix
new file mode 100644
index 000000000..c666e07f3
--- /dev/null
+++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-elements.nix
@@ -0,0 +1,9 @@
+# Tests that the rhs argument of op is not forced unconditionally
+let
+ lst = builtins.foldl'
+ (acc: x: acc ++ [ x ])
+ [ ]
+ [ 42 (throw "this shouldn't be evaluated") ];
+in
+
+builtins.head lst
diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp
new file mode 100644
index 000000000..d81cc0710
--- /dev/null
+++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.exp
@@ -0,0 +1 @@
+42
diff --git a/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix
new file mode 100644
index 000000000..abcd5366a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-foldlStrict-lazy-initial-accumulator.nix
@@ -0,0 +1,6 @@
+# Checks that the nul value for the accumulator is not forced unconditionally.
+# Some languages provide a foldl' that is strict in this argument, but Nix does not.
+builtins.foldl'
+ (_: x: x)
+ (throw "This is never forced")
+ [ "but the results of applying op are" 42 ]
diff --git a/tests/functional/lang/eval-okay-foldlStrict.exp b/tests/functional/lang/eval-okay-foldlStrict.exp
new file mode 100644
index 000000000..837e12b40
--- /dev/null
+++ b/tests/functional/lang/eval-okay-foldlStrict.exp
@@ -0,0 +1 @@
+500500
diff --git a/tests/functional/lang/eval-okay-foldlStrict.nix b/tests/functional/lang/eval-okay-foldlStrict.nix
new file mode 100644
index 000000000..3b87188d2
--- /dev/null
+++ b/tests/functional/lang/eval-okay-foldlStrict.nix
@@ -0,0 +1,3 @@
+with import ./lib.nix;
+
+builtins.foldl' (x: y: x + y) 0 (range 1 1000)
diff --git a/tests/functional/lang/eval-okay-fromTOML-timestamps.exp b/tests/functional/lang/eval-okay-fromTOML-timestamps.exp
new file mode 100644
index 000000000..08b3c69a6
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromTOML-timestamps.exp
@@ -0,0 +1 @@
+{ "1234" = "value"; "127.0.0.1" = "value"; a = { b = { c = { }; }; }; arr1 = [ 1 2 3 ]; arr2 = [ "red" "yellow" "green" ]; arr3 = [ [ 1 2 ] [ 3 4 5 ] ]; arr4 = [ "all" "strings" "are the same" "type" ]; arr5 = [ [ 1 2 ] [ "a" "b" "c" ] ]; arr7 = [ 1 2 3 ]; arr8 = [ 1 2 ]; bare-key = "value"; bare_key = "value"; bin1 = 214; bool1 = true; bool2 = false; "character encoding" = "value"; d = { e = { f = { }; }; }; dog = { "tater.man" = { type = { name = "pug"; }; }; }; flt1 = 1; flt2 = 3.1415; flt3 = -0.01; flt4 = 5e+22; flt5 = 1e+06; flt6 = -0.02; flt7 = 6.626e-34; flt8 = 9.22462e+06; fruit = [ { name = "apple"; physical = { color = "red"; shape = "round"; }; variety = [ { name = "red delicious"; } { name = "granny smith"; } ]; } { name = "banana"; variety = [ { name = "plantain"; } ]; } ]; g = { h = { i = { }; }; }; hex1 = 3735928559; hex2 = 3735928559; hex3 = 3735928559; int1 = 99; int2 = 42; int3 = 0; int4 = -17; int5 = 1000; int6 = 5349221; int7 = 12345; j = { "ʞ" = { l = { }; }; }; key = "value"; key2 = "value"; ld1 = { _type = "timestamp"; value = "1979-05-27"; }; ldt1 = { _type = "timestamp"; value = "1979-05-27T07:32:00"; }; ldt2 = { _type = "timestamp"; value = "1979-05-27T00:32:00.999999"; }; lt1 = { _type = "timestamp"; value = "07:32:00"; }; lt2 = { _type = "timestamp"; value = "00:32:00.999999"; }; name = "Orange"; oct1 = 342391; oct2 = 493; odt1 = { _type = "timestamp"; value = "1979-05-27T07:32:00Z"; }; odt2 = { _type = "timestamp"; value = "1979-05-27T00:32:00-07:00"; }; odt3 = { _type = "timestamp"; value = "1979-05-27T00:32:00.999999-07:00"; }; odt4 = { _type = "timestamp"; value = "1979-05-27T07:32:00Z"; }; physical = { color = "orange"; shape = "round"; }; products = [ { name = "Hammer"; sku = 738594937; } { } { color = "gray"; name = "Nail"; sku = 284758393; } ]; "quoted \"value\"" = "value"; site = { "google.com" = true; }; str = "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."; table-1 = { key1 = "some string"; key2 = 123; }; table-2 = { key1 = "another string"; key2 = 456; }; x = { y = { z = { w = { animal = { type = { name = "pug"; }; }; name = { first = "Tom"; last = "Preston-Werner"; }; point = { x = 1; y = 2; }; }; }; }; }; "ʎǝʞ" = "value"; }
diff --git a/tests/functional/lang/eval-okay-fromTOML-timestamps.flags b/tests/functional/lang/eval-okay-fromTOML-timestamps.flags
new file mode 100644
index 000000000..9ed39dc6b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromTOML-timestamps.flags
@@ -0,0 +1 @@
+--extra-experimental-features parse-toml-timestamps
diff --git a/tests/functional/lang/eval-okay-fromTOML-timestamps.nix b/tests/functional/lang/eval-okay-fromTOML-timestamps.nix
new file mode 100644
index 000000000..74cff9470
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromTOML-timestamps.nix
@@ -0,0 +1,130 @@
+builtins.fromTOML ''
+ key = "value"
+ bare_key = "value"
+ bare-key = "value"
+ 1234 = "value"
+
+ "127.0.0.1" = "value"
+ "character encoding" = "value"
+ "ʎǝʞ" = "value"
+ 'key2' = "value"
+ 'quoted "value"' = "value"
+
+ name = "Orange"
+
+ physical.color = "orange"
+ physical.shape = "round"
+ site."google.com" = true
+
+ # This is legal according to the spec, but cpptoml doesn't handle it.
+ #a.b.c = 1
+ #a.d = 2
+
+ str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
+
+ int1 = +99
+ int2 = 42
+ int3 = 0
+ int4 = -17
+ int5 = 1_000
+ int6 = 5_349_221
+ int7 = 1_2_3_4_5
+
+ hex1 = 0xDEADBEEF
+ hex2 = 0xdeadbeef
+ hex3 = 0xdead_beef
+
+ oct1 = 0o01234567
+ oct2 = 0o755
+
+ bin1 = 0b11010110
+
+ flt1 = +1.0
+ flt2 = 3.1415
+ flt3 = -0.01
+ flt4 = 5e+22
+ flt5 = 1e6
+ flt6 = -2E-2
+ flt7 = 6.626e-34
+ flt8 = 9_224_617.445_991_228_313
+
+ bool1 = true
+ bool2 = false
+
+ odt1 = 1979-05-27T07:32:00Z
+ odt2 = 1979-05-27T00:32:00-07:00
+ odt3 = 1979-05-27T00:32:00.999999-07:00
+ odt4 = 1979-05-27 07:32:00Z
+ ldt1 = 1979-05-27T07:32:00
+ ldt2 = 1979-05-27T00:32:00.999999
+ ld1 = 1979-05-27
+ lt1 = 07:32:00
+ lt2 = 00:32:00.999999
+
+ arr1 = [ 1, 2, 3 ]
+ arr2 = [ "red", "yellow", "green" ]
+ arr3 = [ [ 1, 2 ], [3, 4, 5] ]
+ arr4 = [ "all", 'strings', """are the same""", ''''type'''']
+ arr5 = [ [ 1, 2 ], ["a", "b", "c"] ]
+
+ arr7 = [
+ 1, 2, 3
+ ]
+
+ arr8 = [
+ 1,
+ 2, # this is ok
+ ]
+
+ [table-1]
+ key1 = "some string"
+ key2 = 123
+
+
+ [table-2]
+ key1 = "another string"
+ key2 = 456
+
+ [dog."tater.man"]
+ type.name = "pug"
+
+ [a.b.c]
+ [ d.e.f ]
+ [ g . h . i ]
+ [ j . "ʞ" . 'l' ]
+ [x.y.z.w]
+
+ name = { first = "Tom", last = "Preston-Werner" }
+ point = { x = 1, y = 2 }
+ animal = { type.name = "pug" }
+
+ [[products]]
+ name = "Hammer"
+ sku = 738594937
+
+ [[products]]
+
+ [[products]]
+ name = "Nail"
+ sku = 284758393
+ color = "gray"
+
+ [[fruit]]
+ name = "apple"
+
+ [fruit.physical]
+ color = "red"
+ shape = "round"
+
+ [[fruit.variety]]
+ name = "red delicious"
+
+ [[fruit.variety]]
+ name = "granny smith"
+
+ [[fruit]]
+ name = "banana"
+
+ [[fruit.variety]]
+ name = "plantain"
+''
diff --git a/tests/functional/lang/eval-okay-fromTOML.exp b/tests/functional/lang/eval-okay-fromTOML.exp
new file mode 100644
index 000000000..d0dd3af2c
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromTOML.exp
@@ -0,0 +1 @@
+[ { clients = { data = [ [ "gamma" "delta" ] [ 1 2 ] ]; hosts = [ "alpha" "omega" ]; }; database = { connection_max = 5000; enabled = true; ports = [ 8001 8001 8002 ]; server = "192.168.1.1"; }; owner = { name = "Tom Preston-Werner"; }; servers = { alpha = { dc = "eqdc10"; ip = "10.0.0.1"; }; beta = { dc = "eqdc10"; ip = "10.0.0.2"; }; }; title = "TOML Example"; } { "1234" = "value"; "127.0.0.1" = "value"; a = { b = { c = { }; }; }; arr1 = [ 1 2 3 ]; arr2 = [ "red" "yellow" "green" ]; arr3 = [ [ 1 2 ] [ 3 4 5 ] ]; arr4 = [ "all" "strings" "are the same" "type" ]; arr5 = [ [ 1 2 ] [ "a" "b" "c" ] ]; arr7 = [ 1 2 3 ]; arr8 = [ 1 2 ]; bare-key = "value"; bare_key = "value"; bin1 = 214; bool1 = true; bool2 = false; "character encoding" = "value"; d = { e = { f = { }; }; }; dog = { "tater.man" = { type = { name = "pug"; }; }; }; flt1 = 1; flt2 = 3.1415; flt3 = -0.01; flt4 = 5e+22; flt5 = 1e+06; flt6 = -0.02; flt7 = 6.626e-34; flt8 = 9.22462e+06; fruit = [ { name = "apple"; physical = { color = "red"; shape = "round"; }; variety = [ { name = "red delicious"; } { name = "granny smith"; } ]; } { name = "banana"; variety = [ { name = "plantain"; } ]; } ]; g = { h = { i = { }; }; }; hex1 = 3735928559; hex2 = 3735928559; hex3 = 3735928559; int1 = 99; int2 = 42; int3 = 0; int4 = -17; int5 = 1000; int6 = 5349221; int7 = 12345; j = { "ʞ" = { l = { }; }; }; key = "value"; key2 = "value"; name = "Orange"; oct1 = 342391; oct2 = 493; physical = { color = "orange"; shape = "round"; }; products = [ { name = "Hammer"; sku = 738594937; } { } { color = "gray"; name = "Nail"; sku = 284758393; } ]; "quoted \"value\"" = "value"; site = { "google.com" = true; }; str = "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."; table-1 = { key1 = "some string"; key2 = 123; }; table-2 = { key1 = "another string"; key2 = 456; }; x = { y = { z = { w = { animal = { type = { name = "pug"; }; }; name = { first = "Tom"; last = "Preston-Werner"; }; point = { x = 1; y = 2; }; }; }; }; }; "ʎǝʞ" = "value"; } { metadata = { "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"; "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"; "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"; "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"; }; package = [ { dependencies = [ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" ]; name = "aho-corasick"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.6.4"; } { name = "ansi_term"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.9.0"; } { dependencies = [ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" ]; name = "atty"; source = "registry+https://github.com/rust-lang/crates.io-index"; version = "0.2.10"; } ]; } { a = [ [ { b = true; } ] ]; c = [ [ { d = true; } ] ]; e = [ [ 123 ] ]; } ]
diff --git a/tests/functional/lang/eval-okay-fromTOML.nix b/tests/functional/lang/eval-okay-fromTOML.nix
new file mode 100644
index 000000000..963932689
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromTOML.nix
@@ -0,0 +1,208 @@
+[
+
+ (builtins.fromTOML ''
+ # This is a TOML document.
+
+ title = "TOML Example"
+
+ [owner]
+ name = "Tom Preston-Werner"
+ #dob = 1979-05-27T07:32:00-08:00 # First class dates
+
+ [database]
+ server = "192.168.1.1"
+ ports = [ 8001, 8001, 8002 ]
+ connection_max = 5000
+ enabled = true
+
+ [servers]
+
+ # Indentation (tabs and/or spaces) is allowed but not required
+ [servers.alpha]
+ ip = "10.0.0.1"
+ dc = "eqdc10"
+
+ [servers.beta]
+ ip = "10.0.0.2"
+ dc = "eqdc10"
+
+ [clients]
+ data = [ ["gamma", "delta"], [1, 2] ]
+
+ # Line breaks are OK when inside arrays
+ hosts = [
+ "alpha",
+ "omega"
+ ]
+ '')
+
+ (builtins.fromTOML ''
+ key = "value"
+ bare_key = "value"
+ bare-key = "value"
+ 1234 = "value"
+
+ "127.0.0.1" = "value"
+ "character encoding" = "value"
+ "ʎǝʞ" = "value"
+ 'key2' = "value"
+ 'quoted "value"' = "value"
+
+ name = "Orange"
+
+ physical.color = "orange"
+ physical.shape = "round"
+ site."google.com" = true
+
+ # This is legal according to the spec, but cpptoml doesn't handle it.
+ #a.b.c = 1
+ #a.d = 2
+
+ str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
+
+ int1 = +99
+ int2 = 42
+ int3 = 0
+ int4 = -17
+ int5 = 1_000
+ int6 = 5_349_221
+ int7 = 1_2_3_4_5
+
+ hex1 = 0xDEADBEEF
+ hex2 = 0xdeadbeef
+ hex3 = 0xdead_beef
+
+ oct1 = 0o01234567
+ oct2 = 0o755
+
+ bin1 = 0b11010110
+
+ flt1 = +1.0
+ flt2 = 3.1415
+ flt3 = -0.01
+ flt4 = 5e+22
+ flt5 = 1e6
+ flt6 = -2E-2
+ flt7 = 6.626e-34
+ flt8 = 9_224_617.445_991_228_313
+
+ bool1 = true
+ bool2 = false
+
+ # FIXME: not supported because Nix doesn't have a date/time type.
+ #odt1 = 1979-05-27T07:32:00Z
+ #odt2 = 1979-05-27T00:32:00-07:00
+ #odt3 = 1979-05-27T00:32:00.999999-07:00
+ #odt4 = 1979-05-27 07:32:00Z
+ #ldt1 = 1979-05-27T07:32:00
+ #ldt2 = 1979-05-27T00:32:00.999999
+ #ld1 = 1979-05-27
+ #lt1 = 07:32:00
+ #lt2 = 00:32:00.999999
+
+ arr1 = [ 1, 2, 3 ]
+ arr2 = [ "red", "yellow", "green" ]
+ arr3 = [ [ 1, 2 ], [3, 4, 5] ]
+ arr4 = [ "all", 'strings', """are the same""", ''''type'''']
+ arr5 = [ [ 1, 2 ], ["a", "b", "c"] ]
+
+ arr7 = [
+ 1, 2, 3
+ ]
+
+ arr8 = [
+ 1,
+ 2, # this is ok
+ ]
+
+ [table-1]
+ key1 = "some string"
+ key2 = 123
+
+
+ [table-2]
+ key1 = "another string"
+ key2 = 456
+
+ [dog."tater.man"]
+ type.name = "pug"
+
+ [a.b.c]
+ [ d.e.f ]
+ [ g . h . i ]
+ [ j . "ʞ" . 'l' ]
+ [x.y.z.w]
+
+ name = { first = "Tom", last = "Preston-Werner" }
+ point = { x = 1, y = 2 }
+ animal = { type.name = "pug" }
+
+ [[products]]
+ name = "Hammer"
+ sku = 738594937
+
+ [[products]]
+
+ [[products]]
+ name = "Nail"
+ sku = 284758393
+ color = "gray"
+
+ [[fruit]]
+ name = "apple"
+
+ [fruit.physical]
+ color = "red"
+ shape = "round"
+
+ [[fruit.variety]]
+ name = "red delicious"
+
+ [[fruit.variety]]
+ name = "granny smith"
+
+ [[fruit]]
+ name = "banana"
+
+ [[fruit.variety]]
+ name = "plantain"
+ '')
+
+ (builtins.fromTOML ''
+ [[package]]
+ name = "aho-corasick"
+ version = "0.6.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ dependencies = [
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ ]
+
+ [[package]]
+ name = "ansi_term"
+ version = "0.9.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+
+ [[package]]
+ name = "atty"
+ version = "0.2.10"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ dependencies = [
+ "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ ]
+
+ [metadata]
+ "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
+ "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+ "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
+ "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
+ '')
+
+ (builtins.fromTOML ''
+ a = [[{ b = true }]]
+ c = [ [ { d = true } ] ]
+ e = [[123]]
+ '')
+
+]
diff --git a/tests/functional/lang/eval-okay-fromjson-escapes.exp b/tests/functional/lang/eval-okay-fromjson-escapes.exp
new file mode 100644
index 000000000..add5505a8
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromjson-escapes.exp
@@ -0,0 +1 @@
+"quote \" reverse solidus \\ solidus / backspace  formfeed newline \n carriage return \r horizontal tab \t 1 char unicode encoded backspace  1 char unicode encoded e with accent é 2 char unicode encoded s with caron š 3 char unicode encoded rightwards arrow →"
diff --git a/tests/functional/lang/eval-okay-fromjson-escapes.nix b/tests/functional/lang/eval-okay-fromjson-escapes.nix
new file mode 100644
index 000000000..f00713507
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromjson-escapes.nix
@@ -0,0 +1,3 @@
+# This string contains all supported escapes in a JSON string, per json.org
+# \b and \f are not supported by Nix
+builtins.fromJSON ''"quote \" reverse solidus \\ solidus \/ backspace \b formfeed \f newline \n carriage return \r horizontal tab \t 1 char unicode encoded backspace \u0008 1 char unicode encoded e with accent \u00e9 2 char unicode encoded s with caron \u0161 3 char unicode encoded rightwards arrow \u2192"''
diff --git a/tests/functional/lang/eval-okay-fromjson.exp b/tests/functional/lang/eval-okay-fromjson.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromjson.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-fromjson.nix b/tests/functional/lang/eval-okay-fromjson.nix
new file mode 100644
index 000000000..4c526b9ae
--- /dev/null
+++ b/tests/functional/lang/eval-okay-fromjson.nix
@@ -0,0 +1,41 @@
+builtins.fromJSON
+ ''
+ {
+ "Video": {
+ "Title": "The Penguin Chronicles",
+ "Width": 1920,
+ "Height": 1080,
+ "EmbeddedData": [3.14159, 23493,null, true ,false, -10],
+ "Thumb": {
+ "Url": "http://www.example.com/video/5678931",
+ "Width": 200,
+ "Height": 250
+ },
+ "Animated" : false,
+ "IDs": [116, 943, 234, 38793, true ,false,null, -100],
+ "Escapes": "\"\\\/\t\n\r\t",
+ "Subtitle" : false,
+ "Latitude": 37.7668,
+ "Longitude": -122.3959
+ }
+ }
+ ''
+==
+ { Video =
+ { Title = "The Penguin Chronicles";
+ Width = 1920;
+ Height = 1080;
+ EmbeddedData = [ 3.14159 23493 null true false (0-10) ];
+ Thumb =
+ { Url = "http://www.example.com/video/5678931";
+ Width = 200;
+ Height = 250;
+ };
+ Animated = false;
+ IDs = [ 116 943 234 38793 true false null (0-100) ];
+ Escapes = "\"\\\/\t\n\r\t"; # supported in JSON but not Nix: \b\f
+ Subtitle = false;
+ Latitude = 37.7668;
+ Longitude = -122.3959;
+ };
+ }
diff --git a/tests/functional/lang/eval-okay-functionargs.exp b/tests/functional/lang/eval-okay-functionargs.exp
new file mode 100644
index 000000000..c1c9f8ffa
--- /dev/null
+++ b/tests/functional/lang/eval-okay-functionargs.exp
@@ -0,0 +1 @@
+[ "stdenv" "fetchurl" "aterm-stdenv" "aterm-stdenv2" "libX11" "libXv" "mplayer-stdenv2.libXv-libX11" "mplayer-stdenv2.libXv-libX11_2" "nix-stdenv-aterm-stdenv" "nix-stdenv2-aterm2-stdenv2" ]
diff --git a/tests/functional/lang/eval-okay-functionargs.exp.xml b/tests/functional/lang/eval-okay-functionargs.exp.xml
new file mode 100644
index 000000000..651f54c36
--- /dev/null
+++ b/tests/functional/lang/eval-okay-functionargs.exp.xml
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='utf-8'?>
+<expr>
+ <list>
+ <string value="stdenv" />
+ <string value="fetchurl" />
+ <string value="aterm-stdenv" />
+ <string value="aterm-stdenv2" />
+ <string value="libX11" />
+ <string value="libXv" />
+ <string value="mplayer-stdenv2.libXv-libX11" />
+ <string value="mplayer-stdenv2.libXv-libX11_2" />
+ <string value="nix-stdenv-aterm-stdenv" />
+ <string value="nix-stdenv2-aterm2-stdenv2" />
+ </list>
+</expr>
diff --git a/tests/functional/lang/eval-okay-functionargs.nix b/tests/functional/lang/eval-okay-functionargs.nix
new file mode 100644
index 000000000..68dca62ee
--- /dev/null
+++ b/tests/functional/lang/eval-okay-functionargs.nix
@@ -0,0 +1,80 @@
+let
+
+ stdenvFun = { }: { name = "stdenv"; };
+ stdenv2Fun = { }: { name = "stdenv2"; };
+ fetchurlFun = { stdenv }: assert stdenv.name == "stdenv"; { name = "fetchurl"; };
+ atermFun = { stdenv, fetchurl }: { name = "aterm-${stdenv.name}"; };
+ aterm2Fun = { stdenv, fetchurl }: { name = "aterm2-${stdenv.name}"; };
+ nixFun = { stdenv, fetchurl, aterm }: { name = "nix-${stdenv.name}-${aterm.name}"; };
+
+ mplayerFun =
+ { stdenv, fetchurl, enableX11 ? false, xorg ? null, enableFoo ? true, foo ? null }:
+ assert stdenv.name == "stdenv2";
+ assert enableX11 -> xorg.libXv.name == "libXv";
+ assert enableFoo -> foo != null;
+ { name = "mplayer-${stdenv.name}.${xorg.libXv.name}-${xorg.libX11.name}"; };
+
+ makeOverridable = f: origArgs: f origArgs //
+ { override = newArgs:
+ makeOverridable f (origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs));
+ };
+
+ callPackage_ = pkgs: f: args:
+ makeOverridable f ((builtins.intersectAttrs (builtins.functionArgs f) pkgs) // args);
+
+ allPackages =
+ { overrides ? (pkgs: pkgsPrev: { }) }:
+ let
+ callPackage = callPackage_ pkgs;
+ pkgs = pkgsStd // (overrides pkgs pkgsStd);
+ pkgsStd = {
+ inherit pkgs;
+ stdenv = callPackage stdenvFun { };
+ stdenv2 = callPackage stdenv2Fun { };
+ fetchurl = callPackage fetchurlFun { };
+ aterm = callPackage atermFun { };
+ xorg = callPackage xorgFun { };
+ mplayer = callPackage mplayerFun { stdenv = pkgs.stdenv2; enableFoo = false; };
+ nix = callPackage nixFun { };
+ };
+ in pkgs;
+
+ libX11Fun = { stdenv, fetchurl }: { name = "libX11"; };
+ libX11_2Fun = { stdenv, fetchurl }: { name = "libX11_2"; };
+ libXvFun = { stdenv, fetchurl, libX11 }: { name = "libXv"; };
+
+ xorgFun =
+ { pkgs }:
+ let callPackage = callPackage_ (pkgs // pkgs.xorg); in
+ {
+ libX11 = callPackage libX11Fun { };
+ libXv = callPackage libXvFun { };
+ };
+
+in
+
+let
+
+ pkgs = allPackages { };
+
+ pkgs2 = allPackages {
+ overrides = pkgs: pkgsPrev: {
+ stdenv = pkgs.stdenv2;
+ nix = pkgsPrev.nix.override { aterm = aterm2Fun { inherit (pkgs) stdenv fetchurl; }; };
+ xorg = pkgsPrev.xorg // { libX11 = libX11_2Fun { inherit (pkgs) stdenv fetchurl; }; };
+ };
+ };
+
+in
+
+ [ pkgs.stdenv.name
+ pkgs.fetchurl.name
+ pkgs.aterm.name
+ pkgs2.aterm.name
+ pkgs.xorg.libX11.name
+ pkgs.xorg.libXv.name
+ pkgs.mplayer.name
+ pkgs2.mplayer.name
+ pkgs.nix.name
+ pkgs2.nix.name
+ ]
diff --git a/tests/functional/lang/eval-okay-getattrpos-functionargs.exp b/tests/functional/lang/eval-okay-getattrpos-functionargs.exp
new file mode 100644
index 000000000..7f9ac40e8
--- /dev/null
+++ b/tests/functional/lang/eval-okay-getattrpos-functionargs.exp
@@ -0,0 +1 @@
+{ column = 11; file = "eval-okay-getattrpos-functionargs.nix"; line = 2; }
diff --git a/tests/functional/lang/eval-okay-getattrpos-functionargs.nix b/tests/functional/lang/eval-okay-getattrpos-functionargs.nix
new file mode 100644
index 000000000..11d6bb0e3
--- /dev/null
+++ b/tests/functional/lang/eval-okay-getattrpos-functionargs.nix
@@ -0,0 +1,4 @@
+let
+ fun = { foo }: {};
+ pos = builtins.unsafeGetAttrPos "foo" (builtins.functionArgs fun);
+in { inherit (pos) column line; file = baseNameOf pos.file; }
diff --git a/tests/functional/lang/eval-okay-getattrpos-undefined.exp b/tests/functional/lang/eval-okay-getattrpos-undefined.exp
new file mode 100644
index 000000000..19765bd50
--- /dev/null
+++ b/tests/functional/lang/eval-okay-getattrpos-undefined.exp
@@ -0,0 +1 @@
+null
diff --git a/tests/functional/lang/eval-okay-getattrpos-undefined.nix b/tests/functional/lang/eval-okay-getattrpos-undefined.nix
new file mode 100644
index 000000000..14dd38f77
--- /dev/null
+++ b/tests/functional/lang/eval-okay-getattrpos-undefined.nix
@@ -0,0 +1 @@
+builtins.unsafeGetAttrPos "abort" builtins
diff --git a/tests/functional/lang/eval-okay-getattrpos.exp b/tests/functional/lang/eval-okay-getattrpos.exp
new file mode 100644
index 000000000..469249bbc
--- /dev/null
+++ b/tests/functional/lang/eval-okay-getattrpos.exp
@@ -0,0 +1 @@
+{ column = 5; file = "eval-okay-getattrpos.nix"; line = 3; }
diff --git a/tests/functional/lang/eval-okay-getattrpos.nix b/tests/functional/lang/eval-okay-getattrpos.nix
new file mode 100644
index 000000000..ca6b07961
--- /dev/null
+++ b/tests/functional/lang/eval-okay-getattrpos.nix
@@ -0,0 +1,6 @@
+let
+ as = {
+ foo = "bar";
+ };
+ pos = builtins.unsafeGetAttrPos "foo" as;
+in { inherit (pos) column line; file = baseNameOf pos.file; }
diff --git a/tests/functional/lang/eval-okay-getenv.exp b/tests/functional/lang/eval-okay-getenv.exp
new file mode 100644
index 000000000..14e24d419
--- /dev/null
+++ b/tests/functional/lang/eval-okay-getenv.exp
@@ -0,0 +1 @@
+"foobar"
diff --git a/tests/functional/lang/eval-okay-getenv.nix b/tests/functional/lang/eval-okay-getenv.nix
new file mode 100644
index 000000000..4cfec5f55
--- /dev/null
+++ b/tests/functional/lang/eval-okay-getenv.nix
@@ -0,0 +1 @@
+builtins.getEnv "TEST_VAR" + (if builtins.getEnv "NO_SUCH_VAR" == "" then "bar" else "bla")
diff --git a/tests/functional/lang/eval-okay-groupBy.exp b/tests/functional/lang/eval-okay-groupBy.exp
new file mode 100644
index 000000000..bfca5652a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-groupBy.exp
@@ -0,0 +1 @@
+{ "1" = [ 9 ]; "2" = [ 8 ]; "3" = [ 13 29 ]; "4" = [ 3 4 10 11 17 18 ]; "5" = [ 0 23 26 28 ]; "6" = [ 1 12 21 27 30 ]; "7" = [ 7 22 ]; "8" = [ 14 ]; "9" = [ 19 ]; b = [ 16 25 ]; c = [ 24 ]; d = [ 2 ]; e = [ 5 6 15 31 ]; f = [ 20 ]; }
diff --git a/tests/functional/lang/eval-okay-groupBy.nix b/tests/functional/lang/eval-okay-groupBy.nix
new file mode 100644
index 000000000..862d89dbd
--- /dev/null
+++ b/tests/functional/lang/eval-okay-groupBy.nix
@@ -0,0 +1,5 @@
+with import ./lib.nix;
+
+builtins.groupBy (n:
+ builtins.substring 0 1 (builtins.hashString "sha256" (toString n))
+) (range 0 31)
diff --git a/tests/functional/lang/eval-okay-hash.exp b/tests/functional/lang/eval-okay-hash.exp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/functional/lang/eval-okay-hash.exp
diff --git a/tests/functional/lang/eval-okay-hashfile.exp b/tests/functional/lang/eval-okay-hashfile.exp
new file mode 100644
index 000000000..ff1e8293e
--- /dev/null
+++ b/tests/functional/lang/eval-okay-hashfile.exp
@@ -0,0 +1 @@
+[ "d3b07384d113edec49eaa6238ad5ff00" "0f343b0931126a20f133d67c2b018a3b" "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" "60cacbf3d72e1e7834203da608037b1bf83b40e8" "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" "5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" "0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6" "8efb4f73c5655351c444eb109230c556d39e2c7624e9c11abc9e3fb4b9b9254218cc5085b454a9698d085cfa92198491f07a723be4574adc70617b73eb0b6461" ]
diff --git a/tests/functional/lang/eval-okay-hashfile.nix b/tests/functional/lang/eval-okay-hashfile.nix
new file mode 100644
index 000000000..aff5a1856
--- /dev/null
+++ b/tests/functional/lang/eval-okay-hashfile.nix
@@ -0,0 +1,4 @@
+let
+ paths = [ ./data ./binary-data ];
+in
+ builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"])
diff --git a/tests/functional/lang/eval-okay-hashstring.exp b/tests/functional/lang/eval-okay-hashstring.exp
new file mode 100644
index 000000000..d720a082d
--- /dev/null
+++ b/tests/functional/lang/eval-okay-hashstring.exp
@@ -0,0 +1 @@
+[ "d41d8cd98f00b204e9800998ecf8427e" "6c69ee7f211c640419d5366cc076ae46" "bb3438fbabd460ea6dbd27d153e2233b" "da39a3ee5e6b4b0d3255bfef95601890afd80709" "cd54e8568c1b37cf1e5badb0779bcbf382212189" "6d12e10b1d331dad210e47fd25d4f260802b7e77" "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" "900a4469df00ccbfd0c145c6d1e4b7953dd0afafadd7534e3a4019e8d38fc663" "ad0387b3bd8652f730ca46d25f9c170af0fd589f42e7f23f5a9e6412d97d7e56" "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" "9d0886f8c6b389398a16257bc79780fab9831c7fc11c8ab07fa732cb7b348feade382f92617c9c5305fefba0af02ab5fd39a587d330997ff5bd0db19f7666653" "21644b72aa259e5a588cd3afbafb1d4310f4889680f6c83b9d531596a5a284f34dbebff409d23bcc86aee6bad10c891606f075c6f4755cb536da27db5693f3a7" ]
diff --git a/tests/functional/lang/eval-okay-hashstring.nix b/tests/functional/lang/eval-okay-hashstring.nix
new file mode 100644
index 000000000..b0f62b245
--- /dev/null
+++ b/tests/functional/lang/eval-okay-hashstring.nix
@@ -0,0 +1,4 @@
+let
+ strings = [ "" "text 1" "text 2" ];
+in
+ builtins.concatLists (map (hash: map (builtins.hashString hash) strings) ["md5" "sha1" "sha256" "sha512"])
diff --git a/tests/functional/lang/eval-okay-if.exp b/tests/functional/lang/eval-okay-if.exp
new file mode 100644
index 000000000..00750edc0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-if.exp
@@ -0,0 +1 @@
+3
diff --git a/tests/functional/lang/eval-okay-if.nix b/tests/functional/lang/eval-okay-if.nix
new file mode 100644
index 000000000..23e4c74d5
--- /dev/null
+++ b/tests/functional/lang/eval-okay-if.nix
@@ -0,0 +1 @@
+if "foo" != "f" + "oo" then 1 else if false then 2 else 3
diff --git a/tests/functional/lang/eval-okay-import.exp b/tests/functional/lang/eval-okay-import.exp
new file mode 100644
index 000000000..c508125b5
--- /dev/null
+++ b/tests/functional/lang/eval-okay-import.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 5 6 7 8 9 10 ]
diff --git a/tests/functional/lang/eval-okay-import.nix b/tests/functional/lang/eval-okay-import.nix
new file mode 100644
index 000000000..0b18d9413
--- /dev/null
+++ b/tests/functional/lang/eval-okay-import.nix
@@ -0,0 +1,11 @@
+let
+
+ overrides = {
+ import = fn: scopedImport overrides fn;
+
+ scopedImport = attrs: fn: scopedImport (overrides // attrs) fn;
+
+ builtins = builtins // overrides;
+ } // import ./lib.nix;
+
+in scopedImport overrides ./imported.nix
diff --git a/tests/functional/lang/eval-okay-ind-string.exp b/tests/functional/lang/eval-okay-ind-string.exp
new file mode 100644
index 000000000..7862331fa
--- /dev/null
+++ b/tests/functional/lang/eval-okay-ind-string.exp
@@ -0,0 +1 @@
+"This is an indented multi-line string\nliteral. An amount of whitespace at\nthe start of each line matching the minimum\nindentation of all lines in the string\nliteral together will be removed. Thus,\nin this case four spaces will be\nstripped from each line, even though\n THIS LINE is indented six spaces.\n\nAlso, empty lines don't count in the\ndetermination of the indentation level (the\nprevious empty line has indentation 0, but\nit doesn't matter).\nIf the string starts with whitespace\n followed by a newline, it's stripped, but\n that's not the case here. Two spaces are\n stripped because of the \" \" at the start. \nThis line is indented\na bit further.\nAnti-quotations, like so, are\nalso allowed.\n The \\ is not special here.\n' can be followed by any character except another ', e.g. 'x'.\nLikewise for $, e.g. $$ or $varName.\nBut ' followed by ' is special, as is $ followed by {.\nIf you want them, use anti-quotations: '', \${.\n Tabs are not interpreted as whitespace (since we can't guess\n what tab settings are intended), so don't use them.\n\tThis line starts with a space and a tab, so only one\n space will be stripped from each line.\nAlso note that if the last line (just before the closing ' ')\nconsists only of whitespace, it's ignored. But here there is\nsome non-whitespace stuff, so the line isn't removed. \nThis shows a hacky way to preserve an empty line after the start.\nBut there's no reason to do so: you could just repeat the empty\nline.\n Similarly you can force an indentation level,\n in this case to 2 spaces. This works because the anti-quote\n is significant (not whitespace).\nstart on network-interfaces\n\nstart script\n\n rm -f /var/run/opengl-driver\n ln -sf 123 /var/run/opengl-driver\n\n rm -f /var/log/slim.log\n \nend script\n\nenv SLIM_CFGFILE=abc\nenv SLIM_THEMESDIR=def\nenv FONTCONFIG_FILE=/etc/fonts/fonts.conf \t\t\t\t# !!! cleanup\nenv XKB_BINDIR=foo/bin \t\t\t\t# Needed for the Xkb extension.\nenv LD_LIBRARY_PATH=libX11/lib:libXext/lib:/usr/lib/ # related to xorg-sys-opengl - needed to load libglx for (AI)GLX support (for compiz)\n\nenv XORG_DRI_DRIVER_PATH=nvidiaDrivers/X11R6/lib/modules/drivers/ \n\nexec slim/bin/slim\nEscaping of ' followed by ': ''\nEscaping of $ followed by {: \${\nAnd finally to interpret \\n etc. as in a string: \n, \r, \t.\nfoo\n'bla'\nbar\ncut -d $'\\t' -f 1\nending dollar $$\n"
diff --git a/tests/functional/lang/eval-okay-ind-string.nix b/tests/functional/lang/eval-okay-ind-string.nix
new file mode 100644
index 000000000..95d59b508
--- /dev/null
+++ b/tests/functional/lang/eval-okay-ind-string.nix
@@ -0,0 +1,128 @@
+let
+
+ s1 = ''
+ This is an indented multi-line string
+ literal. An amount of whitespace at
+ the start of each line matching the minimum
+ indentation of all lines in the string
+ literal together will be removed. Thus,
+ in this case four spaces will be
+ stripped from each line, even though
+ THIS LINE is indented six spaces.
+
+ Also, empty lines don't count in the
+ determination of the indentation level (the
+ previous empty line has indentation 0, but
+ it doesn't matter).
+ '';
+
+ s2 = '' If the string starts with whitespace
+ followed by a newline, it's stripped, but
+ that's not the case here. Two spaces are
+ stripped because of the " " at the start.
+ '';
+
+ s3 = ''
+ This line is indented
+ a bit further.
+ ''; # indentation of last line doesn't count if it's empty
+
+ s4 = ''
+ Anti-quotations, like ${if true then "so" else "not so"}, are
+ also allowed.
+ '';
+
+ s5 = ''
+ The \ is not special here.
+ ' can be followed by any character except another ', e.g. 'x'.
+ Likewise for $, e.g. $$ or $varName.
+ But ' followed by ' is special, as is $ followed by {.
+ If you want them, use anti-quotations: ${"''"}, ${"\${"}.
+ '';
+
+ s6 = ''
+ Tabs are not interpreted as whitespace (since we can't guess
+ what tab settings are intended), so don't use them.
+ This line starts with a space and a tab, so only one
+ space will be stripped from each line.
+ '';
+
+ s7 = ''
+ Also note that if the last line (just before the closing ' ')
+ consists only of whitespace, it's ignored. But here there is
+ some non-whitespace stuff, so the line isn't removed. '';
+
+ s8 = '' ${""}
+ This shows a hacky way to preserve an empty line after the start.
+ But there's no reason to do so: you could just repeat the empty
+ line.
+ '';
+
+ s9 = ''
+ ${""} Similarly you can force an indentation level,
+ in this case to 2 spaces. This works because the anti-quote
+ is significant (not whitespace).
+ '';
+
+ s10 = ''
+ '';
+
+ s11 = '''';
+
+ s12 = '' '';
+
+ s13 = ''
+ start on network-interfaces
+
+ start script
+
+ rm -f /var/run/opengl-driver
+ ${if true
+ then "ln -sf 123 /var/run/opengl-driver"
+ else if true
+ then "ln -sf 456 /var/run/opengl-driver"
+ else ""
+ }
+
+ rm -f /var/log/slim.log
+
+ end script
+
+ env SLIM_CFGFILE=${"abc"}
+ env SLIM_THEMESDIR=${"def"}
+ env FONTCONFIG_FILE=/etc/fonts/fonts.conf # !!! cleanup
+ env XKB_BINDIR=${"foo"}/bin # Needed for the Xkb extension.
+ env LD_LIBRARY_PATH=${"libX11"}/lib:${"libXext"}/lib:/usr/lib/ # related to xorg-sys-opengl - needed to load libglx for (AI)GLX support (for compiz)
+
+ ${if true
+ then "env XORG_DRI_DRIVER_PATH=${"nvidiaDrivers"}/X11R6/lib/modules/drivers/"
+ else if true
+ then "env XORG_DRI_DRIVER_PATH=${"mesa"}/lib/modules/dri"
+ else ""
+ }
+
+ exec ${"slim"}/bin/slim
+ '';
+
+ s14 = ''
+ Escaping of ' followed by ': '''
+ Escaping of $ followed by {: ''${
+ And finally to interpret \n etc. as in a string: ''\n, ''\r, ''\t.
+ '';
+
+ # Regression test: string interpolation in '${x}' should work, but didn't.
+ s15 = let x = "bla"; in ''
+ foo
+ '${x}'
+ bar
+ '';
+
+ # Regression test: accept $'.
+ s16 = ''
+ cut -d $'\t' -f 1
+ '';
+
+ # Accept dollars at end of strings
+ s17 = ''ending dollar $'' + ''$'' + "\n";
+
+in s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 + s16 + s17
diff --git a/tests/functional/lang/eval-okay-intersectAttrs.exp b/tests/functional/lang/eval-okay-intersectAttrs.exp
new file mode 100644
index 000000000..50445bc0e
--- /dev/null
+++ b/tests/functional/lang/eval-okay-intersectAttrs.exp
@@ -0,0 +1 @@
+[ { } { a = 1; } { a = 1; } { a = "a"; } { m = 1; } { m = "m"; } { n = 1; } { n = "n"; } { n = 1; p = 2; } { n = "n"; p = "p"; } { n = 1; p = 2; } { n = "n"; p = "p"; } { a = "a"; b = "b"; c = "c"; d = "d"; e = "e"; f = "f"; g = "g"; h = "h"; i = "i"; j = "j"; k = "k"; l = "l"; m = "m"; n = "n"; o = "o"; p = "p"; q = "q"; r = "r"; s = "s"; t = "t"; u = "u"; v = "v"; w = "w"; x = "x"; y = "y"; z = "z"; } true ]
diff --git a/tests/functional/lang/eval-okay-intersectAttrs.nix b/tests/functional/lang/eval-okay-intersectAttrs.nix
new file mode 100644
index 000000000..39d49938c
--- /dev/null
+++ b/tests/functional/lang/eval-okay-intersectAttrs.nix
@@ -0,0 +1,50 @@
+let
+ alphabet =
+ { a = "a";
+ b = "b";
+ c = "c";
+ d = "d";
+ e = "e";
+ f = "f";
+ g = "g";
+ h = "h";
+ i = "i";
+ j = "j";
+ k = "k";
+ l = "l";
+ m = "m";
+ n = "n";
+ o = "o";
+ p = "p";
+ q = "q";
+ r = "r";
+ s = "s";
+ t = "t";
+ u = "u";
+ v = "v";
+ w = "w";
+ x = "x";
+ y = "y";
+ z = "z";
+ };
+ foo = {
+ inherit (alphabet) f o b a r z q u x;
+ aa = throw "aa";
+ };
+ alphabetFail = builtins.mapAttrs throw alphabet;
+in
+[ (builtins.intersectAttrs { a = abort "l1"; } { b = abort "r1"; })
+ (builtins.intersectAttrs { a = abort "l2"; } { a = 1; })
+ (builtins.intersectAttrs alphabetFail { a = 1; })
+ (builtins.intersectAttrs { a = abort "laa"; } alphabet)
+ (builtins.intersectAttrs alphabetFail { m = 1; })
+ (builtins.intersectAttrs { m = abort "lam"; } alphabet)
+ (builtins.intersectAttrs alphabetFail { n = 1; })
+ (builtins.intersectAttrs { n = abort "lan"; } alphabet)
+ (builtins.intersectAttrs alphabetFail { n = 1; p = 2; })
+ (builtins.intersectAttrs { n = abort "lan2"; p = abort "lap"; } alphabet)
+ (builtins.intersectAttrs alphabetFail { n = 1; p = 2; })
+ (builtins.intersectAttrs { n = abort "lan2"; p = abort "lap"; } alphabet)
+ (builtins.intersectAttrs alphabetFail alphabet)
+ (builtins.intersectAttrs alphabet foo == builtins.intersectAttrs foo alphabet)
+]
diff --git a/tests/functional/lang/eval-okay-let.exp b/tests/functional/lang/eval-okay-let.exp
new file mode 100644
index 000000000..14e24d419
--- /dev/null
+++ b/tests/functional/lang/eval-okay-let.exp
@@ -0,0 +1 @@
+"foobar"
diff --git a/tests/functional/lang/eval-okay-let.nix b/tests/functional/lang/eval-okay-let.nix
new file mode 100644
index 000000000..fe118c528
--- /dev/null
+++ b/tests/functional/lang/eval-okay-let.nix
@@ -0,0 +1,5 @@
+let {
+ x = "foo";
+ y = "bar";
+ body = x + y;
+}
diff --git a/tests/functional/lang/eval-okay-list.exp b/tests/functional/lang/eval-okay-list.exp
new file mode 100644
index 000000000..f784f26d8
--- /dev/null
+++ b/tests/functional/lang/eval-okay-list.exp
@@ -0,0 +1 @@
+"foobarblatest"
diff --git a/tests/functional/lang/eval-okay-list.nix b/tests/functional/lang/eval-okay-list.nix
new file mode 100644
index 000000000..d433bcf90
--- /dev/null
+++ b/tests/functional/lang/eval-okay-list.nix
@@ -0,0 +1,7 @@
+with import ./lib.nix;
+
+let {
+
+ body = concat ["foo" "bar" "bla" "test"];
+
+} \ No newline at end of file
diff --git a/tests/functional/lang/eval-okay-listtoattrs.exp b/tests/functional/lang/eval-okay-listtoattrs.exp
new file mode 100644
index 000000000..74abef7bc
--- /dev/null
+++ b/tests/functional/lang/eval-okay-listtoattrs.exp
@@ -0,0 +1 @@
+"AAbar"
diff --git a/tests/functional/lang/eval-okay-listtoattrs.nix b/tests/functional/lang/eval-okay-listtoattrs.nix
new file mode 100644
index 000000000..4186e029b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-listtoattrs.nix
@@ -0,0 +1,11 @@
+# this test shows how to use listToAttrs and that evaluation is still lazy (throw isn't called)
+with import ./lib.nix;
+
+let
+ asi = name: value : { inherit name value; };
+ list = [ ( asi "a" "A" ) ( asi "b" "B" ) ];
+ a = builtins.listToAttrs list;
+ b = builtins.listToAttrs ( list ++ list );
+ r = builtins.listToAttrs [ (asi "result" [ a b ]) ( asi "throw" (throw "this should not be thrown")) ];
+ x = builtins.listToAttrs [ (asi "foo" "bar") (asi "foo" "bla") ];
+in concat (map (x: x.a) r.result) + x.foo
diff --git a/tests/functional/lang/eval-okay-logic.exp b/tests/functional/lang/eval-okay-logic.exp
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/functional/lang/eval-okay-logic.exp
@@ -0,0 +1 @@
+1
diff --git a/tests/functional/lang/eval-okay-logic.nix b/tests/functional/lang/eval-okay-logic.nix
new file mode 100644
index 000000000..fbb127944
--- /dev/null
+++ b/tests/functional/lang/eval-okay-logic.nix
@@ -0,0 +1 @@
+assert !false && (true || false) -> true; 1
diff --git a/tests/functional/lang/eval-okay-map.exp b/tests/functional/lang/eval-okay-map.exp
new file mode 100644
index 000000000..dbb64f717
--- /dev/null
+++ b/tests/functional/lang/eval-okay-map.exp
@@ -0,0 +1 @@
+"foobarblabarxyzzybar"
diff --git a/tests/functional/lang/eval-okay-map.nix b/tests/functional/lang/eval-okay-map.nix
new file mode 100644
index 000000000..a76c1d811
--- /dev/null
+++ b/tests/functional/lang/eval-okay-map.nix
@@ -0,0 +1,3 @@
+with import ./lib.nix;
+
+concat (map (x: x + "bar") [ "foo" "bla" "xyzzy" ]) \ No newline at end of file
diff --git a/tests/functional/lang/eval-okay-mapattrs.exp b/tests/functional/lang/eval-okay-mapattrs.exp
new file mode 100644
index 000000000..3f113f17b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-mapattrs.exp
@@ -0,0 +1 @@
+{ x = "x-foo"; y = "y-bar"; }
diff --git a/tests/functional/lang/eval-okay-mapattrs.nix b/tests/functional/lang/eval-okay-mapattrs.nix
new file mode 100644
index 000000000..f075b6275
--- /dev/null
+++ b/tests/functional/lang/eval-okay-mapattrs.nix
@@ -0,0 +1,3 @@
+with import ./lib.nix;
+
+builtins.mapAttrs (name: value: name + "-" + value) { x = "foo"; y = "bar"; }
diff --git a/tests/functional/lang/eval-okay-merge-dynamic-attrs.exp b/tests/functional/lang/eval-okay-merge-dynamic-attrs.exp
new file mode 100644
index 000000000..157d677ce
--- /dev/null
+++ b/tests/functional/lang/eval-okay-merge-dynamic-attrs.exp
@@ -0,0 +1 @@
+{ set1 = { a = 1; b = 2; }; set2 = { a = 1; b = 2; }; set3 = { a = 1; b = 2; }; set4 = { a = 1; b = 2; }; }
diff --git a/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix b/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix
new file mode 100644
index 000000000..f459a554f
--- /dev/null
+++ b/tests/functional/lang/eval-okay-merge-dynamic-attrs.nix
@@ -0,0 +1,13 @@
+{
+ set1 = { a = 1; };
+ set1 = { "${"b" + ""}" = 2; };
+
+ set2 = { "${"b" + ""}" = 2; };
+ set2 = { a = 1; };
+
+ set3.a = 1;
+ set3."${"b" + ""}" = 2;
+
+ set4."${"b" + ""}" = 2;
+ set4.a = 1;
+}
diff --git a/tests/functional/lang/eval-okay-nested-with.exp b/tests/functional/lang/eval-okay-nested-with.exp
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/tests/functional/lang/eval-okay-nested-with.exp
@@ -0,0 +1 @@
+2
diff --git a/tests/functional/lang/eval-okay-nested-with.nix b/tests/functional/lang/eval-okay-nested-with.nix
new file mode 100644
index 000000000..ba9d79aa7
--- /dev/null
+++ b/tests/functional/lang/eval-okay-nested-with.nix
@@ -0,0 +1,3 @@
+with { x = 1; };
+with { x = 2; };
+x
diff --git a/tests/functional/lang/eval-okay-new-let.exp b/tests/functional/lang/eval-okay-new-let.exp
new file mode 100644
index 000000000..f98b38807
--- /dev/null
+++ b/tests/functional/lang/eval-okay-new-let.exp
@@ -0,0 +1 @@
+"xyzzyfoobar"
diff --git a/tests/functional/lang/eval-okay-new-let.nix b/tests/functional/lang/eval-okay-new-let.nix
new file mode 100644
index 000000000..738123141
--- /dev/null
+++ b/tests/functional/lang/eval-okay-new-let.nix
@@ -0,0 +1,14 @@
+let
+
+ f = z:
+
+ let
+ x = "foo";
+ y = "bar";
+ body = 1; # compat test
+ in
+ z + x + y;
+
+ arg = "xyzzy";
+
+in f arg
diff --git a/tests/functional/lang/eval-okay-null-dynamic-attrs.exp b/tests/functional/lang/eval-okay-null-dynamic-attrs.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-null-dynamic-attrs.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-null-dynamic-attrs.nix b/tests/functional/lang/eval-okay-null-dynamic-attrs.nix
new file mode 100644
index 000000000..b060c0bc9
--- /dev/null
+++ b/tests/functional/lang/eval-okay-null-dynamic-attrs.nix
@@ -0,0 +1 @@
+{ ${null} = true; } == {}
diff --git a/tests/functional/lang/eval-okay-overrides.exp b/tests/functional/lang/eval-okay-overrides.exp
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/tests/functional/lang/eval-okay-overrides.exp
@@ -0,0 +1 @@
+2
diff --git a/tests/functional/lang/eval-okay-overrides.nix b/tests/functional/lang/eval-okay-overrides.nix
new file mode 100644
index 000000000..719bdc9c0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-overrides.nix
@@ -0,0 +1,9 @@
+let
+
+ overrides = { a = 2; b = 3; };
+
+in (rec {
+ __overrides = overrides;
+ x = a;
+ a = 1;
+}).x
diff --git a/tests/functional/lang/eval-okay-parse-flake-ref.exp b/tests/functional/lang/eval-okay-parse-flake-ref.exp
new file mode 100644
index 000000000..fc17ba085
--- /dev/null
+++ b/tests/functional/lang/eval-okay-parse-flake-ref.exp
@@ -0,0 +1 @@
+{ dir = "lib"; owner = "NixOS"; ref = "23.05"; repo = "nixpkgs"; type = "github"; }
diff --git a/tests/functional/lang/eval-okay-parse-flake-ref.nix b/tests/functional/lang/eval-okay-parse-flake-ref.nix
new file mode 100644
index 000000000..db4ed2742
--- /dev/null
+++ b/tests/functional/lang/eval-okay-parse-flake-ref.nix
@@ -0,0 +1 @@
+ builtins.parseFlakeRef "github:NixOS/nixpkgs/23.05?dir=lib"
diff --git a/tests/functional/lang/eval-okay-partition.exp b/tests/functional/lang/eval-okay-partition.exp
new file mode 100644
index 000000000..cd8b8b020
--- /dev/null
+++ b/tests/functional/lang/eval-okay-partition.exp
@@ -0,0 +1 @@
+{ right = [ 0 2 4 6 8 10 100 102 104 106 108 110 ]; wrong = [ 1 3 5 7 9 101 103 105 107 109 ]; }
diff --git a/tests/functional/lang/eval-okay-partition.nix b/tests/functional/lang/eval-okay-partition.nix
new file mode 100644
index 000000000..846d2ce49
--- /dev/null
+++ b/tests/functional/lang/eval-okay-partition.nix
@@ -0,0 +1,5 @@
+with import ./lib.nix;
+
+builtins.partition
+ (x: x / 2 * 2 == x)
+ (builtins.concatLists [ (range 0 10) (range 100 110) ])
diff --git a/tests/functional/lang/eval-okay-path-string-interpolation.exp b/tests/functional/lang/eval-okay-path-string-interpolation.exp
new file mode 100644
index 000000000..5b8ea0243
--- /dev/null
+++ b/tests/functional/lang/eval-okay-path-string-interpolation.exp
@@ -0,0 +1 @@
+{ absolute = /foo; expr = /pwd/lang/foo/bar; home = /fake-home/foo; notfirst = /pwd/lang/bar/foo; simple = /pwd/lang/foo; slashes = /foo/bar; surrounded = /pwd/lang/a-foo-b; }
diff --git a/tests/functional/lang/eval-okay-path-string-interpolation.nix b/tests/functional/lang/eval-okay-path-string-interpolation.nix
new file mode 100644
index 000000000..497d7c1c7
--- /dev/null
+++ b/tests/functional/lang/eval-okay-path-string-interpolation.nix
@@ -0,0 +1,12 @@
+let
+ foo = "foo";
+in
+{
+ simple = ./${foo};
+ surrounded = ./a-${foo}-b;
+ absolute = /${foo};
+ expr = ./${foo + "/bar"};
+ home = ~/${foo};
+ notfirst = ./bar/${foo};
+ slashes = /${foo}/${"bar"};
+}
diff --git a/tests/functional/lang/eval-okay-path.exp b/tests/functional/lang/eval-okay-path.exp
new file mode 100644
index 000000000..3ce7f8283
--- /dev/null
+++ b/tests/functional/lang/eval-okay-path.exp
@@ -0,0 +1 @@
+"/nix/store/ya937r4ydw0l6kayq8jkyqaips9c75jm-output"
diff --git a/tests/functional/lang/eval-okay-path.nix b/tests/functional/lang/eval-okay-path.nix
new file mode 100644
index 000000000..e67168cf3
--- /dev/null
+++ b/tests/functional/lang/eval-okay-path.nix
@@ -0,0 +1,7 @@
+builtins.path
+ { path = ./.;
+ filter = path: _: baseNameOf path == "data";
+ recursive = true;
+ sha256 = "1yhm3gwvg5a41yylymgblsclk95fs6jy72w0wv925mmidlhcq4sw";
+ name = "output";
+ }
diff --git a/tests/functional/lang/eval-okay-pathexists.exp b/tests/functional/lang/eval-okay-pathexists.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-pathexists.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-pathexists.nix b/tests/functional/lang/eval-okay-pathexists.nix
new file mode 100644
index 000000000..c5e7a62de
--- /dev/null
+++ b/tests/functional/lang/eval-okay-pathexists.nix
@@ -0,0 +1,29 @@
+builtins.pathExists (./lib.nix)
+&& builtins.pathExists (builtins.toPath ./lib.nix)
+&& builtins.pathExists (builtins.toString ./lib.nix)
+&& !builtins.pathExists (builtins.toString ./lib.nix + "/")
+&& !builtins.pathExists (builtins.toString ./lib.nix + "/.")
+# FIXME
+# && !builtins.pathExists (builtins.toString ./lib.nix + "/..")
+# && !builtins.pathExists (builtins.toString ./lib.nix + "/a/..")
+# && !builtins.pathExists (builtins.toString ./lib.nix + "/../lib.nix")
+&& !builtins.pathExists (builtins.toString ./lib.nix + "/./")
+&& !builtins.pathExists (builtins.toString ./lib.nix + "/./.")
+&& builtins.pathExists (builtins.toString ./.. + "/lang/lib.nix")
+&& !builtins.pathExists (builtins.toString ./.. + "lang/lib.nix")
+&& builtins.pathExists (builtins.toString ./. + "/../lang/lib.nix")
+&& builtins.pathExists (builtins.toString ./. + "/../lang/./lib.nix")
+&& builtins.pathExists (builtins.toString ./.)
+&& builtins.pathExists (builtins.toString ./. + "/")
+&& builtins.pathExists (builtins.toString ./. + "/../lang")
+&& builtins.pathExists (builtins.toString ./. + "/../lang/")
+&& builtins.pathExists (builtins.toString ./. + "/../lang/.")
+&& builtins.pathExists (builtins.toString ./. + "/../lang/./")
+&& builtins.pathExists (builtins.toString ./. + "/../lang//./")
+&& builtins.pathExists (builtins.toString ./. + "/../lang/..")
+&& builtins.pathExists (builtins.toString ./. + "/../lang/../")
+&& builtins.pathExists (builtins.toString ./. + "/../lang/..//")
+&& builtins.pathExists (builtins.toPath (builtins.toString ./lib.nix))
+&& !builtins.pathExists (builtins.toPath (builtins.toString ./bla.nix))
+&& builtins.pathExists ./lib.nix
+&& !builtins.pathExists ./bla.nix
diff --git a/tests/functional/lang/eval-okay-patterns.exp b/tests/functional/lang/eval-okay-patterns.exp
new file mode 100644
index 000000000..a4304010f
--- /dev/null
+++ b/tests/functional/lang/eval-okay-patterns.exp
@@ -0,0 +1 @@
+"abcxyzDDDDEFijk"
diff --git a/tests/functional/lang/eval-okay-patterns.nix b/tests/functional/lang/eval-okay-patterns.nix
new file mode 100644
index 000000000..96fd25a01
--- /dev/null
+++ b/tests/functional/lang/eval-okay-patterns.nix
@@ -0,0 +1,16 @@
+let
+
+ f = args@{x, y, z}: x + args.y + z;
+
+ g = {x, y, z}@args: f args;
+
+ h = {x ? "d", y ? x, z ? args.x}@args: x + y + z;
+
+ j = {x, y, z, ...}: x + y + z;
+
+in
+ f {x = "a"; y = "b"; z = "c";} +
+ g {x = "x"; y = "y"; z = "z";} +
+ h {x = "D";} +
+ h {x = "D"; y = "E"; z = "F";} +
+ j {x = "i"; y = "j"; z = "k"; bla = "bla"; foo = "bar";}
diff --git a/tests/functional/lang/eval-okay-print.err.exp b/tests/functional/lang/eval-okay-print.err.exp
new file mode 100644
index 000000000..3fc99be3e
--- /dev/null
+++ b/tests/functional/lang/eval-okay-print.err.exp
@@ -0,0 +1 @@
+trace: [ <CODE> ]
diff --git a/tests/functional/lang/eval-okay-print.exp b/tests/functional/lang/eval-okay-print.exp
new file mode 100644
index 000000000..0d960fb70
--- /dev/null
+++ b/tests/functional/lang/eval-okay-print.exp
@@ -0,0 +1 @@
+[ null <PRIMOP> <PRIMOP-APP> <LAMBDA> [ [ «repeated» ] ] ]
diff --git a/tests/functional/lang/eval-okay-print.nix b/tests/functional/lang/eval-okay-print.nix
new file mode 100644
index 000000000..d36ba4da3
--- /dev/null
+++ b/tests/functional/lang/eval-okay-print.nix
@@ -0,0 +1 @@
+with builtins; trace [(1+1)] [ null toString (deepSeq "x") (a: a) (let x=[x]; in x) ]
diff --git a/tests/functional/lang/eval-okay-readDir.exp b/tests/functional/lang/eval-okay-readDir.exp
new file mode 100644
index 000000000..6413f6d4f
--- /dev/null
+++ b/tests/functional/lang/eval-okay-readDir.exp
@@ -0,0 +1 @@
+{ bar = "regular"; foo = "directory"; ldir = "symlink"; linked = "symlink"; }
diff --git a/tests/functional/lang/eval-okay-readDir.nix b/tests/functional/lang/eval-okay-readDir.nix
new file mode 100644
index 000000000..a7ec9292a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-readDir.nix
@@ -0,0 +1 @@
+builtins.readDir ./readDir
diff --git a/tests/functional/lang/eval-okay-readFileType.exp b/tests/functional/lang/eval-okay-readFileType.exp
new file mode 100644
index 000000000..6413f6d4f
--- /dev/null
+++ b/tests/functional/lang/eval-okay-readFileType.exp
@@ -0,0 +1 @@
+{ bar = "regular"; foo = "directory"; ldir = "symlink"; linked = "symlink"; }
diff --git a/tests/functional/lang/eval-okay-readFileType.nix b/tests/functional/lang/eval-okay-readFileType.nix
new file mode 100644
index 000000000..174fb6c3a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-readFileType.nix
@@ -0,0 +1,6 @@
+{
+ bar = builtins.readFileType ./readDir/bar;
+ foo = builtins.readFileType ./readDir/foo;
+ linked = builtins.readFileType ./readDir/linked;
+ ldir = builtins.readFileType ./readDir/ldir;
+}
diff --git a/tests/functional/lang/eval-okay-readfile.exp b/tests/functional/lang/eval-okay-readfile.exp
new file mode 100644
index 000000000..a2c87d0c4
--- /dev/null
+++ b/tests/functional/lang/eval-okay-readfile.exp
@@ -0,0 +1 @@
+"builtins.readFile ./eval-okay-readfile.nix\n"
diff --git a/tests/functional/lang/eval-okay-readfile.nix b/tests/functional/lang/eval-okay-readfile.nix
new file mode 100644
index 000000000..82f7cb174
--- /dev/null
+++ b/tests/functional/lang/eval-okay-readfile.nix
@@ -0,0 +1 @@
+builtins.readFile ./eval-okay-readfile.nix
diff --git a/tests/functional/lang/eval-okay-redefine-builtin.exp b/tests/functional/lang/eval-okay-redefine-builtin.exp
new file mode 100644
index 000000000..c508d5366
--- /dev/null
+++ b/tests/functional/lang/eval-okay-redefine-builtin.exp
@@ -0,0 +1 @@
+false
diff --git a/tests/functional/lang/eval-okay-redefine-builtin.nix b/tests/functional/lang/eval-okay-redefine-builtin.nix
new file mode 100644
index 000000000..df9fc3f37
--- /dev/null
+++ b/tests/functional/lang/eval-okay-redefine-builtin.nix
@@ -0,0 +1,3 @@
+let
+ throw = abort "Error!";
+in (builtins.tryEval <foobaz>).success
diff --git a/tests/functional/lang/eval-okay-regex-match.exp b/tests/functional/lang/eval-okay-regex-match.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-regex-match.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-regex-match.nix b/tests/functional/lang/eval-okay-regex-match.nix
new file mode 100644
index 000000000..273e25907
--- /dev/null
+++ b/tests/functional/lang/eval-okay-regex-match.nix
@@ -0,0 +1,29 @@
+with builtins;
+
+let
+
+ matches = pat: s: match pat s != null;
+
+ splitFN = match "((.*)/)?([^/]*)\\.(nix|cc)";
+
+in
+
+assert matches "foobar" "foobar";
+assert matches "fo*" "f";
+assert !matches "fo+" "f";
+assert matches "fo*" "fo";
+assert matches "fo*" "foo";
+assert matches "fo+" "foo";
+assert matches "fo{1,2}" "foo";
+assert !matches "fo{1,2}" "fooo";
+assert !matches "fo*" "foobar";
+assert matches "[[:space:]]+([^[:space:]]+)[[:space:]]+" " foo ";
+assert !matches "[[:space:]]+([[:upper:]]+)[[:space:]]+" " foo ";
+
+assert match "(.*)\\.nix" "foobar.nix" == [ "foobar" ];
+assert match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " FOO " == [ "FOO" ];
+
+assert splitFN "/path/to/foobar.nix" == [ "/path/to/" "/path/to" "foobar" "nix" ];
+assert splitFN "foobar.cc" == [ null null "foobar" "cc" ];
+
+true
diff --git a/tests/functional/lang/eval-okay-regex-split.exp b/tests/functional/lang/eval-okay-regex-split.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-regex-split.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-regex-split.nix b/tests/functional/lang/eval-okay-regex-split.nix
new file mode 100644
index 000000000..0073e0577
--- /dev/null
+++ b/tests/functional/lang/eval-okay-regex-split.nix
@@ -0,0 +1,48 @@
+with builtins;
+
+# Non capturing regex returns empty lists
+assert split "foobar" "foobar" == ["" [] ""];
+assert split "fo*" "f" == ["" [] ""];
+assert split "fo+" "f" == ["f"];
+assert split "fo*" "fo" == ["" [] ""];
+assert split "fo*" "foo" == ["" [] ""];
+assert split "fo+" "foo" == ["" [] ""];
+assert split "fo{1,2}" "foo" == ["" [] ""];
+assert split "fo{1,2}" "fooo" == ["" [] "o"];
+assert split "fo*" "foobar" == ["" [] "bar"];
+
+# Capturing regex returns a list of sub-matches
+assert split "(fo*)" "f" == ["" ["f"] ""];
+assert split "(fo+)" "f" == ["f"];
+assert split "(fo*)" "fo" == ["" ["fo"] ""];
+assert split "(f)(o*)" "f" == ["" ["f" ""] ""];
+assert split "(f)(o*)" "foo" == ["" ["f" "oo"] ""];
+assert split "(fo+)" "foo" == ["" ["foo"] ""];
+assert split "(fo{1,2})" "foo" == ["" ["foo"] ""];
+assert split "(fo{1,2})" "fooo" == ["" ["foo"] "o"];
+assert split "(fo*)" "foobar" == ["" ["foo"] "bar"];
+
+# Matches are greedy.
+assert split "(o+)" "oooofoooo" == ["" ["oooo"] "f" ["oooo"] ""];
+
+# Matches multiple times.
+assert split "(b)" "foobarbaz" == ["foo" ["b"] "ar" ["b"] "az"];
+
+# Split large strings containing newlines. null are inserted when a
+# pattern within the current did not match anything.
+assert split "[[:space:]]+|([',.!?])" ''
+ Nix Rocks!
+ That's why I use it.
+'' == [
+ "Nix" [ null ] "Rocks" ["!"] "" [ null ]
+ "That" ["'"] "s" [ null ] "why" [ null ] "I" [ null ] "use" [ null ] "it" ["."] "" [ null ]
+ ""
+];
+
+# Documentation examples
+assert split "(a)b" "abc" == [ "" [ "a" ] "c" ];
+assert split "([ac])" "abc" == [ "" [ "a" ] "b" [ "c" ] "" ];
+assert split "(a)|(c)" "abc" == [ "" [ "a" null ] "b" [ null "c" ] "" ];
+assert split "([[:upper:]]+)" " FOO " == [ " " [ "FOO" ] " " ];
+
+true
diff --git a/tests/functional/lang/eval-okay-regression-20220122.exp b/tests/functional/lang/eval-okay-regression-20220122.exp
new file mode 100644
index 000000000..00750edc0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-regression-20220122.exp
@@ -0,0 +1 @@
+3
diff --git a/tests/functional/lang/eval-okay-regression-20220122.nix b/tests/functional/lang/eval-okay-regression-20220122.nix
new file mode 100644
index 000000000..694e9a13b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-regression-20220122.nix
@@ -0,0 +1 @@
+((_: _) 1) + ((__: __) 2)
diff --git a/tests/functional/lang/eval-okay-regression-20220125.exp b/tests/functional/lang/eval-okay-regression-20220125.exp
new file mode 100644
index 000000000..00750edc0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-regression-20220125.exp
@@ -0,0 +1 @@
+3
diff --git a/tests/functional/lang/eval-okay-regression-20220125.nix b/tests/functional/lang/eval-okay-regression-20220125.nix
new file mode 100644
index 000000000..485502373
--- /dev/null
+++ b/tests/functional/lang/eval-okay-regression-20220125.nix
@@ -0,0 +1,2 @@
+((__curPosFoo: __curPosFoo) 1) + ((__curPosBar: __curPosBar) 2)
+
diff --git a/tests/functional/lang/eval-okay-remove.exp b/tests/functional/lang/eval-okay-remove.exp
new file mode 100644
index 000000000..8d38505c1
--- /dev/null
+++ b/tests/functional/lang/eval-okay-remove.exp
@@ -0,0 +1 @@
+456
diff --git a/tests/functional/lang/eval-okay-remove.nix b/tests/functional/lang/eval-okay-remove.nix
new file mode 100644
index 000000000..4ad5ba897
--- /dev/null
+++ b/tests/functional/lang/eval-okay-remove.nix
@@ -0,0 +1,5 @@
+let {
+ attrs = {x = 123; y = 456;};
+
+ body = (removeAttrs attrs ["x"]).y;
+} \ No newline at end of file
diff --git a/tests/functional/lang/eval-okay-replacestrings.exp b/tests/functional/lang/eval-okay-replacestrings.exp
new file mode 100644
index 000000000..eac67c5fe
--- /dev/null
+++ b/tests/functional/lang/eval-okay-replacestrings.exp
@@ -0,0 +1 @@
+[ "faabar" "fbar" "fubar" "faboor" "fubar" "XaXbXcX" "X" "a_b" "fubar" ]
diff --git a/tests/functional/lang/eval-okay-replacestrings.nix b/tests/functional/lang/eval-okay-replacestrings.nix
new file mode 100644
index 000000000..a803e6519
--- /dev/null
+++ b/tests/functional/lang/eval-okay-replacestrings.nix
@@ -0,0 +1,12 @@
+with builtins;
+
+[ (replaceStrings ["o"] ["a"] "foobar")
+ (replaceStrings ["o"] [""] "foobar")
+ (replaceStrings ["oo"] ["u"] "foobar")
+ (replaceStrings ["oo" "a"] ["a" "oo"] "foobar")
+ (replaceStrings ["oo" "oo"] ["u" "i"] "foobar")
+ (replaceStrings [""] ["X"] "abc")
+ (replaceStrings [""] ["X"] "")
+ (replaceStrings ["-"] ["_"] "a-b")
+ (replaceStrings ["oo" "XX"] ["u" (throw "unreachable")] "foobar")
+]
diff --git a/tests/functional/lang/eval-okay-scope-1.exp b/tests/functional/lang/eval-okay-scope-1.exp
new file mode 100644
index 000000000..00750edc0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-1.exp
@@ -0,0 +1 @@
+3
diff --git a/tests/functional/lang/eval-okay-scope-1.nix b/tests/functional/lang/eval-okay-scope-1.nix
new file mode 100644
index 000000000..fa38a7174
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-1.nix
@@ -0,0 +1,6 @@
+(({x}: x:
+
+ { x = 1;
+ y = x;
+ }
+) {x = 2;} 3).y
diff --git a/tests/functional/lang/eval-okay-scope-2.exp b/tests/functional/lang/eval-okay-scope-2.exp
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-2.exp
@@ -0,0 +1 @@
+1
diff --git a/tests/functional/lang/eval-okay-scope-2.nix b/tests/functional/lang/eval-okay-scope-2.nix
new file mode 100644
index 000000000..eb8b02bc4
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-2.nix
@@ -0,0 +1,6 @@
+((x: {x}:
+ rec {
+ x = 1;
+ y = x;
+ }
+) 2 {x = 3;}).y
diff --git a/tests/functional/lang/eval-okay-scope-3.exp b/tests/functional/lang/eval-okay-scope-3.exp
new file mode 100644
index 000000000..b8626c4cf
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-3.exp
@@ -0,0 +1 @@
+4
diff --git a/tests/functional/lang/eval-okay-scope-3.nix b/tests/functional/lang/eval-okay-scope-3.nix
new file mode 100644
index 000000000..10d6bc04d
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-3.nix
@@ -0,0 +1,6 @@
+((x: as: {x}:
+ rec {
+ inherit (as) x;
+ y = x;
+ }
+) 2 {x = 4;} {x = 3;}).y
diff --git a/tests/functional/lang/eval-okay-scope-4.exp b/tests/functional/lang/eval-okay-scope-4.exp
new file mode 100644
index 000000000..00ff03a46
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-4.exp
@@ -0,0 +1 @@
+"ccdd"
diff --git a/tests/functional/lang/eval-okay-scope-4.nix b/tests/functional/lang/eval-okay-scope-4.nix
new file mode 100644
index 000000000..dc8243bc8
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-4.nix
@@ -0,0 +1,10 @@
+let {
+
+ x = "a";
+ y = "b";
+
+ f = {x ? y, y ? x}: x + y;
+
+ body = f {x = "c";} + f {y = "d";};
+
+}
diff --git a/tests/functional/lang/eval-okay-scope-6.exp b/tests/functional/lang/eval-okay-scope-6.exp
new file mode 100644
index 000000000..00ff03a46
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-6.exp
@@ -0,0 +1 @@
+"ccdd"
diff --git a/tests/functional/lang/eval-okay-scope-6.nix b/tests/functional/lang/eval-okay-scope-6.nix
new file mode 100644
index 000000000..0995d4e7e
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-6.nix
@@ -0,0 +1,7 @@
+let {
+
+ f = {x ? y, y ? x}: x + y;
+
+ body = f {x = "c";} + f {y = "d";};
+
+}
diff --git a/tests/functional/lang/eval-okay-scope-7.exp b/tests/functional/lang/eval-okay-scope-7.exp
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-7.exp
@@ -0,0 +1 @@
+1
diff --git a/tests/functional/lang/eval-okay-scope-7.nix b/tests/functional/lang/eval-okay-scope-7.nix
new file mode 100644
index 000000000..4da02968f
--- /dev/null
+++ b/tests/functional/lang/eval-okay-scope-7.nix
@@ -0,0 +1,6 @@
+rec {
+ inherit (x) y;
+ x = {
+ y = 1;
+ };
+}.y
diff --git a/tests/functional/lang/eval-okay-search-path.exp b/tests/functional/lang/eval-okay-search-path.exp
new file mode 100644
index 000000000..4519bc406
--- /dev/null
+++ b/tests/functional/lang/eval-okay-search-path.exp
@@ -0,0 +1 @@
+"abccX"
diff --git a/tests/functional/lang/eval-okay-search-path.flags b/tests/functional/lang/eval-okay-search-path.flags
new file mode 100644
index 000000000..dfad1c611
--- /dev/null
+++ b/tests/functional/lang/eval-okay-search-path.flags
@@ -0,0 +1 @@
+-I lang/dir1 -I lang/dir2 -I dir5=lang/dir3
diff --git a/tests/functional/lang/eval-okay-search-path.nix b/tests/functional/lang/eval-okay-search-path.nix
new file mode 100644
index 000000000..6fe33decc
--- /dev/null
+++ b/tests/functional/lang/eval-okay-search-path.nix
@@ -0,0 +1,10 @@
+with import ./lib.nix;
+with builtins;
+
+assert isFunction (import <nix/fetchurl.nix>);
+
+assert length __nixPath == 5;
+assert length (filter (x: baseNameOf x.path == "dir4") __nixPath) == 1;
+
+import <a.nix> + import <b.nix> + import <c.nix> + import <dir5/c.nix>
+ + (let __nixPath = [ { path = ./dir2; } { path = ./dir1; } ]; in import <a.nix>)
diff --git a/tests/functional/lang/eval-okay-seq.exp b/tests/functional/lang/eval-okay-seq.exp
new file mode 100644
index 000000000..0cfbf0888
--- /dev/null
+++ b/tests/functional/lang/eval-okay-seq.exp
@@ -0,0 +1 @@
+2
diff --git a/tests/functional/lang/eval-okay-seq.nix b/tests/functional/lang/eval-okay-seq.nix
new file mode 100644
index 000000000..0a9a21c03
--- /dev/null
+++ b/tests/functional/lang/eval-okay-seq.nix
@@ -0,0 +1 @@
+builtins.seq 1 2
diff --git a/tests/functional/lang/eval-okay-sort.exp b/tests/functional/lang/eval-okay-sort.exp
new file mode 100644
index 000000000..899119e20
--- /dev/null
+++ b/tests/functional/lang/eval-okay-sort.exp
@@ -0,0 +1 @@
+[ [ 42 77 147 249 483 526 ] [ 526 483 249 147 77 42 ] [ "bar" "fnord" "foo" "xyzzy" ] [ { key = 1; value = "foo"; } { key = 1; value = "fnord"; } { key = 2; value = "bar"; } ] [ [ ] [ ] [ 1 ] [ 1 4 ] [ 1 5 ] [ 1 6 ] [ 2 ] [ 2 3 ] [ 3 ] [ 3 ] ] ]
diff --git a/tests/functional/lang/eval-okay-sort.nix b/tests/functional/lang/eval-okay-sort.nix
new file mode 100644
index 000000000..50aa78e40
--- /dev/null
+++ b/tests/functional/lang/eval-okay-sort.nix
@@ -0,0 +1,20 @@
+with builtins;
+
+[ (sort lessThan [ 483 249 526 147 42 77 ])
+ (sort (x: y: y < x) [ 483 249 526 147 42 77 ])
+ (sort lessThan [ "foo" "bar" "xyzzy" "fnord" ])
+ (sort (x: y: x.key < y.key)
+ [ { key = 1; value = "foo"; } { key = 2; value = "bar"; } { key = 1; value = "fnord"; } ])
+ (sort lessThan [
+ [ 1 6 ]
+ [ ]
+ [ 2 3 ]
+ [ 3 ]
+ [ 1 5 ]
+ [ 2 ]
+ [ 1 ]
+ [ ]
+ [ 1 4 ]
+ [ 3 ]
+ ])
+]
diff --git a/tests/functional/lang/eval-okay-splitversion.exp b/tests/functional/lang/eval-okay-splitversion.exp
new file mode 100644
index 000000000..153ceb818
--- /dev/null
+++ b/tests/functional/lang/eval-okay-splitversion.exp
@@ -0,0 +1 @@
+[ "1" "2" "3" ]
diff --git a/tests/functional/lang/eval-okay-splitversion.nix b/tests/functional/lang/eval-okay-splitversion.nix
new file mode 100644
index 000000000..9e5c99d2e
--- /dev/null
+++ b/tests/functional/lang/eval-okay-splitversion.nix
@@ -0,0 +1 @@
+builtins.splitVersion "1.2.3"
diff --git a/tests/functional/lang/eval-okay-string.exp b/tests/functional/lang/eval-okay-string.exp
new file mode 100644
index 000000000..63f650f73
--- /dev/null
+++ b/tests/functional/lang/eval-okay-string.exp
@@ -0,0 +1 @@
+"foobar/a/b/c/d/foo/xyzzy/foo.txt/../foo/x/yescape: \"quote\" \n \\end\nof\nlinefoobarblaatfoo$bar$\"$\"$"
diff --git a/tests/functional/lang/eval-okay-string.nix b/tests/functional/lang/eval-okay-string.nix
new file mode 100644
index 000000000..47cc989ad
--- /dev/null
+++ b/tests/functional/lang/eval-okay-string.nix
@@ -0,0 +1,12 @@
+"foo" + "bar"
+ + toString (/a/b + /c/d)
+ + toString (/foo/bar + "/../xyzzy/." + "/foo.txt")
+ + ("/../foo" + toString /x/y)
+ + "escape: \"quote\" \n \\"
+ + "end
+of
+line"
+ + "foo${if true then "b${"a" + "r"}" else "xyzzy"}blaat"
+ + "foo$bar"
+ + "$\"$\""
+ + "$"
diff --git a/tests/functional/lang/eval-okay-strings-as-attrs-names.exp b/tests/functional/lang/eval-okay-strings-as-attrs-names.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-strings-as-attrs-names.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-strings-as-attrs-names.nix b/tests/functional/lang/eval-okay-strings-as-attrs-names.nix
new file mode 100644
index 000000000..5e40928db
--- /dev/null
+++ b/tests/functional/lang/eval-okay-strings-as-attrs-names.nix
@@ -0,0 +1,20 @@
+let
+
+ attr = {
+ "key 1" = "test";
+ "key 2" = "caseok";
+ };
+
+ t1 = builtins.getAttr "key 1" attr;
+ t2 = attr."key 2";
+ t3 = attr ? "key 1";
+ t4 = builtins.attrNames { inherit (attr) "key 1"; };
+
+ # This is permitted, but there is currently no way to reference this
+ # variable.
+ "foo bar" = 1;
+
+in t1 == "test"
+ && t2 == "caseok"
+ && t3 == true
+ && t4 == ["key 1"]
diff --git a/tests/functional/lang/eval-okay-substring.exp b/tests/functional/lang/eval-okay-substring.exp
new file mode 100644
index 000000000..6aace04b0
--- /dev/null
+++ b/tests/functional/lang/eval-okay-substring.exp
@@ -0,0 +1 @@
+"ooxfoobarybarzobaabbc"
diff --git a/tests/functional/lang/eval-okay-substring.nix b/tests/functional/lang/eval-okay-substring.nix
new file mode 100644
index 000000000..424af00d9
--- /dev/null
+++ b/tests/functional/lang/eval-okay-substring.nix
@@ -0,0 +1,21 @@
+with builtins;
+
+let
+
+ s = "foobar";
+
+in
+
+substring 1 2 s
++ "x"
++ substring 0 (stringLength s) s
++ "y"
++ substring 3 100 s
++ "z"
++ substring 2 (sub (stringLength s) 3) s
++ "a"
++ substring 3 0 s
++ "b"
++ substring 3 1 s
++ "c"
++ substring 5 10 "perl"
diff --git a/tests/functional/lang/eval-okay-tail-call-1.exp-disabled b/tests/functional/lang/eval-okay-tail-call-1.exp-disabled
new file mode 100644
index 000000000..f7393e847
--- /dev/null
+++ b/tests/functional/lang/eval-okay-tail-call-1.exp-disabled
@@ -0,0 +1 @@
+100000
diff --git a/tests/functional/lang/eval-okay-tail-call-1.nix b/tests/functional/lang/eval-okay-tail-call-1.nix
new file mode 100644
index 000000000..a3962ce3f
--- /dev/null
+++ b/tests/functional/lang/eval-okay-tail-call-1.nix
@@ -0,0 +1,3 @@
+let
+ f = n: if n == 100000 then n else f (n + 1);
+in f 0
diff --git a/tests/functional/lang/eval-okay-tojson.exp b/tests/functional/lang/eval-okay-tojson.exp
new file mode 100644
index 000000000..e92aae323
--- /dev/null
+++ b/tests/functional/lang/eval-okay-tojson.exp
@@ -0,0 +1 @@
+"{\"a\":123,\"b\":-456,\"c\":\"foo\",\"d\":\"foo\\n\\\"bar\\\"\",\"e\":true,\"f\":false,\"g\":[1,2,3],\"h\":[\"a\",[\"b\",{\"foo\\nbar\":{}}]],\"i\":3,\"j\":1.44,\"k\":\"foo\"}"
diff --git a/tests/functional/lang/eval-okay-tojson.nix b/tests/functional/lang/eval-okay-tojson.nix
new file mode 100644
index 000000000..ce67943be
--- /dev/null
+++ b/tests/functional/lang/eval-okay-tojson.nix
@@ -0,0 +1,13 @@
+builtins.toJSON
+ { a = 123;
+ b = -456;
+ c = "foo";
+ d = "foo\n\"bar\"";
+ e = true;
+ f = false;
+ g = [ 1 2 3 ];
+ h = [ "a" [ "b" { "foo\nbar" = {}; } ] ];
+ i = 1 + 2;
+ j = 1.44;
+ k = { __toString = self: self.a; a = "foo"; };
+ }
diff --git a/tests/functional/lang/eval-okay-toxml.exp b/tests/functional/lang/eval-okay-toxml.exp
new file mode 100644
index 000000000..828220890
--- /dev/null
+++ b/tests/functional/lang/eval-okay-toxml.exp
@@ -0,0 +1 @@
+"<?xml version='1.0' encoding='utf-8'?>\n<expr>\n <attrs>\n <attr name=\"a\">\n <string value=\"s\" />\n </attr>\n </attrs>\n</expr>\n"
diff --git a/tests/functional/lang/eval-okay-toxml.nix b/tests/functional/lang/eval-okay-toxml.nix
new file mode 100644
index 000000000..068c97a6c
--- /dev/null
+++ b/tests/functional/lang/eval-okay-toxml.nix
@@ -0,0 +1,3 @@
+# Make sure the expected XML output is produced; in particular, make sure it
+# doesn't contain source location information.
+builtins.toXML { a = "s"; }
diff --git a/tests/functional/lang/eval-okay-toxml2.exp b/tests/functional/lang/eval-okay-toxml2.exp
new file mode 100644
index 000000000..634a841eb
--- /dev/null
+++ b/tests/functional/lang/eval-okay-toxml2.exp
@@ -0,0 +1 @@
+"<?xml version='1.0' encoding='utf-8'?>\n<expr>\n <list>\n <string value=\"ab\" />\n <int value=\"10\" />\n <attrs>\n <attr name=\"x\">\n <string value=\"x\" />\n </attr>\n <attr name=\"y\">\n <string value=\"x\" />\n </attr>\n </attrs>\n </list>\n</expr>\n"
diff --git a/tests/functional/lang/eval-okay-toxml2.nix b/tests/functional/lang/eval-okay-toxml2.nix
new file mode 100644
index 000000000..ff1791b30
--- /dev/null
+++ b/tests/functional/lang/eval-okay-toxml2.nix
@@ -0,0 +1 @@
+builtins.toXML [("a" + "b") 10 (rec {x = "x"; y = x;})]
diff --git a/tests/functional/lang/eval-okay-tryeval.exp b/tests/functional/lang/eval-okay-tryeval.exp
new file mode 100644
index 000000000..2b2e6fa71
--- /dev/null
+++ b/tests/functional/lang/eval-okay-tryeval.exp
@@ -0,0 +1 @@
+{ x = { success = true; value = "x"; }; y = { success = false; value = false; }; z = { success = false; value = false; }; }
diff --git a/tests/functional/lang/eval-okay-tryeval.nix b/tests/functional/lang/eval-okay-tryeval.nix
new file mode 100644
index 000000000..629bc440a
--- /dev/null
+++ b/tests/functional/lang/eval-okay-tryeval.nix
@@ -0,0 +1,5 @@
+{
+ x = builtins.tryEval "x";
+ y = builtins.tryEval (assert false; "y");
+ z = builtins.tryEval (throw "bla");
+}
diff --git a/tests/functional/lang/eval-okay-types.exp b/tests/functional/lang/eval-okay-types.exp
new file mode 100644
index 000000000..92a153299
--- /dev/null
+++ b/tests/functional/lang/eval-okay-types.exp
@@ -0,0 +1 @@
+[ true false true false true false true false true true true true true true true true true true true false true true true false "int" "bool" "string" "null" "set" "list" "lambda" "lambda" "lambda" "lambda" ]
diff --git a/tests/functional/lang/eval-okay-types.nix b/tests/functional/lang/eval-okay-types.nix
new file mode 100644
index 000000000..9b58be5d1
--- /dev/null
+++ b/tests/functional/lang/eval-okay-types.nix
@@ -0,0 +1,37 @@
+with builtins;
+
+[ (isNull null)
+ (isNull (x: x))
+ (isFunction (x: x))
+ (isFunction "fnord")
+ (isString ("foo" + "bar"))
+ (isString [ "x" ])
+ (isInt (1 + 2))
+ (isInt { x = 123; })
+ (isInt (1 / 2))
+ (isInt (1 + 1))
+ (isInt (1 / 2))
+ (isInt (1 * 2))
+ (isInt (1 - 2))
+ (isFloat (1.2))
+ (isFloat (1 + 1.0))
+ (isFloat (1 / 2.0))
+ (isFloat (1 * 2.0))
+ (isFloat (1 - 2.0))
+ (isBool (true && false))
+ (isBool null)
+ (isPath /nix/store)
+ (isPath ./.)
+ (isAttrs { x = 123; })
+ (isAttrs null)
+ (typeOf (3 * 4))
+ (typeOf true)
+ (typeOf "xyzzy")
+ (typeOf null)
+ (typeOf { x = 456; })
+ (typeOf [ 1 2 3 ])
+ (typeOf (x: x))
+ (typeOf ((x: y: x) 1))
+ (typeOf map)
+ (typeOf (map (x: x)))
+]
diff --git a/tests/functional/lang/eval-okay-versions.exp b/tests/functional/lang/eval-okay-versions.exp
new file mode 100644
index 000000000..27ba77dda
--- /dev/null
+++ b/tests/functional/lang/eval-okay-versions.exp
@@ -0,0 +1 @@
+true
diff --git a/tests/functional/lang/eval-okay-versions.nix b/tests/functional/lang/eval-okay-versions.nix
new file mode 100644
index 000000000..e9111f5f4
--- /dev/null
+++ b/tests/functional/lang/eval-okay-versions.nix
@@ -0,0 +1,43 @@
+let
+
+ name1 = "hello-1.0.2";
+ name2 = "hello";
+ name3 = "915resolution-0.5.2";
+ name4 = "xf86-video-i810-1.7.4";
+ name5 = "name-that-ends-with-dash--1.0";
+
+ eq = 0;
+ lt = builtins.sub 0 1;
+ gt = 1;
+
+ versionTest = v1: v2: expected:
+ let d1 = builtins.compareVersions v1 v2;
+ d2 = builtins.compareVersions v2 v1;
+ in d1 == builtins.sub 0 d2 && d1 == expected;
+
+ tests = [
+ ((builtins.parseDrvName name1).name == "hello")
+ ((builtins.parseDrvName name1).version == "1.0.2")
+ ((builtins.parseDrvName name2).name == "hello")
+ ((builtins.parseDrvName name2).version == "")
+ ((builtins.parseDrvName name3).name == "915resolution")
+ ((builtins.parseDrvName name3).version == "0.5.2")
+ ((builtins.parseDrvName name4).name == "xf86-video-i810")
+ ((builtins.parseDrvName name4).version == "1.7.4")
+ ((builtins.parseDrvName name5).name == "name-that-ends-with-dash")
+ ((builtins.parseDrvName name5).version == "-1.0")
+ (versionTest "1.0" "2.3" lt)
+ (versionTest "2.1" "2.3" lt)
+ (versionTest "2.3" "2.3" eq)
+ (versionTest "2.5" "2.3" gt)
+ (versionTest "3.1" "2.3" gt)
+ (versionTest "2.3.1" "2.3" gt)
+ (versionTest "2.3.1" "2.3a" gt)
+ (versionTest "2.3pre1" "2.3" lt)
+ (versionTest "2.3pre3" "2.3pre12" lt)
+ (versionTest "2.3a" "2.3c" lt)
+ (versionTest "2.3pre1" "2.3c" lt)
+ (versionTest "2.3pre1" "2.3q" lt)
+ ];
+
+in (import ./lib.nix).and tests
diff --git a/tests/functional/lang/eval-okay-with.exp b/tests/functional/lang/eval-okay-with.exp
new file mode 100644
index 000000000..378c8dc80
--- /dev/null
+++ b/tests/functional/lang/eval-okay-with.exp
@@ -0,0 +1 @@
+"xyzzybarxyzzybar"
diff --git a/tests/functional/lang/eval-okay-with.nix b/tests/functional/lang/eval-okay-with.nix
new file mode 100644
index 000000000..033e8d3ab
--- /dev/null
+++ b/tests/functional/lang/eval-okay-with.nix
@@ -0,0 +1,19 @@
+let {
+
+ a = "xyzzy";
+
+ as = {
+ a = "foo";
+ b = "bar";
+ };
+
+ bs = {
+ a = "bar";
+ };
+
+ x = with as; a + b;
+
+ y = with as; with bs; a + b;
+
+ body = x + y;
+}
diff --git a/tests/functional/lang/eval-okay-xml.exp.xml b/tests/functional/lang/eval-okay-xml.exp.xml
new file mode 100644
index 000000000..20099326c
--- /dev/null
+++ b/tests/functional/lang/eval-okay-xml.exp.xml
@@ -0,0 +1,52 @@
+<?xml version='1.0' encoding='utf-8'?>
+<expr>
+ <attrs>
+ <attr name="a">
+ <string value="foo" />
+ </attr>
+ <attr name="at">
+ <function>
+ <attrspat name="args">
+ <attr name="x" />
+ <attr name="y" />
+ <attr name="z" />
+ </attrspat>
+ </function>
+ </attr>
+ <attr name="b">
+ <string value="bar" />
+ </attr>
+ <attr name="c">
+ <string value="foobar" />
+ </attr>
+ <attr name="ellipsis">
+ <function>
+ <attrspat ellipsis="1">
+ <attr name="x" />
+ <attr name="y" />
+ <attr name="z" />
+ </attrspat>
+ </function>
+ </attr>
+ <attr name="f">
+ <function>
+ <attrspat>
+ <attr name="x" />
+ <attr name="y" />
+ <attr name="z" />
+ </attrspat>
+ </function>
+ </attr>
+ <attr name="id">
+ <function>
+ <varpat name="x" />
+ </function>
+ </attr>
+ <attr name="x">
+ <int value="123" />
+ </attr>
+ <attr name="y">
+ <float value="567.89" />
+ </attr>
+ </attrs>
+</expr>
diff --git a/tests/functional/lang/eval-okay-xml.nix b/tests/functional/lang/eval-okay-xml.nix
new file mode 100644
index 000000000..9ee9f8a0b
--- /dev/null
+++ b/tests/functional/lang/eval-okay-xml.nix
@@ -0,0 +1,21 @@
+rec {
+
+ x = 123;
+
+ y = 567.890;
+
+ a = "foo";
+
+ b = "bar";
+
+ c = "foo" + "bar";
+
+ f = {z, x, y}: if y then x else z;
+
+ id = x: x;
+
+ at = args@{x, y, z}: x;
+
+ ellipsis = {x, y, z, ...}: x;
+
+}
diff --git a/tests/functional/lang/eval-okay-zipAttrsWith.exp b/tests/functional/lang/eval-okay-zipAttrsWith.exp
new file mode 100644
index 000000000..9c0b15d22
--- /dev/null
+++ b/tests/functional/lang/eval-okay-zipAttrsWith.exp
@@ -0,0 +1 @@
+{ "0" = { n = "0"; v = [ 5 23 29 ]; }; "1" = { n = "1"; v = [ 7 30 ]; }; "2" = { n = "2"; v = [ 18 ]; }; "4" = { n = "4"; v = [ 10 ]; }; "5" = { n = "5"; v = [ 15 25 26 31 ]; }; "6" = { n = "6"; v = [ 3 14 ]; }; "7" = { n = "7"; v = [ 12 ]; }; "8" = { n = "8"; v = [ 2 6 8 9 ]; }; "9" = { n = "9"; v = [ 0 16 ]; }; a = { n = "a"; v = [ 17 21 22 27 ]; }; c = { n = "c"; v = [ 11 24 ]; }; d = { n = "d"; v = [ 4 13 28 ]; }; e = { n = "e"; v = [ 20 ]; }; f = { n = "f"; v = [ 1 19 ]; }; }
diff --git a/tests/functional/lang/eval-okay-zipAttrsWith.nix b/tests/functional/lang/eval-okay-zipAttrsWith.nix
new file mode 100644
index 000000000..877d4e5fa
--- /dev/null
+++ b/tests/functional/lang/eval-okay-zipAttrsWith.nix
@@ -0,0 +1,9 @@
+with import ./lib.nix;
+
+let
+ str = builtins.hashString "sha256" "test";
+in
+builtins.zipAttrsWith
+ (n: v: { inherit n v; })
+ (map (n: { ${builtins.substring n 1 str} = n; })
+ (range 0 31))
diff --git a/tests/functional/lang/framework.sh b/tests/functional/lang/framework.sh
new file mode 100644
index 000000000..516bff8ad
--- /dev/null
+++ b/tests/functional/lang/framework.sh
@@ -0,0 +1,33 @@
+# Golden test support
+#
+# Test that the output of the given test matches what is expected. If
+# `_NIX_TEST_ACCEPT` is non-empty also update the expected output so
+# that next time the test succeeds.
+function diffAndAcceptInner() {
+ local -r testName=$1
+ local -r got="$2"
+ local -r expected="$3"
+
+ # Absence of expected file indicates empty output expected.
+ if test -e "$expected"; then
+ local -r expectedOrEmpty="$expected"
+ else
+ local -r expectedOrEmpty=lang/empty.exp
+ fi
+
+ # Diff so we get a nice message
+ if ! diff --unified "$got" "$expectedOrEmpty"; then
+ echo "FAIL: evaluation result of $testName not as expected"
+ badDiff=1
+ fi
+
+ # Update expected if `_NIX_TEST_ACCEPT` is non-empty.
+ if test -n "${_NIX_TEST_ACCEPT-}"; then
+ cp "$got" "$expected"
+ # Delete empty expected files to avoid bloating the repo with
+ # empty files.
+ if ! test -s "$expected"; then
+ rm "$expected"
+ fi
+ fi
+}
diff --git a/tests/functional/lang/imported.nix b/tests/functional/lang/imported.nix
new file mode 100644
index 000000000..fb39ee4ef
--- /dev/null
+++ b/tests/functional/lang/imported.nix
@@ -0,0 +1,3 @@
+# The function ‘range’ comes from lib.nix and was added to the lexical
+# scope by scopedImport.
+range 1 5 ++ import ./imported2.nix
diff --git a/tests/functional/lang/imported2.nix b/tests/functional/lang/imported2.nix
new file mode 100644
index 000000000..6d0a2992b
--- /dev/null
+++ b/tests/functional/lang/imported2.nix
@@ -0,0 +1 @@
+range 6 10
diff --git a/tests/functional/lang/lib.nix b/tests/functional/lang/lib.nix
new file mode 100644
index 000000000..028a53831
--- /dev/null
+++ b/tests/functional/lang/lib.nix
@@ -0,0 +1,61 @@
+with builtins;
+
+rec {
+
+ fold = op: nul: list:
+ if list == []
+ then nul
+ else op (head list) (fold op nul (tail list));
+
+ concat =
+ fold (x: y: x + y) "";
+
+ and = fold (x: y: x && y) true;
+
+ flatten = x:
+ if isList x
+ then fold (x: y: (flatten x) ++ y) [] x
+ else [x];
+
+ sum = foldl' (x: y: add x y) 0;
+
+ hasSuffix = ext: fileName:
+ let lenFileName = stringLength fileName;
+ lenExt = stringLength ext;
+ in !(lessThan lenFileName lenExt) &&
+ substring (sub lenFileName lenExt) lenFileName fileName == ext;
+
+ # Split a list at the given position.
+ splitAt = pos: list:
+ if pos == 0 then {first = []; second = list;} else
+ if list == [] then {first = []; second = [];} else
+ let res = splitAt (sub pos 1) (tail list);
+ in {first = [(head list)] ++ res.first; second = res.second;};
+
+ # Stable merge sort.
+ sortBy = comp: list:
+ if lessThan 1 (length list)
+ then
+ let
+ split = splitAt (div (length list) 2) list;
+ first = sortBy comp split.first;
+ second = sortBy comp split.second;
+ in mergeLists comp first second
+ else list;
+
+ mergeLists = comp: list1: list2:
+ if list1 == [] then list2 else
+ if list2 == [] then list1 else
+ if comp (head list2) (head list1) then [(head list2)] ++ mergeLists comp list1 (tail list2) else
+ [(head list1)] ++ mergeLists comp (tail list1) list2;
+
+ id = x: x;
+
+ const = x: y: x;
+
+ range = first: last:
+ if first > last
+ then []
+ else genList (n: first + n) (last - first + 1);
+
+}
diff --git a/tests/functional/lang/parse-fail-dup-attrs-1.err.exp b/tests/functional/lang/parse-fail-dup-attrs-1.err.exp
new file mode 100644
index 000000000..4fe6b7a1f
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-1.err.exp
@@ -0,0 +1,7 @@
+error: attribute 'x' already defined at «stdin»:1:3
+
+ at «stdin»:3:3:
+
+ 2| y = 456;
+ 3| x = 789;
+ | ^
diff --git a/tests/functional/lang/parse-fail-dup-attrs-1.nix b/tests/functional/lang/parse-fail-dup-attrs-1.nix
new file mode 100644
index 000000000..2c02317d2
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-1.nix
@@ -0,0 +1,4 @@
+{ x = 123;
+ y = 456;
+ x = 789;
+}
diff --git a/tests/functional/lang/parse-fail-dup-attrs-2.err.exp b/tests/functional/lang/parse-fail-dup-attrs-2.err.exp
new file mode 100644
index 000000000..3aba2891f
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-2.err.exp
@@ -0,0 +1,7 @@
+error: attribute 'x' already defined at «stdin»:9:5
+
+ at «stdin»:10:17:
+
+ 9| x = 789;
+ 10| inherit (as) x;
+ | ^
diff --git a/tests/functional/lang/parse-fail-dup-attrs-2.nix b/tests/functional/lang/parse-fail-dup-attrs-2.nix
new file mode 100644
index 000000000..864d9865e
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-2.nix
@@ -0,0 +1,13 @@
+let {
+
+ as = {
+ x = 123;
+ y = 456;
+ };
+
+ bs = {
+ x = 789;
+ inherit (as) x;
+ };
+
+}
diff --git a/tests/functional/lang/parse-fail-dup-attrs-3.err.exp b/tests/functional/lang/parse-fail-dup-attrs-3.err.exp
new file mode 100644
index 000000000..3aba2891f
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-3.err.exp
@@ -0,0 +1,7 @@
+error: attribute 'x' already defined at «stdin»:9:5
+
+ at «stdin»:10:17:
+
+ 9| x = 789;
+ 10| inherit (as) x;
+ | ^
diff --git a/tests/functional/lang/parse-fail-dup-attrs-3.nix b/tests/functional/lang/parse-fail-dup-attrs-3.nix
new file mode 100644
index 000000000..114d19779
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-3.nix
@@ -0,0 +1,13 @@
+let {
+
+ as = {
+ x = 123;
+ y = 456;
+ };
+
+ bs = rec {
+ x = 789;
+ inherit (as) x;
+ };
+
+}
diff --git a/tests/functional/lang/parse-fail-dup-attrs-4.err.exp b/tests/functional/lang/parse-fail-dup-attrs-4.err.exp
new file mode 100644
index 000000000..ff68446a1
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-4.err.exp
@@ -0,0 +1,7 @@
+error: attribute 'services.ssh.port' already defined at «stdin»:2:3
+
+ at «stdin»:3:3:
+
+ 2| services.ssh.port = 22;
+ 3| services.ssh.port = 23;
+ | ^
diff --git a/tests/functional/lang/parse-fail-dup-attrs-4.nix b/tests/functional/lang/parse-fail-dup-attrs-4.nix
new file mode 100644
index 000000000..77417432b
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-4.nix
@@ -0,0 +1,4 @@
+{
+ services.ssh.port = 22;
+ services.ssh.port = 23;
+}
diff --git a/tests/functional/lang/parse-fail-dup-attrs-6.err.exp b/tests/functional/lang/parse-fail-dup-attrs-6.err.exp
new file mode 100644
index 000000000..74823fc25
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-6.err.exp
@@ -0,0 +1 @@
+error: attribute ‘services.ssh’ at (string):3:3 already defined at (string):2:3
diff --git a/tests/functional/lang/parse-fail-dup-attrs-7.err.exp b/tests/functional/lang/parse-fail-dup-attrs-7.err.exp
new file mode 100644
index 000000000..512a499ca
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-7.err.exp
@@ -0,0 +1,7 @@
+error: attribute 'x' already defined at «stdin»:6:12
+
+ at «stdin»:7:12:
+
+ 6| inherit x;
+ 7| inherit x;
+ | ^
diff --git a/tests/functional/lang/parse-fail-dup-attrs-7.nix b/tests/functional/lang/parse-fail-dup-attrs-7.nix
new file mode 100644
index 000000000..bbc3eb08c
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-attrs-7.nix
@@ -0,0 +1,9 @@
+rec {
+
+ x = 1;
+
+ as = {
+ inherit x;
+ inherit x;
+ };
+} \ No newline at end of file
diff --git a/tests/functional/lang/parse-fail-dup-formals.err.exp b/tests/functional/lang/parse-fail-dup-formals.err.exp
new file mode 100644
index 000000000..1d566fb33
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-formals.err.exp
@@ -0,0 +1,6 @@
+error: duplicate formal function argument 'x'
+
+ at «stdin»:1:8:
+
+ 1| {x, y, x}: x
+ | ^
diff --git a/tests/functional/lang/parse-fail-dup-formals.nix b/tests/functional/lang/parse-fail-dup-formals.nix
new file mode 100644
index 000000000..a0edd91a9
--- /dev/null
+++ b/tests/functional/lang/parse-fail-dup-formals.nix
@@ -0,0 +1 @@
+{x, y, x}: x \ No newline at end of file
diff --git a/tests/functional/lang/parse-fail-eof-in-string.err.exp b/tests/functional/lang/parse-fail-eof-in-string.err.exp
new file mode 100644
index 000000000..f9fa72312
--- /dev/null
+++ b/tests/functional/lang/parse-fail-eof-in-string.err.exp
@@ -0,0 +1,7 @@
+error: syntax error, unexpected end of file, expecting '"'
+
+ at «stdin»:3:5:
+
+ 2| # Note that this file must not end with a newline.
+ 3| a 1"$
+ | ^
diff --git a/tests/functional/lang/parse-fail-eof-in-string.nix b/tests/functional/lang/parse-fail-eof-in-string.nix
new file mode 100644
index 000000000..19775d2ec
--- /dev/null
+++ b/tests/functional/lang/parse-fail-eof-in-string.nix
@@ -0,0 +1,3 @@
+# https://github.com/NixOS/nix/issues/6562
+# Note that this file must not end with a newline.
+a 1"$ \ No newline at end of file
diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp b/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp
new file mode 100644
index 000000000..32f776795
--- /dev/null
+++ b/tests/functional/lang/parse-fail-mixed-nested-attrs1.err.exp
@@ -0,0 +1,8 @@
+error: attribute 'z' already defined at «stdin»:3:16
+
+ at «stdin»:2:3:
+
+ 1| {
+ 2| x.z = 3;
+ | ^
+ 3| x = { y = 3; z = 3; };
diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs1.nix b/tests/functional/lang/parse-fail-mixed-nested-attrs1.nix
new file mode 100644
index 000000000..11e40e66f
--- /dev/null
+++ b/tests/functional/lang/parse-fail-mixed-nested-attrs1.nix
@@ -0,0 +1,4 @@
+{
+ x.z = 3;
+ x = { y = 3; z = 3; };
+}
diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp b/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp
new file mode 100644
index 000000000..0437cd50c
--- /dev/null
+++ b/tests/functional/lang/parse-fail-mixed-nested-attrs2.err.exp
@@ -0,0 +1,8 @@
+error: attribute 'y' already defined at «stdin»:3:9
+
+ at «stdin»:2:3:
+
+ 1| {
+ 2| x.y.y = 3;
+ | ^
+ 3| x = { y.y= 3; z = 3; };
diff --git a/tests/functional/lang/parse-fail-mixed-nested-attrs2.nix b/tests/functional/lang/parse-fail-mixed-nested-attrs2.nix
new file mode 100644
index 000000000..17da82e5f
--- /dev/null
+++ b/tests/functional/lang/parse-fail-mixed-nested-attrs2.nix
@@ -0,0 +1,4 @@
+{
+ x.y.y = 3;
+ x = { y.y= 3; z = 3; };
+}
diff --git a/tests/functional/lang/parse-fail-patterns-1.err.exp b/tests/functional/lang/parse-fail-patterns-1.err.exp
new file mode 100644
index 000000000..634a04aaa
--- /dev/null
+++ b/tests/functional/lang/parse-fail-patterns-1.err.exp
@@ -0,0 +1,7 @@
+error: duplicate formal function argument 'args'
+
+ at «stdin»:1:1:
+
+ 1| args@{args, x, y, z}: x
+ | ^
+ 2|
diff --git a/tests/functional/lang/parse-fail-patterns-1.nix b/tests/functional/lang/parse-fail-patterns-1.nix
new file mode 100644
index 000000000..7b4061641
--- /dev/null
+++ b/tests/functional/lang/parse-fail-patterns-1.nix
@@ -0,0 +1 @@
+args@{args, x, y, z}: x
diff --git a/tests/functional/lang/parse-fail-regression-20060610.err.exp b/tests/functional/lang/parse-fail-regression-20060610.err.exp
new file mode 100644
index 000000000..167d01e85
--- /dev/null
+++ b/tests/functional/lang/parse-fail-regression-20060610.err.exp
@@ -0,0 +1,8 @@
+error: undefined variable 'gcc'
+
+ at «stdin»:8:12:
+
+ 7|
+ 8| body = ({
+ | ^
+ 9| inherit gcc;
diff --git a/tests/functional/lang/parse-fail-regression-20060610.nix b/tests/functional/lang/parse-fail-regression-20060610.nix
new file mode 100644
index 000000000..b1934f7e1
--- /dev/null
+++ b/tests/functional/lang/parse-fail-regression-20060610.nix
@@ -0,0 +1,11 @@
+let {
+ x =
+ {gcc}:
+ {
+ inherit gcc;
+ };
+
+ body = ({
+ inherit gcc;
+ }).gcc;
+}
diff --git a/tests/functional/lang/parse-fail-undef-var-2.err.exp b/tests/functional/lang/parse-fail-undef-var-2.err.exp
new file mode 100644
index 000000000..77c96bbd2
--- /dev/null
+++ b/tests/functional/lang/parse-fail-undef-var-2.err.exp
@@ -0,0 +1,7 @@
+error: syntax error, unexpected ':', expecting '}'
+
+ at «stdin»:3:13:
+
+ 2|
+ 3| f = {x, y :
+ | ^
diff --git a/tests/functional/lang/parse-fail-undef-var-2.nix b/tests/functional/lang/parse-fail-undef-var-2.nix
new file mode 100644
index 000000000..c10a52b1e
--- /dev/null
+++ b/tests/functional/lang/parse-fail-undef-var-2.nix
@@ -0,0 +1,7 @@
+let {
+
+ f = {x, y : ["baz" "bar" z "bat"]}: x + y;
+
+ body = f {x = "foo"; y = "bar";};
+
+}
diff --git a/tests/functional/lang/parse-fail-undef-var.err.exp b/tests/functional/lang/parse-fail-undef-var.err.exp
new file mode 100644
index 000000000..48e88747f
--- /dev/null
+++ b/tests/functional/lang/parse-fail-undef-var.err.exp
@@ -0,0 +1,7 @@
+error: undefined variable 'y'
+
+ at «stdin»:1:4:
+
+ 1| x: y
+ | ^
+ 2|
diff --git a/tests/functional/lang/parse-fail-undef-var.nix b/tests/functional/lang/parse-fail-undef-var.nix
new file mode 100644
index 000000000..7b6300811
--- /dev/null
+++ b/tests/functional/lang/parse-fail-undef-var.nix
@@ -0,0 +1 @@
+x: y
diff --git a/tests/functional/lang/parse-fail-utf8.err.exp b/tests/functional/lang/parse-fail-utf8.err.exp
new file mode 100644
index 000000000..6087479a3
--- /dev/null
+++ b/tests/functional/lang/parse-fail-utf8.err.exp
@@ -0,0 +1,6 @@
+error: syntax error, unexpected invalid token, expecting end of file
+
+ at «stdin»:1:5:
+
+ 1| 123
+ | ^
diff --git a/tests/functional/lang/parse-fail-utf8.nix b/tests/functional/lang/parse-fail-utf8.nix
new file mode 100644
index 000000000..34948d48a
--- /dev/null
+++ b/tests/functional/lang/parse-fail-utf8.nix
@@ -0,0 +1 @@
+123 é 4
diff --git a/tests/functional/lang/parse-okay-1.exp b/tests/functional/lang/parse-okay-1.exp
new file mode 100644
index 000000000..d5ab5f18a
--- /dev/null
+++ b/tests/functional/lang/parse-okay-1.exp
@@ -0,0 +1 @@
+({ x, y, z }: ((x + y) + z))
diff --git a/tests/functional/lang/parse-okay-1.nix b/tests/functional/lang/parse-okay-1.nix
new file mode 100644
index 000000000..23a58ed10
--- /dev/null
+++ b/tests/functional/lang/parse-okay-1.nix
@@ -0,0 +1 @@
+{x, y, z}: x + y + z
diff --git a/tests/functional/lang/parse-okay-crlf.exp b/tests/functional/lang/parse-okay-crlf.exp
new file mode 100644
index 000000000..4213609fc
--- /dev/null
+++ b/tests/functional/lang/parse-okay-crlf.exp
@@ -0,0 +1 @@
+rec { foo = "multi\nline\n string\n test\r"; x = y; y = 123; z = 456; }
diff --git a/tests/functional/lang/parse-okay-crlf.nix b/tests/functional/lang/parse-okay-crlf.nix
new file mode 100644
index 000000000..21518d4c6
--- /dev/null
+++ b/tests/functional/lang/parse-okay-crlf.nix
@@ -0,0 +1,17 @@
+rec {
+
+ /* Dit is
+ een test. */
+
+ x =
+ # Dit is een test. y;
+
+ y = 123;
+
+ # CR or CR/LF (but not explicit \r's) in strings should be
+ # translated to LF.
+ foo = "multi line
+ string
+ test\r";
+
+ z = 456; }
diff --git a/tests/functional/lang/parse-okay-dup-attrs-5.exp b/tests/functional/lang/parse-okay-dup-attrs-5.exp
new file mode 100644
index 000000000..88b0b036f
--- /dev/null
+++ b/tests/functional/lang/parse-okay-dup-attrs-5.exp
@@ -0,0 +1 @@
+{ services = { ssh = { enable = true; port = 23; }; }; }
diff --git a/tests/functional/lang/parse-okay-dup-attrs-5.nix b/tests/functional/lang/parse-okay-dup-attrs-5.nix
new file mode 100644
index 000000000..f4b9efd0c
--- /dev/null
+++ b/tests/functional/lang/parse-okay-dup-attrs-5.nix
@@ -0,0 +1,4 @@
+{
+ services.ssh = { enable = true; };
+ services.ssh.port = 23;
+}
diff --git a/tests/functional/lang/parse-okay-dup-attrs-6.exp b/tests/functional/lang/parse-okay-dup-attrs-6.exp
new file mode 100644
index 000000000..88b0b036f
--- /dev/null
+++ b/tests/functional/lang/parse-okay-dup-attrs-6.exp
@@ -0,0 +1 @@
+{ services = { ssh = { enable = true; port = 23; }; }; }
diff --git a/tests/functional/lang/parse-okay-dup-attrs-6.nix b/tests/functional/lang/parse-okay-dup-attrs-6.nix
new file mode 100644
index 000000000..ae6d7a769
--- /dev/null
+++ b/tests/functional/lang/parse-okay-dup-attrs-6.nix
@@ -0,0 +1,4 @@
+{
+ services.ssh.port = 23;
+ services.ssh = { enable = true; };
+}
diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-1.exp b/tests/functional/lang/parse-okay-mixed-nested-attrs-1.exp
new file mode 100644
index 000000000..89c66f760
--- /dev/null
+++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-1.exp
@@ -0,0 +1 @@
+{ x = { q = 3; y = 3; z = 3; }; }
diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-1.nix b/tests/functional/lang/parse-okay-mixed-nested-attrs-1.nix
new file mode 100644
index 000000000..fd1001c8c
--- /dev/null
+++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-1.nix
@@ -0,0 +1,4 @@
+{
+ x = { y = 3; z = 3; };
+ x.q = 3;
+}
diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-2.exp b/tests/functional/lang/parse-okay-mixed-nested-attrs-2.exp
new file mode 100644
index 000000000..89c66f760
--- /dev/null
+++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-2.exp
@@ -0,0 +1 @@
+{ x = { q = 3; y = 3; z = 3; }; }
diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-2.nix b/tests/functional/lang/parse-okay-mixed-nested-attrs-2.nix
new file mode 100644
index 000000000..ad066b680
--- /dev/null
+++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-2.nix
@@ -0,0 +1,4 @@
+{
+ x.q = 3;
+ x = { y = 3; z = 3; };
+}
diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-3.exp b/tests/functional/lang/parse-okay-mixed-nested-attrs-3.exp
new file mode 100644
index 000000000..b89a59734
--- /dev/null
+++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-3.exp
@@ -0,0 +1 @@
+{ services = { httpd = { enable = true; }; ssh = { enable = true; port = 123; }; }; }
diff --git a/tests/functional/lang/parse-okay-mixed-nested-attrs-3.nix b/tests/functional/lang/parse-okay-mixed-nested-attrs-3.nix
new file mode 100644
index 000000000..45a33e480
--- /dev/null
+++ b/tests/functional/lang/parse-okay-mixed-nested-attrs-3.nix
@@ -0,0 +1,7 @@
+{
+ services.ssh.enable = true;
+ services.ssh = { port = 123; };
+ services = {
+ httpd.enable = true;
+ };
+}
diff --git a/tests/functional/lang/parse-okay-regression-20041027.exp b/tests/functional/lang/parse-okay-regression-20041027.exp
new file mode 100644
index 000000000..9df7219e4
--- /dev/null
+++ b/tests/functional/lang/parse-okay-regression-20041027.exp
@@ -0,0 +1 @@
+({ fetchurl, stdenv }: ((stdenv).mkDerivation { name = "libXi-6.0.1"; src = (fetchurl { md5 = "7e935a42428d63a387b3c048be0f2756"; url = "http://freedesktop.org/~xlibs/release/libXi-6.0.1.tar.bz2"; }); }))
diff --git a/tests/functional/lang/parse-okay-regression-20041027.nix b/tests/functional/lang/parse-okay-regression-20041027.nix
new file mode 100644
index 000000000..ae2e256ee
--- /dev/null
+++ b/tests/functional/lang/parse-okay-regression-20041027.nix
@@ -0,0 +1,11 @@
+{stdenv, fetchurl /* pkgconfig, libX11 */ }:
+
+stdenv.mkDerivation {
+ name = "libXi-6.0.1";
+ src = fetchurl {
+ url = http://freedesktop.org/~xlibs/release/libXi-6.0.1.tar.bz2;
+ md5 = "7e935a42428d63a387b3c048be0f2756";
+ };
+/* buildInputs = [pkgconfig];
+ propagatedBuildInputs = [libX11]; */
+}
diff --git a/tests/functional/lang/parse-okay-regression-751.exp b/tests/functional/lang/parse-okay-regression-751.exp
new file mode 100644
index 000000000..e2ed886fe
--- /dev/null
+++ b/tests/functional/lang/parse-okay-regression-751.exp
@@ -0,0 +1 @@
+(let const = (a: "const"); in ((const { x = "q"; })))
diff --git a/tests/functional/lang/parse-okay-regression-751.nix b/tests/functional/lang/parse-okay-regression-751.nix
new file mode 100644
index 000000000..05c78b301
--- /dev/null
+++ b/tests/functional/lang/parse-okay-regression-751.nix
@@ -0,0 +1,2 @@
+let const = a: "const"; in
+''${ const { x = "q"; }}''
diff --git a/tests/functional/lang/parse-okay-subversion.exp b/tests/functional/lang/parse-okay-subversion.exp
new file mode 100644
index 000000000..4168ee8bf
--- /dev/null
+++ b/tests/functional/lang/parse-okay-subversion.exp
@@ -0,0 +1 @@
+({ fetchurl, localServer ? false, httpServer ? false, sslSupport ? false, pythonBindings ? false, javaSwigBindings ? false, javahlBindings ? false, stdenv, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null }: assert (expat != null); assert (localServer -> (db4 != null)); assert (httpServer -> ((httpd != null) && ((httpd).expat == expat))); assert (sslSupport -> ((openssl != null) && (httpServer -> ((httpd).openssl == openssl)))); assert (pythonBindings -> ((swig != null) && (swig).pythonSupport)); assert (javaSwigBindings -> ((swig != null) && (swig).javaSupport)); assert (javahlBindings -> (j2sdk != null)); ((stdenv).mkDerivation { builder = /foo/bar; db4 = (if localServer then db4 else null); inherit expat ; inherit httpServer ; httpd = (if httpServer then httpd else null); j2sdk = (if javaSwigBindings then (swig).j2sdk else (if javahlBindings then j2sdk else null)); inherit javaSwigBindings ; inherit javahlBindings ; inherit localServer ; name = "subversion-1.1.1"; openssl = (if sslSupport then openssl else null); patches = (if javahlBindings then [ (/javahl.patch) ] else [ ]); python = (if pythonBindings then (swig).python else null); inherit pythonBindings ; src = (fetchurl { md5 = "a180c3fe91680389c210c99def54d9e0"; url = "http://subversion.tigris.org/tarballs/subversion-1.1.1.tar.bz2"; }); inherit sslSupport ; swig = (if (pythonBindings || javaSwigBindings) then swig else null); }))
diff --git a/tests/functional/lang/parse-okay-subversion.nix b/tests/functional/lang/parse-okay-subversion.nix
new file mode 100644
index 000000000..356272815
--- /dev/null
+++ b/tests/functional/lang/parse-okay-subversion.nix
@@ -0,0 +1,43 @@
+{ localServer ? false
+, httpServer ? false
+, sslSupport ? false
+, pythonBindings ? false
+, javaSwigBindings ? false
+, javahlBindings ? false
+, stdenv, fetchurl
+, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null
+}:
+
+assert expat != null;
+assert localServer -> db4 != null;
+assert httpServer -> httpd != null && httpd.expat == expat;
+assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl);
+assert pythonBindings -> swig != null && swig.pythonSupport;
+assert javaSwigBindings -> swig != null && swig.javaSupport;
+assert javahlBindings -> j2sdk != null;
+
+stdenv.mkDerivation {
+ name = "subversion-1.1.1";
+
+ builder = /foo/bar;
+ src = fetchurl {
+ url = http://subversion.tigris.org/tarballs/subversion-1.1.1.tar.bz2;
+ md5 = "a180c3fe91680389c210c99def54d9e0";
+ };
+
+ # This is a hopefully temporary fix for the problem that
+ # libsvnjavahl.so isn't linked against libstdc++, which causes
+ # loading the library into the JVM to fail.
+ patches = if javahlBindings then [/javahl.patch] else [];
+
+ openssl = if sslSupport then openssl else null;
+ httpd = if httpServer then httpd else null;
+ db4 = if localServer then db4 else null;
+ swig = if pythonBindings || javaSwigBindings then swig else null;
+ python = if pythonBindings then swig.python else null;
+ j2sdk = if javaSwigBindings then swig.j2sdk else
+ if javahlBindings then j2sdk else null;
+
+ inherit expat localServer httpServer sslSupport
+ pythonBindings javaSwigBindings javahlBindings;
+}
diff --git a/tests/functional/lang/parse-okay-url.exp b/tests/functional/lang/parse-okay-url.exp
new file mode 100644
index 000000000..e5f0829b0
--- /dev/null
+++ b/tests/functional/lang/parse-okay-url.exp
@@ -0,0 +1 @@
+[ ("x:x") ("https://svn.cs.uu.nl:12443/repos/trace/trunk") ("http://www2.mplayerhq.hu/MPlayer/releases/fonts/font-arial-iso-8859-1.tar.bz2") ("http://losser.st-lab.cs.uu.nl/~armijn/.nix/gcc-3.3.4-static-nix.tar.gz") ("http://fpdownload.macromedia.com/get/shockwave/flash/english/linux/7.0r25/install_flash_player_7_linux.tar.gz") ("https://ftp5.gwdg.de/pub/linux/archlinux/extra/os/x86_64/unzip-6.0-14-x86_64.pkg.tar.zst") ("ftp://ftp.gtk.org/pub/gtk/v1.2/gtk+-1.2.10.tar.gz") ]
diff --git a/tests/functional/lang/parse-okay-url.nix b/tests/functional/lang/parse-okay-url.nix
new file mode 100644
index 000000000..08de27d0a
--- /dev/null
+++ b/tests/functional/lang/parse-okay-url.nix
@@ -0,0 +1,8 @@
+[ x:x
+ https://svn.cs.uu.nl:12443/repos/trace/trunk
+ http://www2.mplayerhq.hu/MPlayer/releases/fonts/font-arial-iso-8859-1.tar.bz2
+ http://losser.st-lab.cs.uu.nl/~armijn/.nix/gcc-3.3.4-static-nix.tar.gz
+ http://fpdownload.macromedia.com/get/shockwave/flash/english/linux/7.0r25/install_flash_player_7_linux.tar.gz
+ https://ftp5.gwdg.de/pub/linux/archlinux/extra/os/x86_64/unzip-6.0-14-x86_64.pkg.tar.zst
+ ftp://ftp.gtk.org/pub/gtk/v1.2/gtk+-1.2.10.tar.gz
+]
diff --git a/tests/functional/lang/readDir/bar b/tests/functional/lang/readDir/bar
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/functional/lang/readDir/bar
diff --git a/tests/functional/lang/readDir/foo/git-hates-directories b/tests/functional/lang/readDir/foo/git-hates-directories
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/functional/lang/readDir/foo/git-hates-directories
diff --git a/tests/functional/lang/readDir/ldir b/tests/functional/lang/readDir/ldir
new file mode 120000
index 000000000..191028156
--- /dev/null
+++ b/tests/functional/lang/readDir/ldir
@@ -0,0 +1 @@
+foo \ No newline at end of file
diff --git a/tests/functional/lang/readDir/linked b/tests/functional/lang/readDir/linked
new file mode 120000
index 000000000..c503f86a0
--- /dev/null
+++ b/tests/functional/lang/readDir/linked
@@ -0,0 +1 @@
+foo/git-hates-directories \ No newline at end of file