about summary refs log tree commit diff
path: root/tvix/eval/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src/tests')
-rw-r--r--tvix/eval/src/tests/mod.rs181
-rw-r--r--tvix/eval/src/tests/nix_tests/README.md8
-rw-r--r--tvix/eval/src/tests/nix_tests/binary-databin0 -> 1024 bytes
-rw-r--r--tvix/eval/src/tests/nix_tests/data1
-rw-r--r--tvix/eval/src/tests/nix_tests/dir1/a.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/dir2/a.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/dir2/b.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/dir3/a.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/dir3/b.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/dir3/c.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/dir4/a.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/dir4/c.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-abort.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-assert.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-bad-antiquote-1.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-bad-antiquote-3.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-blackhole.nix-disabled5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-deepseq.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-division-by-zero-float.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-division-by-zero-int.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-hashfile-missing.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-missing-arg.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-path-slash.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-remove.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-seq.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-substring.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-fail-to-path.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-any-all.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-any-all.nix11
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-arithmetic.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-arithmetic.nix59
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrnames.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrnames.nix11
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs2.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs2.nix10
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs3.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs3.nix22
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs4.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs4.nix7
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs5.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-attrs5.nix21
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-1.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-1.nix2
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-2.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-2.nix2
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-builtins-add.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-builtins-add.nix8
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-builtins.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-builtins.nix12
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-callable-attrs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-callable-attrs.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-catattrs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-catattrs.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-closure.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-closure.nix13
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-comments.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-comments.nix59
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-concat.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-concat.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-concatmap.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-concatmap.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-concatstringssep.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-concatstringssep.nix8
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-deepseq.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-deepseq.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-delayed-with-inherit.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-delayed-with-inherit.nix24
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-2.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-2.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-bare.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-bare.nix17
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs.nix17
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-elem.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-elem.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-empty-args.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-empty-args.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-eq.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-eq.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-filter.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-filter.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-flatten.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-flatten.nix8
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-float.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-float.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-foldlStrict.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-foldlStrict.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-fromTOML.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-fromTOML.nix208
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-fromjson-escapes.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-fromjson-escapes.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-fromjson.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-fromjson.nix35
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-hash.exp0
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-if.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-if.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-ind-string.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-ind-string.nix128
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-let.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-let.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-list.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-list.nix7
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-listtoattrs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-listtoattrs.nix11
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-logic.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-logic.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-map.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-map.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-mapattrs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-mapattrs.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-nested-with.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-nested-with.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-new-let.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-new-let.nix14
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-null-dynamic-attrs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-null-dynamic-attrs.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-partition.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-partition.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-pathexists.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-pathexists.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-patterns.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-patterns.nix16
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-readfile.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-readfile.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-redefine-builtin.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-redefine-builtin.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-regex-match.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-regex-match.nix29
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-regex-split.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-regex-split.nix48
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-regression-20220122.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-regression-20220122.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-regression-20220125.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-regression-20220125.nix2
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-remove.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-remove.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-replacestrings.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-replacestrings.nix11
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-1.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-1.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-2.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-2.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-3.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-3.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-4.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-4.nix10
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-6.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-6.nix7
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-7.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-scope-7.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-seq.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-seq.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-sort.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-sort.nix20
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-splitversion.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-splitversion.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-string.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-string.nix12
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-strings-as-attrs-names.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-strings-as-attrs-names.nix20
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-substring.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-substring.nix21
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-tail-call-1.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-tail-call-1.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-tojson.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-tojson.nix13
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-toxml.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-toxml.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-toxml2.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-toxml2.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-tryeval.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-tryeval.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-types.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-types.nix37
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-versions.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-versions.nix43
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-with.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/eval-okay-with.nix19
-rw-r--r--tvix/eval/src/tests/nix_tests/imported.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/imported2.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/lib.nix61
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-bad-antiquote-2.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-nonexist-path.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-scope-5.nix10
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-undeclared-arg.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-attrs6.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-attrs6.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.flags1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.nix15
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-closure.exp.xml343
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context-introspection.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context-introspection.nix24
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-curpos.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-curpos.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-delayed-with.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-delayed-with.nix29
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-eq-derivations.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-eq-derivations.nix10
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-floor-ceil.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-floor-ceil.nix9
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-functionargs.exp.xml15
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-functionargs.nix80
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-functionargs.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-functionargs.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-undefined.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-undefined.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos.nix6
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getenv.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getenv.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-groupBy.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-groupBy.nix5
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashfile.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashfile.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashstring.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashstring.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-import.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-import.nix11
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-overrides.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-overrides.nix9
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-path.nix7
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.nix.disabled1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.flags1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.nix10
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-xml.exp.xml52
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-xml.nix21
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-zipAttrsWith.exp1
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-zipAttrsWith.nix9
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/readDir/bar0
-rw-r--r--tvix/eval/src/tests/nix_tests/notyetpassing/readDir/foo/git-hates-directories0
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-1.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-2.nix13
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-3.nix13
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-4.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-7.nix9
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-dup-formals.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-eof-in-string.nix3
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-mixed-nested-attrs1.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-mixed-nested-attrs2.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-patterns-1.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-regression-20060610.nix11
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-uft8.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-undef-var-2.nix7
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-fail-undef-var.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-1.nix1
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-crlf.nix17
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-dup-attrs-5.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-dup-attrs-6.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-1.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-2.nix4
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-3.nix7
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-regression-20041027.nix11
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-regression-751.nix2
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-subversion.nix43
-rw-r--r--tvix/eval/src/tests/nix_tests/parse-okay-url.nix8
-rw-r--r--tvix/eval/src/tests/one_offs.rs36
-rw-r--r--tvix/eval/src/tests/tvix_tests/README.md19
-rw-r--r--tvix/eval/src/tests/tvix_tests/directory/default.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-builtins-thunk-error.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-builtins-tojson-tostring-notcallable.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-builtins-tojson-tostring-strong.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-closed-formals.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-deep-forced-thunk-error.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-deepseq.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-foldlStrict-strict-op-application.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-force-before-value-pointer-equality.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-getEnv-coercion.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-infinite-recursion.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-outer-value-never-pointer-equal.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-parsedrvname-coerce.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-remove.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-seq.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-access-strange-identifier.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-access-strange-identifier.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.nix9
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-float.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-float.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-int.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-int.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-assert-thunk-condition.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-assert-thunk-condition.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-inherit-literal.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-inherit-literal.nix2
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-simple-inherit.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-simple-inherit.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-lhs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-lhs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-rhs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-rhs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-kv-lhs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-kv-lhs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-basenameof.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-basenameof.nix10
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-add.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-add.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-all.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-all.nix15
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-any.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-any.nix15
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrnames.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrnames.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrvalues.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrvalues.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitand.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitand.nix10
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitor.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitor.nix10
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitxor.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitxor.nix12
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-builtins.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-builtins.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-catAttrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-catAttrs.nix10
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-compareVersions.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-compareVersions.nix46
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-concat-lists.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-concat-lists.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.nix11
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-elemat.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-elemat.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-filter.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-filter.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-getattr.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-getattr.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-groupby-thunk.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-groupby-thunk.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-hasattr.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-hasattr.nix9
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-head.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-head.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-length.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-length.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-lessThan.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-lessThan.nix15
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.nix19
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-mul.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-mul.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-partition.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-partition.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-splitVersion.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-splitVersion.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-string-length.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-string-length.nix10
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-sub.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-sub.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-coerce.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-coerce.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring.nix18
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tail.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tail.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-thunked-function-calls.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-thunked-function-calls.nix31
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-toString.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-toString.nix23
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-literals.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-literals.nix11
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath-nested.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath-nested.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-thunks.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-thunks.nix9
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-tostring.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-tostring.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-of.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-of.nix22
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-predicates.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-predicates.nix34
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-ceil.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-ceil.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-closure-pointer-compare.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-closure-pointer-compare.nix14
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-closure-self.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-closure-self.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-closure-with-shadowing.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-closure-with-shadowing.nix14
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-false.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-false.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-true.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-true.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-false.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-false.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-true.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-true.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-false.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-false.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-true.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-true.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-false.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-false.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-true.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-true.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-coerce-opadd.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-coerce-opadd.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-compare-lists.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-compare-lists.nix17
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-concat-lists.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-concat-lists.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-concat-strings.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-concat-strings.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-concatmap.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-concatmap.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-concatstringssep.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-concatstringssep.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-contains-nested-non-set.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-contains-nested-non-set.nix3
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix3
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-attrs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with-closure.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with-closure.nix18
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deepseq.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deepseq.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deferred-with.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-deferred-with.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-dirof.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-dirof.nix10
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-elem.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-elem.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-eq-float.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-eq-float.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-eq-int.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-eq-int.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-eq-nested-list.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-eq-nested-list.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-escapify-integer-keys.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-escapify-integer-keys.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-fib.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-fib.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-fix.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-fix.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-float-repr.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-float-repr.nix2
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-floor.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-floor.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-elements.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-elements.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-initial-accumulator.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-initial-accumulator.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-fromjson-escapes.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-fromjson-escapes.nix3
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-fromjson.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-fromjson.nix24
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-functionargs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-functionargs.nix80
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-functor-call.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-functor-call.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-genlist.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-genlist.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.nix30
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-import.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-import.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-inherit-string-ident.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-inherit-string-ident.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals-deferred.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals-deferred.nix3
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals.nix3
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-intersectattrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-intersectattrs.nix3
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lambda-identity.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lambda-identity.nix2
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-late-binding-closure.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-late-binding-closure.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-late-binding.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-late-binding.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lazy-assert.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lazy-assert.nix8
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.nix15
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-fix.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-fix.nix9
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-in-with.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-in-with.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-identifiers.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-identifiers.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit-from-later-bound.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit-from-later-bound.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix12
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-sibling-access.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-sibling-access.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit-mixed.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit-mixed.nix20
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit.nix9
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-listtoattrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-listtoattrs.nix15
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-manual-rec.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-manual-rec.nix9
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-attrs.nix9
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-rec-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-rec-attrs.nix12
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-multiline-string.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-multiline-string.nix2
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-multiple-nested-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-multiple-nested-attrs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-mutually-recursive-let-binding.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-mutually-recursive-let-binding.nix14
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-ne-int.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-ne-int.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-ne-string.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-ne-string.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-closure.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-closure.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-deferred-upvalue.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-deferred-upvalue.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.nix26
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-let.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-let.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-rec.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-rec.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-let-slots.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-let-slots.nix17
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-let.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-let.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-poisoning.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-poisoning.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-set-thunks.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-set-thunks.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-siblings.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-siblings.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-thunks.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-thunks.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-with.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nested-with.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nix-version-cmp.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-nix-version-cmp.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-observe-infinite-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-observe-infinite-attrs.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-optimised-bools.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-optimised-bools.nix21
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-default.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-default.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested-default.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested-default.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.nix2
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-or-operator.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-overlapping-nested-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-overlapping-nested-attrs.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-parsedrvname.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-parsedrvname.nix12
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-pathexists.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-pathexists.nix2
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-poisoned-scopes.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-poisoned-scopes.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-readDir.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-readDir.nix.disabled1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-readfile.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-readfile.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-rec-dynamic-keys.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-rec-dynamic-keys.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-rec-nested-access.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-rec-nested-access.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-recursive-attrs-all-features.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-recursive-attrs-all-features.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-regex-match.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-regex-match.nix29
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-remove.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-remove.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-repeated-list-to-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-repeated-list-to-attrs.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-seq.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-seq.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-closure.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-closure.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-interpol.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-interpol.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-let.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-let.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-nested-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-nested-attrs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-recursive-attrs.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-recursive-attrs.nix4
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-with.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-simple-with.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-stable-sort.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-stable-sort.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-functor.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-functor.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-string-interpolation.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-string-interpolation.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-with.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-thunked-with.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.nix10
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-tryeval.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-tryeval.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-unpoison-scope.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-unpoison-scope.nix7
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-useless-inherit-with.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-useless-inherit-with.nix15
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-compare.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-compare.nix6
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-equality.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-equality.nix46
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-with-closure.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-with-closure.nix5
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-with-in-dynamic-key.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-with-in-dynamic-key.nix12
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-with-in-list.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-with-in-list.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-bool-false.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-bool-true.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-dollar-escape.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-empty-attrs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-empty-list.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-flat-attrs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-float.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-heterogeneous-list.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-homogeneous-float-list.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-homogeneous-int-list.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-homogeneous-string-list.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-int.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-kv-attrs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-nested-attrs.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-null.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-signed-float.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-signed-int.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-string.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/lib.nix61
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-minimal-2.3-builtins.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-minimal-2.3-builtins.nix35
-rw-r--r--tvix/eval/src/tests/tvix_tests/readDir/bar0
-rw-r--r--tvix/eval/src/tests/tvix_tests/readDir/foo/.keep0
664 files changed, 4316 insertions, 0 deletions
diff --git a/tvix/eval/src/tests/mod.rs b/tvix/eval/src/tests/mod.rs
new file mode 100644
index 000000000000..f800baf05018
--- /dev/null
+++ b/tvix/eval/src/tests/mod.rs
@@ -0,0 +1,181 @@
+use builtin_macros::builtins;
+use pretty_assertions::assert_eq;
+use test_generator::test_resources;
+
+/// Module for one-off tests which do not follow the rest of the
+/// test layout.
+mod one_offs;
+
+#[builtins]
+mod mock_builtins {
+    //! Builtins which are required by language tests, but should not
+    //! actually exist in //tvix/eval.
+    use crate::generators::GenCo;
+    use crate::*;
+    use genawaiter::rc::Gen;
+
+    #[builtin("derivation")]
+    async fn builtin_derivation(co: GenCo, input: Value) -> Result<Value, ErrorKind> {
+        let input = input.to_attrs()?;
+        let attrs = input.update(NixAttrs::from_iter(
+            [
+                (
+                    "outPath",
+                    "/nix/store/00000000000000000000000000000000-mock",
+                ),
+                (
+                    "drvPath",
+                    "/nix/store/00000000000000000000000000000000-mock.drv",
+                ),
+                ("type", "derivation"),
+            ]
+            .into_iter(),
+        ));
+
+        Ok(Value::Attrs(Box::new(attrs)))
+    }
+}
+
+fn eval_test(code_path: &str, expect_success: bool) {
+    let base = code_path
+        .strip_suffix("nix")
+        .expect("test files always end in .nix");
+    let exp_path = format!("{}exp", base);
+    let exp_xml_path = std::path::PathBuf::from(format!("{}exp.xml", base));
+
+    let code = std::fs::read_to_string(code_path).expect("should be able to read test code");
+
+    if exp_xml_path.exists() {
+        // We can't test them at the moment because we don't have XML output yet.
+        // Checking for success / failure only is a bit disingenious.
+        return;
+    }
+
+    let mut eval = crate::Evaluation::new_impure(&code, Some(code_path.into()));
+    eval.strict = true;
+    eval.builtins.extend(mock_builtins::builtins());
+
+    let result = eval.evaluate();
+
+    if expect_success && !result.errors.is_empty() {
+        panic!(
+            "{code_path}: evaluation of eval-okay test should succeed, but failed with {:?}",
+            result.errors,
+        );
+    }
+
+    if !expect_success && !result.errors.is_empty() {
+        return;
+    }
+
+    let result_str = result.value.unwrap().to_string();
+
+    if let Ok(exp) = std::fs::read_to_string(exp_path) {
+        if expect_success {
+            assert_eq!(
+                result_str,
+                exp.trim(),
+                "{code_path}: result value representation (left) must match expectation (right)"
+            );
+        } else {
+            assert_ne!(
+                result_str,
+                exp.trim(),
+                "{code_path}: test passed unexpectedly!  consider moving it out of notyetpassing"
+            );
+        }
+    } else if expect_success {
+        panic!("{code_path}: should be able to read test expectation");
+    } else {
+        panic!(
+            "{code_path}: test should have failed, but succeeded with output {}",
+            result_str
+        );
+    }
+}
+
+// identity-* tests contain Nix code snippets which should evaluate to
+// themselves exactly (i.e. literals).
+#[test_resources("src/tests/tvix_tests/identity-*.nix")]
+fn identity(code_path: &str) {
+    let code = std::fs::read_to_string(code_path).expect("should be able to read test code");
+
+    let mut eval = crate::Evaluation::new(&code, None);
+    eval.strict = true;
+    eval.io_handle = Box::new(crate::StdIO);
+
+    let result = eval.evaluate();
+    assert!(
+        result.errors.is_empty(),
+        "evaluation of identity test failed: {:?}",
+        result.errors
+    );
+
+    let result_str = result.value.unwrap().to_string();
+
+    assert_eq!(
+        result_str,
+        code.trim(),
+        "result value representation (left) must match expectation (right)"
+    )
+}
+
+// eval-okay-* tests contain a snippet of Nix code, and an expectation
+// of the produced string output of the evaluator.
+//
+// These evaluations are always supposed to succeed, i.e. all snippets
+// are guaranteed to be valid Nix code.
+#[test_resources("src/tests/tvix_tests/eval-okay-*.nix")]
+fn eval_okay(code_path: &str) {
+    eval_test(code_path, true)
+}
+
+// eval-okay-* tests from the original Nix test suite.
+#[cfg(feature = "nix_tests")]
+#[test_resources("src/tests/nix_tests/eval-okay-*.nix")]
+fn nix_eval_okay(code_path: &str) {
+    eval_test(code_path, true)
+}
+
+// eval-okay-* tests from the original Nix test suite which do not yet pass for tvix
+//
+// Eventually there will be none of these left, and this function
+// will disappear :) Until then, to run these tests, use `cargo test
+// --features expected_failures`.
+//
+// Please don't submit failing tests unless they're in
+// notyetpassing; this makes the test suite much more useful for
+// regression testing, since there should always be zero non-ignored
+// failing tests.
+//
+// Unfortunately test_generator is unmaintained, so the PRs to make
+// it understand #[ignored] has been sitting for two years, so we
+// can't use `cargo test --include-ignored`, which is the normal way
+// of handling this situation.
+//
+//   https://github.com/frehberg/test-generator/pull/10
+//   https://github.com/frehberg/test-generator/pull/8
+#[test_resources("src/tests/nix_tests/notyetpassing/eval-okay-*.nix")]
+fn nix_eval_okay_currently_failing(code_path: &str) {
+    eval_test(code_path, false)
+}
+
+#[test_resources("src/tests/tvix_tests/notyetpassing/eval-okay-*.nix")]
+fn eval_okay_currently_failing(code_path: &str) {
+    eval_test(code_path, false)
+}
+
+// eval-fail-* tests contain a snippet of Nix code, which is
+// expected to fail evaluation.  The exact type of failure
+// (assertion, parse error, etc) is not currently checked.
+#[test_resources("src/tests/tvix_tests/eval-fail-*.nix")]
+fn eval_fail(code_path: &str) {
+    eval_test(code_path, false)
+}
+
+// eval-fail-* tests from the original Nix test suite.
+#[cfg(feature = "nix_tests")]
+#[test_resources("src/tests/nix_tests/eval-fail-*.nix")]
+fn nix_eval_fail(code_path: &str) {
+    eval_test(code_path, false)
+}
diff --git a/tvix/eval/src/tests/nix_tests/README.md b/tvix/eval/src/tests/nix_tests/README.md
new file mode 100644
index 000000000000..357f3547da18
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/README.md
@@ -0,0 +1,8 @@
+These test definitions are taken from the Nix 2.3 code base, they can
+be found upstream at:
+
+  https://github.com/NixOS/nix/tree/2.3.16/tests/lang
+
+These tests follow the licensing directions of Nix 2.3 itself:
+
+  https://github.com/NixOS/nix/blob/2.3.16/COPYING
diff --git a/tvix/eval/src/tests/nix_tests/binary-data b/tvix/eval/src/tests/nix_tests/binary-data
new file mode 100644
index 000000000000..06d740502001
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/binary-data
Binary files differdiff --git a/tvix/eval/src/tests/nix_tests/data b/tvix/eval/src/tests/nix_tests/data
new file mode 100644
index 000000000000..257cc5642cb1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/data
@@ -0,0 +1 @@
+foo
diff --git a/tvix/eval/src/tests/nix_tests/dir1/a.nix b/tvix/eval/src/tests/nix_tests/dir1/a.nix
new file mode 100644
index 000000000000..231f150c579c
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/dir1/a.nix
@@ -0,0 +1 @@
+"a"
diff --git a/tvix/eval/src/tests/nix_tests/dir2/a.nix b/tvix/eval/src/tests/nix_tests/dir2/a.nix
new file mode 100644
index 000000000000..170df520ab68
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/dir2/a.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tvix/eval/src/tests/nix_tests/dir2/b.nix b/tvix/eval/src/tests/nix_tests/dir2/b.nix
new file mode 100644
index 000000000000..19010cc35ca6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/dir2/b.nix
@@ -0,0 +1 @@
+"b"
diff --git a/tvix/eval/src/tests/nix_tests/dir3/a.nix b/tvix/eval/src/tests/nix_tests/dir3/a.nix
new file mode 100644
index 000000000000..170df520ab68
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/dir3/a.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tvix/eval/src/tests/nix_tests/dir3/b.nix b/tvix/eval/src/tests/nix_tests/dir3/b.nix
new file mode 100644
index 000000000000..170df520ab68
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/dir3/b.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tvix/eval/src/tests/nix_tests/dir3/c.nix b/tvix/eval/src/tests/nix_tests/dir3/c.nix
new file mode 100644
index 000000000000..cdf158597eef
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/dir3/c.nix
@@ -0,0 +1 @@
+"c"
diff --git a/tvix/eval/src/tests/nix_tests/dir4/a.nix b/tvix/eval/src/tests/nix_tests/dir4/a.nix
new file mode 100644
index 000000000000..170df520ab68
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/dir4/a.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tvix/eval/src/tests/nix_tests/dir4/c.nix b/tvix/eval/src/tests/nix_tests/dir4/c.nix
new file mode 100644
index 000000000000..170df520ab68
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/dir4/c.nix
@@ -0,0 +1 @@
+"X"
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-abort.nix b/tvix/eval/src/tests/nix_tests/eval-fail-abort.nix
new file mode 100644
index 000000000000..75c51bceb540
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-abort.nix
@@ -0,0 +1 @@
+if true then abort "this should fail" else 1
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-assert.nix b/tvix/eval/src/tests/nix_tests/eval-fail-assert.nix
new file mode 100644
index 000000000000..3b7a1e8bf0c2
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-fail-bad-antiquote-1.nix b/tvix/eval/src/tests/nix_tests/eval-fail-bad-antiquote-1.nix
new file mode 100644
index 000000000000..ffe9c983c26b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-bad-antiquote-1.nix
@@ -0,0 +1 @@
+"${x: x}"
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-bad-antiquote-3.nix b/tvix/eval/src/tests/nix_tests/eval-fail-bad-antiquote-3.nix
new file mode 100644
index 000000000000..65b9d4f505b1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-bad-antiquote-3.nix
@@ -0,0 +1 @@
+''${x: x}''
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-blackhole.nix-disabled b/tvix/eval/src/tests/nix_tests/eval-fail-blackhole.nix-disabled
new file mode 100644
index 000000000000..81133b511c95
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-blackhole.nix-disabled
@@ -0,0 +1,5 @@
+let {
+  body = x;
+  x = y;
+  y = x;
+}
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-deepseq.nix b/tvix/eval/src/tests/nix_tests/eval-fail-deepseq.nix
new file mode 100644
index 000000000000..9baa49b063ec
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-deepseq.nix
@@ -0,0 +1 @@
+builtins.deepSeq { x = abort "foo"; } 456
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-division-by-zero-float.nix b/tvix/eval/src/tests/nix_tests/eval-fail-division-by-zero-float.nix
new file mode 100644
index 000000000000..82dd6873218e
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-division-by-zero-float.nix
@@ -0,0 +1 @@
+1.0 / 0.0
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-division-by-zero-int.nix b/tvix/eval/src/tests/nix_tests/eval-fail-division-by-zero-int.nix
new file mode 100644
index 000000000000..72dca4d5e478
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-division-by-zero-int.nix
@@ -0,0 +1 @@
+1 / 0
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-hashfile-missing.nix b/tvix/eval/src/tests/nix_tests/eval-fail-hashfile-missing.nix
new file mode 100644
index 000000000000..ce098b82380a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-fail-missing-arg.nix b/tvix/eval/src/tests/nix_tests/eval-fail-missing-arg.nix
new file mode 100644
index 000000000000..c4be9797c534
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-missing-arg.nix
@@ -0,0 +1 @@
+({x, y, z}: x + y + z) {x = "foo"; z = "bar";}
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-path-slash.nix b/tvix/eval/src/tests/nix_tests/eval-fail-path-slash.nix
new file mode 100644
index 000000000000..8c2e104c788f
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-fail-remove.nix b/tvix/eval/src/tests/nix_tests/eval-fail-remove.nix
new file mode 100644
index 000000000000..539e0eb0a6f6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-fail-seq.nix b/tvix/eval/src/tests/nix_tests/eval-fail-seq.nix
new file mode 100644
index 000000000000..cddbbfd3261e
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-seq.nix
@@ -0,0 +1 @@
+builtins.seq (abort "foo") 2
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-substring.nix b/tvix/eval/src/tests/nix_tests/eval-fail-substring.nix
new file mode 100644
index 000000000000..f37c2bc0a160
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-substring.nix
@@ -0,0 +1 @@
+builtins.substring (builtins.sub 0 1) 1 "x"
diff --git a/tvix/eval/src/tests/nix_tests/eval-fail-to-path.nix b/tvix/eval/src/tests/nix_tests/eval-fail-to-path.nix
new file mode 100644
index 000000000000..5e322bc31369
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-fail-to-path.nix
@@ -0,0 +1 @@
+builtins.toPath "foo/bar"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-any-all.exp b/tvix/eval/src/tests/nix_tests/eval-okay-any-all.exp
new file mode 100644
index 000000000000..eb273f45b2a6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-any-all.exp
@@ -0,0 +1 @@
+[ false false true true true true false true ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-any-all.nix b/tvix/eval/src/tests/nix_tests/eval-okay-any-all.nix
new file mode 100644
index 000000000000..a3f26ea2aa83
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-arithmetic.exp b/tvix/eval/src/tests/nix_tests/eval-okay-arithmetic.exp
new file mode 100644
index 000000000000..5c54d10b7b47
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-arithmetic.exp
@@ -0,0 +1 @@
+2216
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-arithmetic.nix b/tvix/eval/src/tests/nix_tests/eval-okay-arithmetic.nix
new file mode 100644
index 000000000000..7e9e6a0b666e
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-attrnames.exp b/tvix/eval/src/tests/nix_tests/eval-okay-attrnames.exp
new file mode 100644
index 000000000000..b4aa387e07b8
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-attrnames.exp
@@ -0,0 +1 @@
+"newxfoonewxy"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-attrnames.nix b/tvix/eval/src/tests/nix_tests/eval-okay-attrnames.nix
new file mode 100644
index 000000000000..e5b26e9f2e39
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-attrs.exp b/tvix/eval/src/tests/nix_tests/eval-okay-attrs.exp
new file mode 100644
index 000000000000..45b0f829eb33
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-attrs.exp
@@ -0,0 +1 @@
+987
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-attrs.nix b/tvix/eval/src/tests/nix_tests/eval-okay-attrs.nix
new file mode 100644
index 000000000000..810b31a5da96
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-attrs2.exp b/tvix/eval/src/tests/nix_tests/eval-okay-attrs2.exp
new file mode 100644
index 000000000000..45b0f829eb33
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-attrs2.exp
@@ -0,0 +1 @@
+987
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-attrs2.nix b/tvix/eval/src/tests/nix_tests/eval-okay-attrs2.nix
new file mode 100644
index 000000000000..9e06b83ac1fd
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-attrs3.exp b/tvix/eval/src/tests/nix_tests/eval-okay-attrs3.exp
new file mode 100644
index 000000000000..19de4fdf79f7
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-attrs3.exp
@@ -0,0 +1 @@
+"foo 22 80 itchyxac"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-attrs3.nix b/tvix/eval/src/tests/nix_tests/eval-okay-attrs3.nix
new file mode 100644
index 000000000000..f29de11fe660
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-attrs4.exp b/tvix/eval/src/tests/nix_tests/eval-okay-attrs4.exp
new file mode 100644
index 000000000000..1851731442d3
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-attrs4.exp
@@ -0,0 +1 @@
+[ true false true false false true false false ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-attrs4.nix b/tvix/eval/src/tests/nix_tests/eval-okay-attrs4.nix
new file mode 100644
index 000000000000..43ec81210f38
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-attrs5.exp b/tvix/eval/src/tests/nix_tests/eval-okay-attrs5.exp
new file mode 100644
index 000000000000..ce0430d78081
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-attrs5.exp
@@ -0,0 +1 @@
+[ 123 "foo" 456 456 "foo" "xyzzy" "xyzzy" true ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-attrs5.nix b/tvix/eval/src/tests/nix_tests/eval-okay-attrs5.nix
new file mode 100644
index 000000000000..a4584cd3b398
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-1.exp b/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-1.exp
new file mode 100644
index 000000000000..3e754364cc9c
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-1.exp
@@ -0,0 +1 @@
+"a\nb"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-1.nix b/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-1.nix
new file mode 100644
index 000000000000..7fef3dddd4dd
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-1.nix
@@ -0,0 +1,2 @@
+"a\
+b"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-2.exp b/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-2.exp
new file mode 100644
index 000000000000..3e754364cc9c
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-2.exp
@@ -0,0 +1 @@
+"a\nb"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-2.nix b/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-2.nix
new file mode 100644
index 000000000000..35ddf495c63b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-backslash-newline-2.nix
@@ -0,0 +1,2 @@
+''a''\
+b''
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-builtins-add.exp b/tvix/eval/src/tests/nix_tests/eval-okay-builtins-add.exp
new file mode 100644
index 000000000000..0350b518a7ec
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-builtins-add.exp
@@ -0,0 +1 @@
+[ 5 4 "int" "tt" "float" 4 ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-builtins-add.nix b/tvix/eval/src/tests/nix_tests/eval-okay-builtins-add.nix
new file mode 100644
index 000000000000..c841816222a5
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-builtins.exp b/tvix/eval/src/tests/nix_tests/eval-okay-builtins.exp
new file mode 100644
index 000000000000..0661686d611d
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-builtins.exp
@@ -0,0 +1 @@
+/foo
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-builtins.nix b/tvix/eval/src/tests/nix_tests/eval-okay-builtins.nix
new file mode 100644
index 000000000000..e9d65e88a817
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-callable-attrs.exp b/tvix/eval/src/tests/nix_tests/eval-okay-callable-attrs.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-callable-attrs.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-callable-attrs.nix b/tvix/eval/src/tests/nix_tests/eval-okay-callable-attrs.nix
new file mode 100644
index 000000000000..310a030df004
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-callable-attrs.nix
@@ -0,0 +1 @@
+({ __functor = self: x: self.foo && x; foo = false; } // { foo = true; }) true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-catattrs.exp b/tvix/eval/src/tests/nix_tests/eval-okay-catattrs.exp
new file mode 100644
index 000000000000..b4a1e66d6b8a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-catattrs.exp
@@ -0,0 +1 @@
+[ 1 2 ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-catattrs.nix b/tvix/eval/src/tests/nix_tests/eval-okay-catattrs.nix
new file mode 100644
index 000000000000..2c3dc10da528
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-catattrs.nix
@@ -0,0 +1 @@
+builtins.catAttrs "a" [ { a = 1; } { b = 0; } { a = 2; } ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-closure.exp b/tvix/eval/src/tests/nix_tests/eval-okay-closure.exp
new file mode 100644
index 000000000000..e7dbf978160d
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-closure.nix b/tvix/eval/src/tests/nix_tests/eval-okay-closure.nix
new file mode 100644
index 000000000000..cccd4dc35730
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-comments.exp b/tvix/eval/src/tests/nix_tests/eval-okay-comments.exp
new file mode 100644
index 000000000000..7182dc2f9b8e
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-comments.exp
@@ -0,0 +1 @@
+"abcdefghijklmnopqrstuvwxyz"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-comments.nix b/tvix/eval/src/tests/nix_tests/eval-okay-comments.nix
new file mode 100644
index 000000000000..cb2cce218029
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-concat.exp b/tvix/eval/src/tests/nix_tests/eval-okay-concat.exp
new file mode 100644
index 000000000000..bb4bbd577410
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-concat.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 5 6 7 8 9 ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-concat.nix b/tvix/eval/src/tests/nix_tests/eval-okay-concat.nix
new file mode 100644
index 000000000000..d158a9bf05b9
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-concat.nix
@@ -0,0 +1 @@
+[1 2 3] ++ [4 5 6] ++ [7 8 9]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-concatmap.exp b/tvix/eval/src/tests/nix_tests/eval-okay-concatmap.exp
new file mode 100644
index 000000000000..3b8be7739deb
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-concatmap.exp
@@ -0,0 +1 @@
+[ [ 1 3 5 7 9 ] [ "a" "z" "b" "z" ] ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-concatmap.nix b/tvix/eval/src/tests/nix_tests/eval-okay-concatmap.nix
new file mode 100644
index 000000000000..97da5d37a412
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-concatstringssep.exp b/tvix/eval/src/tests/nix_tests/eval-okay-concatstringssep.exp
new file mode 100644
index 000000000000..93987647ffe6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-concatstringssep.exp
@@ -0,0 +1 @@
+[ "" "foobarxyzzy" "foo, bar, xyzzy" "foo" "" ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-concatstringssep.nix b/tvix/eval/src/tests/nix_tests/eval-okay-concatstringssep.nix
new file mode 100644
index 000000000000..adc4c41bd551
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-deepseq.exp b/tvix/eval/src/tests/nix_tests/eval-okay-deepseq.exp
new file mode 100644
index 000000000000..8d38505c1686
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-deepseq.exp
@@ -0,0 +1 @@
+456
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-deepseq.nix b/tvix/eval/src/tests/nix_tests/eval-okay-deepseq.nix
new file mode 100644
index 000000000000..53aa4b1dc251
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-deepseq.nix
@@ -0,0 +1 @@
+builtins.deepSeq (let as = { x = 123; y = as; }; in as) 456
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-delayed-with-inherit.exp b/tvix/eval/src/tests/nix_tests/eval-okay-delayed-with-inherit.exp
new file mode 100644
index 000000000000..eaacb55c1aff
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-delayed-with-inherit.exp
@@ -0,0 +1 @@
+"b-overridden"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-delayed-with-inherit.nix b/tvix/eval/src/tests/nix_tests/eval-okay-delayed-with-inherit.nix
new file mode 100644
index 000000000000..84b388c27130
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-2.exp b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-2.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-2.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-2.nix b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-2.nix
new file mode 100644
index 000000000000..6d57bf854908
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-2.nix
@@ -0,0 +1 @@
+{ a."${"b"}" = true; a."${"c"}" = false; }.a.b
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-bare.exp b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-bare.exp
new file mode 100644
index 000000000000..df8750afc036
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-bare.exp
@@ -0,0 +1 @@
+{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; }
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-bare.nix b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs-bare.nix
new file mode 100644
index 000000000000..0dbe15e6384c
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs.exp b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs.exp
new file mode 100644
index 000000000000..df8750afc036
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs.exp
@@ -0,0 +1 @@
+{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; }
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs.nix b/tvix/eval/src/tests/nix_tests/eval-okay-dynamic-attrs.nix
new file mode 100644
index 000000000000..ee02ac7e6579
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-elem.exp b/tvix/eval/src/tests/nix_tests/eval-okay-elem.exp
new file mode 100644
index 000000000000..3cf6c0e962f0
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-elem.exp
@@ -0,0 +1 @@
+[ true false 30 ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-elem.nix b/tvix/eval/src/tests/nix_tests/eval-okay-elem.nix
new file mode 100644
index 000000000000..71ea7a4ed03d
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-empty-args.exp b/tvix/eval/src/tests/nix_tests/eval-okay-empty-args.exp
new file mode 100644
index 000000000000..cb5537d5d7ce
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-empty-args.exp
@@ -0,0 +1 @@
+"ab"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-empty-args.nix b/tvix/eval/src/tests/nix_tests/eval-okay-empty-args.nix
new file mode 100644
index 000000000000..78c133afdd94
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-empty-args.nix
@@ -0,0 +1 @@
+({}: {x,y,}: "${x}${y}") {} {x = "a"; y = "b";}
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-eq.exp b/tvix/eval/src/tests/nix_tests/eval-okay-eq.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-eq.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-eq.nix b/tvix/eval/src/tests/nix_tests/eval-okay-eq.nix
new file mode 100644
index 000000000000..73d200b38141
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-eq.nix
@@ -0,0 +1,3 @@
+["foobar" (rec {x = 1; y = x;})]
+==
+[("foo" + "bar") ({x = 1; y = 1;})]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-filter.exp b/tvix/eval/src/tests/nix_tests/eval-okay-filter.exp
new file mode 100644
index 000000000000..355d51c27d8f
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-filter.exp
@@ -0,0 +1 @@
+[ 0 2 4 6 8 10 100 102 104 106 108 110 ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-filter.nix b/tvix/eval/src/tests/nix_tests/eval-okay-filter.nix
new file mode 100644
index 000000000000..85109b0d0eb8
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-flatten.exp b/tvix/eval/src/tests/nix_tests/eval-okay-flatten.exp
new file mode 100644
index 000000000000..b979b2b8b9bc
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-flatten.exp
@@ -0,0 +1 @@
+"1234567"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-flatten.nix b/tvix/eval/src/tests/nix_tests/eval-okay-flatten.nix
new file mode 100644
index 000000000000..fe911e9683e2
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-float.exp b/tvix/eval/src/tests/nix_tests/eval-okay-float.exp
new file mode 100644
index 000000000000..3c50a8adce86
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-float.exp
@@ -0,0 +1 @@
+[ 3.4 3.5 2.5 1.5 ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-float.nix b/tvix/eval/src/tests/nix_tests/eval-okay-float.nix
new file mode 100644
index 000000000000..b2702c7b1668
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-foldlStrict.exp b/tvix/eval/src/tests/nix_tests/eval-okay-foldlStrict.exp
new file mode 100644
index 000000000000..837e12b406f6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-foldlStrict.exp
@@ -0,0 +1 @@
+500500
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-foldlStrict.nix b/tvix/eval/src/tests/nix_tests/eval-okay-foldlStrict.nix
new file mode 100644
index 000000000000..3b87188d243b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-fromTOML.exp b/tvix/eval/src/tests/nix_tests/eval-okay-fromTOML.exp
new file mode 100644
index 000000000000..d0dd3af2c814
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-fromTOML.nix b/tvix/eval/src/tests/nix_tests/eval-okay-fromTOML.nix
new file mode 100644
index 000000000000..963932689942
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-fromjson-escapes.exp b/tvix/eval/src/tests/nix_tests/eval-okay-fromjson-escapes.exp
new file mode 100644
index 000000000000..add5505a8287
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-fromjson-escapes.nix b/tvix/eval/src/tests/nix_tests/eval-okay-fromjson-escapes.nix
new file mode 100644
index 000000000000..f00713507732
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-fromjson.exp b/tvix/eval/src/tests/nix_tests/eval-okay-fromjson.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-fromjson.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-fromjson.nix b/tvix/eval/src/tests/nix_tests/eval-okay-fromjson.nix
new file mode 100644
index 000000000000..e1c0f86cc4e4
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-fromjson.nix
@@ -0,0 +1,35 @@
+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
+          },
+          "Subtitle" : false,
+          "Latitude":  46.2051,
+          "Longitude": 6.0723
+        }
+    }
+  ''
+==
+  { 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;
+        };
+      Subtitle = false;
+      Latitude = 46.2051;
+      Longitude = 6.0723;
+    };
+  }
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-hash.exp b/tvix/eval/src/tests/nix_tests/eval-okay-hash.exp
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-hash.exp
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-if.exp b/tvix/eval/src/tests/nix_tests/eval-okay-if.exp
new file mode 100644
index 000000000000..00750edc07d6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-if.exp
@@ -0,0 +1 @@
+3
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-if.nix b/tvix/eval/src/tests/nix_tests/eval-okay-if.nix
new file mode 100644
index 000000000000..23e4c74d5016
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-if.nix
@@ -0,0 +1 @@
+if "foo" != "f" + "oo" then 1 else if false then 2 else 3
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-ind-string.exp b/tvix/eval/src/tests/nix_tests/eval-okay-ind-string.exp
new file mode 100644
index 000000000000..7862331fa551
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-ind-string.nix b/tvix/eval/src/tests/nix_tests/eval-okay-ind-string.nix
new file mode 100644
index 000000000000..1669dc0648ea
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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: antiquotation 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/tvix/eval/src/tests/nix_tests/eval-okay-let.exp b/tvix/eval/src/tests/nix_tests/eval-okay-let.exp
new file mode 100644
index 000000000000..14e24d419005
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-let.exp
@@ -0,0 +1 @@
+"foobar"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-let.nix b/tvix/eval/src/tests/nix_tests/eval-okay-let.nix
new file mode 100644
index 000000000000..fe118c5282e3
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-let.nix
@@ -0,0 +1,5 @@
+let {
+  x = "foo";
+  y = "bar";
+  body = x + y;
+}
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-list.exp b/tvix/eval/src/tests/nix_tests/eval-okay-list.exp
new file mode 100644
index 000000000000..f784f26d83f4
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-list.exp
@@ -0,0 +1 @@
+"foobarblatest"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-list.nix b/tvix/eval/src/tests/nix_tests/eval-okay-list.nix
new file mode 100644
index 000000000000..d433bcf908ba
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-listtoattrs.exp b/tvix/eval/src/tests/nix_tests/eval-okay-listtoattrs.exp
new file mode 100644
index 000000000000..74abef7bc6ed
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-listtoattrs.exp
@@ -0,0 +1 @@
+"AAbar"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-listtoattrs.nix b/tvix/eval/src/tests/nix_tests/eval-okay-listtoattrs.nix
new file mode 100644
index 000000000000..4186e029b538
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-logic.exp b/tvix/eval/src/tests/nix_tests/eval-okay-logic.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-logic.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-logic.nix b/tvix/eval/src/tests/nix_tests/eval-okay-logic.nix
new file mode 100644
index 000000000000..fbb12794401f
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-logic.nix
@@ -0,0 +1 @@
+assert !false && (true || false) -> true; 1
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-map.exp b/tvix/eval/src/tests/nix_tests/eval-okay-map.exp
new file mode 100644
index 000000000000..dbb64f717b96
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-map.exp
@@ -0,0 +1 @@
+"foobarblabarxyzzybar"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-map.nix b/tvix/eval/src/tests/nix_tests/eval-okay-map.nix
new file mode 100644
index 000000000000..a76c1d811454
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-mapattrs.exp b/tvix/eval/src/tests/nix_tests/eval-okay-mapattrs.exp
new file mode 100644
index 000000000000..3f113f17bab1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-mapattrs.exp
@@ -0,0 +1 @@
+{ x = "x-foo"; y = "y-bar"; }
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-mapattrs.nix b/tvix/eval/src/tests/nix_tests/eval-okay-mapattrs.nix
new file mode 100644
index 000000000000..f075b6275e5a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-nested-with.exp b/tvix/eval/src/tests/nix_tests/eval-okay-nested-with.exp
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-nested-with.exp
@@ -0,0 +1 @@
+2
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-nested-with.nix b/tvix/eval/src/tests/nix_tests/eval-okay-nested-with.nix
new file mode 100644
index 000000000000..ba9d79aa79b1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-nested-with.nix
@@ -0,0 +1,3 @@
+with { x = 1; };
+with { x = 2; };
+x
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-new-let.exp b/tvix/eval/src/tests/nix_tests/eval-okay-new-let.exp
new file mode 100644
index 000000000000..f98b388071c2
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-new-let.exp
@@ -0,0 +1 @@
+"xyzzyfoobar"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-new-let.nix b/tvix/eval/src/tests/nix_tests/eval-okay-new-let.nix
new file mode 100644
index 000000000000..738123141508
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-null-dynamic-attrs.exp b/tvix/eval/src/tests/nix_tests/eval-okay-null-dynamic-attrs.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-null-dynamic-attrs.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-null-dynamic-attrs.nix b/tvix/eval/src/tests/nix_tests/eval-okay-null-dynamic-attrs.nix
new file mode 100644
index 000000000000..b060c0bc9850
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-null-dynamic-attrs.nix
@@ -0,0 +1 @@
+{ ${null} = true; } == {}
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-partition.exp b/tvix/eval/src/tests/nix_tests/eval-okay-partition.exp
new file mode 100644
index 000000000000..cd8b8b020c05
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-partition.nix b/tvix/eval/src/tests/nix_tests/eval-okay-partition.nix
new file mode 100644
index 000000000000..846d2ce49486
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-pathexists.exp b/tvix/eval/src/tests/nix_tests/eval-okay-pathexists.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-pathexists.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-pathexists.nix b/tvix/eval/src/tests/nix_tests/eval-okay-pathexists.nix
new file mode 100644
index 000000000000..50c28ee0cd30
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-pathexists.nix
@@ -0,0 +1,5 @@
+builtins.pathExists (builtins.toPath ./lib.nix)
+&& 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/tvix/eval/src/tests/nix_tests/eval-okay-patterns.exp b/tvix/eval/src/tests/nix_tests/eval-okay-patterns.exp
new file mode 100644
index 000000000000..a4304010fe80
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-patterns.exp
@@ -0,0 +1 @@
+"abcxyzDDDDEFijk"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-patterns.nix b/tvix/eval/src/tests/nix_tests/eval-okay-patterns.nix
new file mode 100644
index 000000000000..96fd25a01517
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-readfile.exp b/tvix/eval/src/tests/nix_tests/eval-okay-readfile.exp
new file mode 100644
index 000000000000..a2c87d0c439f
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-readfile.exp
@@ -0,0 +1 @@
+"builtins.readFile ./eval-okay-readfile.nix\n"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-readfile.nix b/tvix/eval/src/tests/nix_tests/eval-okay-readfile.nix
new file mode 100644
index 000000000000..82f7cb17435a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-readfile.nix
@@ -0,0 +1 @@
+builtins.readFile ./eval-okay-readfile.nix
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-redefine-builtin.exp b/tvix/eval/src/tests/nix_tests/eval-okay-redefine-builtin.exp
new file mode 100644
index 000000000000..c508d5366f70
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-redefine-builtin.exp
@@ -0,0 +1 @@
+false
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-redefine-builtin.nix b/tvix/eval/src/tests/nix_tests/eval-okay-redefine-builtin.nix
new file mode 100644
index 000000000000..df9fc3f37d22
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-redefine-builtin.nix
@@ -0,0 +1,3 @@
+let
+  throw = abort "Error!";
+in (builtins.tryEval <foobaz>).success
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-regex-match.exp b/tvix/eval/src/tests/nix_tests/eval-okay-regex-match.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-regex-match.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-regex-match.nix b/tvix/eval/src/tests/nix_tests/eval-okay-regex-match.nix
new file mode 100644
index 000000000000..273e2590713e
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-regex-split.exp b/tvix/eval/src/tests/nix_tests/eval-okay-regex-split.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-regex-split.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-regex-split.nix b/tvix/eval/src/tests/nix_tests/eval-okay-regex-split.nix
new file mode 100644
index 000000000000..0073e057787d
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220122.exp b/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220122.exp
new file mode 100644
index 000000000000..00750edc07d6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220122.exp
@@ -0,0 +1 @@
+3
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220122.nix b/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220122.nix
new file mode 100644
index 000000000000..694e9a13b7c5
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220122.nix
@@ -0,0 +1 @@
+((_: _) 1) + ((__: __) 2)
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220125.exp b/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220125.exp
new file mode 100644
index 000000000000..00750edc07d6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220125.exp
@@ -0,0 +1 @@
+3
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220125.nix b/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220125.nix
new file mode 100644
index 000000000000..48550237394a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-regression-20220125.nix
@@ -0,0 +1,2 @@
+((__curPosFoo: __curPosFoo) 1) + ((__curPosBar: __curPosBar) 2)
+
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-remove.exp b/tvix/eval/src/tests/nix_tests/eval-okay-remove.exp
new file mode 100644
index 000000000000..8d38505c1686
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-remove.exp
@@ -0,0 +1 @@
+456
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-remove.nix b/tvix/eval/src/tests/nix_tests/eval-okay-remove.nix
new file mode 100644
index 000000000000..4ad5ba897fa7
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-replacestrings.exp b/tvix/eval/src/tests/nix_tests/eval-okay-replacestrings.exp
new file mode 100644
index 000000000000..72e8274d8c58
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-replacestrings.exp
@@ -0,0 +1 @@
+[ "faabar" "fbar" "fubar" "faboor" "fubar" "XaXbXcX" "X" "a_b" ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-replacestrings.nix b/tvix/eval/src/tests/nix_tests/eval-okay-replacestrings.nix
new file mode 100644
index 000000000000..bd8031fc004e
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-replacestrings.nix
@@ -0,0 +1,11 @@
+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")
+]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-1.exp b/tvix/eval/src/tests/nix_tests/eval-okay-scope-1.exp
new file mode 100644
index 000000000000..00750edc07d6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-1.exp
@@ -0,0 +1 @@
+3
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-1.nix b/tvix/eval/src/tests/nix_tests/eval-okay-scope-1.nix
new file mode 100644
index 000000000000..fa38a7174e03
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-1.nix
@@ -0,0 +1,6 @@
+(({x}: x:
+
+  { x = 1;
+    y = x;
+  }
+) {x = 2;} 3).y
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-2.exp b/tvix/eval/src/tests/nix_tests/eval-okay-scope-2.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-2.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-2.nix b/tvix/eval/src/tests/nix_tests/eval-okay-scope-2.nix
new file mode 100644
index 000000000000..eb8b02bc4994
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-2.nix
@@ -0,0 +1,6 @@
+((x: {x}:
+  rec {
+    x = 1;
+    y = x;
+  }
+) 2 {x = 3;}).y
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-3.exp b/tvix/eval/src/tests/nix_tests/eval-okay-scope-3.exp
new file mode 100644
index 000000000000..b8626c4cff28
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-3.exp
@@ -0,0 +1 @@
+4
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-3.nix b/tvix/eval/src/tests/nix_tests/eval-okay-scope-3.nix
new file mode 100644
index 000000000000..10d6bc04d830
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-scope-4.exp b/tvix/eval/src/tests/nix_tests/eval-okay-scope-4.exp
new file mode 100644
index 000000000000..00ff03a46c9b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-4.exp
@@ -0,0 +1 @@
+"ccdd"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-4.nix b/tvix/eval/src/tests/nix_tests/eval-okay-scope-4.nix
new file mode 100644
index 000000000000..dc8243bc8546
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-scope-6.exp b/tvix/eval/src/tests/nix_tests/eval-okay-scope-6.exp
new file mode 100644
index 000000000000..00ff03a46c9b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-6.exp
@@ -0,0 +1 @@
+"ccdd"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-6.nix b/tvix/eval/src/tests/nix_tests/eval-okay-scope-6.nix
new file mode 100644
index 000000000000..0995d4e7e7e0
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-scope-7.exp b/tvix/eval/src/tests/nix_tests/eval-okay-scope-7.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-7.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-scope-7.nix b/tvix/eval/src/tests/nix_tests/eval-okay-scope-7.nix
new file mode 100644
index 000000000000..4da02968f6b7
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-scope-7.nix
@@ -0,0 +1,6 @@
+rec {
+  inherit (x) y;
+  x = {
+    y = 1;
+  };
+}.y
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-seq.exp b/tvix/eval/src/tests/nix_tests/eval-okay-seq.exp
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-seq.exp
@@ -0,0 +1 @@
+2
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-seq.nix b/tvix/eval/src/tests/nix_tests/eval-okay-seq.nix
new file mode 100644
index 000000000000..0a9a21c03b62
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-seq.nix
@@ -0,0 +1 @@
+builtins.seq 1 2
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-sort.exp b/tvix/eval/src/tests/nix_tests/eval-okay-sort.exp
new file mode 100644
index 000000000000..899119e20e38
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-sort.nix b/tvix/eval/src/tests/nix_tests/eval-okay-sort.nix
new file mode 100644
index 000000000000..50aa78e40325
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-splitversion.exp b/tvix/eval/src/tests/nix_tests/eval-okay-splitversion.exp
new file mode 100644
index 000000000000..153ceb8186a0
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-splitversion.exp
@@ -0,0 +1 @@
+[ "1" "2" "3" ]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-splitversion.nix b/tvix/eval/src/tests/nix_tests/eval-okay-splitversion.nix
new file mode 100644
index 000000000000..9e5c99d2e7f6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-splitversion.nix
@@ -0,0 +1 @@
+builtins.splitVersion "1.2.3"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-string.exp b/tvix/eval/src/tests/nix_tests/eval-okay-string.exp
new file mode 100644
index 000000000000..63f650f73a3a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-string.nix b/tvix/eval/src/tests/nix_tests/eval-okay-string.nix
new file mode 100644
index 000000000000..47cc989ad46a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-strings-as-attrs-names.exp b/tvix/eval/src/tests/nix_tests/eval-okay-strings-as-attrs-names.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-strings-as-attrs-names.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-strings-as-attrs-names.nix b/tvix/eval/src/tests/nix_tests/eval-okay-strings-as-attrs-names.nix
new file mode 100644
index 000000000000..5e40928dbe31
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-substring.exp b/tvix/eval/src/tests/nix_tests/eval-okay-substring.exp
new file mode 100644
index 000000000000..6aace04b0f57
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-substring.exp
@@ -0,0 +1 @@
+"ooxfoobarybarzobaabbc"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-substring.nix b/tvix/eval/src/tests/nix_tests/eval-okay-substring.nix
new file mode 100644
index 000000000000..424af00d9b3b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-tail-call-1.exp b/tvix/eval/src/tests/nix_tests/eval-okay-tail-call-1.exp
new file mode 100644
index 000000000000..f7393e847d34
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-tail-call-1.exp
@@ -0,0 +1 @@
+100000
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-tail-call-1.nix b/tvix/eval/src/tests/nix_tests/eval-okay-tail-call-1.nix
new file mode 100644
index 000000000000..a3962ce3fdb5
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-tojson.exp b/tvix/eval/src/tests/nix_tests/eval-okay-tojson.exp
new file mode 100644
index 000000000000..e92aae3235f2
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-tojson.nix b/tvix/eval/src/tests/nix_tests/eval-okay-tojson.nix
new file mode 100644
index 000000000000..ce67943bead5
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-toxml.exp b/tvix/eval/src/tests/nix_tests/eval-okay-toxml.exp
new file mode 100644
index 000000000000..828220890ecd
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-toxml.nix b/tvix/eval/src/tests/nix_tests/eval-okay-toxml.nix
new file mode 100644
index 000000000000..068c97a6c1b3
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-toxml2.exp b/tvix/eval/src/tests/nix_tests/eval-okay-toxml2.exp
new file mode 100644
index 000000000000..634a841eb190
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-toxml2.nix b/tvix/eval/src/tests/nix_tests/eval-okay-toxml2.nix
new file mode 100644
index 000000000000..ff1791b30eb5
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-toxml2.nix
@@ -0,0 +1 @@
+builtins.toXML [("a" + "b") 10 (rec {x = "x"; y = x;})]
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-tryeval.exp b/tvix/eval/src/tests/nix_tests/eval-okay-tryeval.exp
new file mode 100644
index 000000000000..2b2e6fa711f4
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-tryeval.nix b/tvix/eval/src/tests/nix_tests/eval-okay-tryeval.nix
new file mode 100644
index 000000000000..629bc440a85a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-types.exp b/tvix/eval/src/tests/nix_tests/eval-okay-types.exp
new file mode 100644
index 000000000000..92a15329935a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-types.nix b/tvix/eval/src/tests/nix_tests/eval-okay-types.nix
new file mode 100644
index 000000000000..9b58be5d1dd4
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-versions.exp b/tvix/eval/src/tests/nix_tests/eval-okay-versions.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-versions.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-versions.nix b/tvix/eval/src/tests/nix_tests/eval-okay-versions.nix
new file mode 100644
index 000000000000..e9111f5f4331
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/eval-okay-with.exp b/tvix/eval/src/tests/nix_tests/eval-okay-with.exp
new file mode 100644
index 000000000000..378c8dc80403
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/eval-okay-with.exp
@@ -0,0 +1 @@
+"xyzzybarxyzzybar"
diff --git a/tvix/eval/src/tests/nix_tests/eval-okay-with.nix b/tvix/eval/src/tests/nix_tests/eval-okay-with.nix
new file mode 100644
index 000000000000..033e8d3aba57
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/imported.nix b/tvix/eval/src/tests/nix_tests/imported.nix
new file mode 100644
index 000000000000..fb39ee4efacd
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/imported2.nix b/tvix/eval/src/tests/nix_tests/imported2.nix
new file mode 100644
index 000000000000..6d0a2992b732
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/imported2.nix
@@ -0,0 +1 @@
+range 6 10
diff --git a/tvix/eval/src/tests/nix_tests/lib.nix b/tvix/eval/src/tests/nix_tests/lib.nix
new file mode 100644
index 000000000000..028a538314b7
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-bad-antiquote-2.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-bad-antiquote-2.nix
new file mode 100644
index 000000000000..3745235ce95e
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-bad-antiquote-2.nix
@@ -0,0 +1 @@
+"${./fnord}"
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-nonexist-path.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-nonexist-path.nix
new file mode 100644
index 000000000000..f2f08107b516
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-scope-5.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-scope-5.nix
new file mode 100644
index 000000000000..f89a65a99be3
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-undeclared-arg.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-undeclared-arg.nix
new file mode 100644
index 000000000000..cafdf1636272
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-fail-undeclared-arg.nix
@@ -0,0 +1 @@
+({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";}
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-attrs6.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-attrs6.exp
new file mode 100644
index 000000000000..b46938032e73
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-attrs6.exp
@@ -0,0 +1 @@
+{ __overrides = { bar = "qux"; }; bar = "qux"; foo = "bar"; }
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-attrs6.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-attrs6.nix
new file mode 100644
index 000000000000..2e5c85483be6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-attrs6.nix
@@ -0,0 +1,4 @@
+rec {
+  "${"foo"}" = "bar";
+   __overrides = { bar = "qux"; };
+}
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.exp
new file mode 100644
index 000000000000..7a8391786a09
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.exp
@@ -0,0 +1 @@
+"xyzzy!xyzzy!foobar"
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.flags b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.flags
new file mode 100644
index 000000000000..217c7a5ae291
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.flags
@@ -0,0 +1 @@
+--arg lib import(nix_tests/lib.nix) --argstr xyzzy xyzzy! -A result
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-autoargs.nix
new file mode 100644
index 000000000000..815f51b1d67a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-closure.exp.xml b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-closure.exp.xml
new file mode 100644
index 000000000000..dffc03a99891
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context-introspection.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context-introspection.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context-introspection.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context-introspection.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context-introspection.nix
new file mode 100644
index 000000000000..43178bd2eef9
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context-introspection.nix
@@ -0,0 +1,24 @@
+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;
+    };
+  };
+
+  legit-context = builtins.getContext "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}";
+
+  constructed-context = builtins.getContext (builtins.appendContext "" desired-context);
+in legit-context == constructed-context
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context.exp
new file mode 100644
index 000000000000..2f535bdbc454
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context.exp
@@ -0,0 +1 @@
+"foo eval-okay-context.nix bar"
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-context.nix
new file mode 100644
index 000000000000..7b9531cfe9e1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-curpos.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-curpos.exp
new file mode 100644
index 000000000000..65fd65b4d01f
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-curpos.exp
@@ -0,0 +1 @@
+[ 3 7 4 9 ]
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-curpos.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-curpos.nix
new file mode 100644
index 000000000000..b79553df0bd3
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-delayed-with.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-delayed-with.exp
new file mode 100644
index 000000000000..8e7c61ab8e77
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-delayed-with.exp
@@ -0,0 +1 @@
+"b-overridden b-overridden a"
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-delayed-with.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-delayed-with.nix
new file mode 100644
index 000000000000..3fb023e1cd42
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-eq-derivations.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-eq-derivations.exp
new file mode 100644
index 000000000000..ec04aab6aeec
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-eq-derivations.exp
@@ -0,0 +1 @@
+[ true true true false ]
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-eq-derivations.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-eq-derivations.nix
new file mode 100644
index 000000000000..d526cb4a2161
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-floor-ceil.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-floor-ceil.exp
new file mode 100644
index 000000000000..81f80420b996
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-floor-ceil.exp
@@ -0,0 +1 @@
+"23;24;23;23"
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-floor-ceil.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-floor-ceil.nix
new file mode 100644
index 000000000000..d76a0d86ea78
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-functionargs.exp.xml b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-functionargs.exp.xml
new file mode 100644
index 000000000000..651f54c36341
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-functionargs.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-functionargs.nix
new file mode 100644
index 000000000000..68dca62ee18d
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-functionargs.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-functionargs.exp
new file mode 100644
index 000000000000..7f9ac40e81b1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-functionargs.exp
@@ -0,0 +1 @@
+{ column = 11; file = "eval-okay-getattrpos-functionargs.nix"; line = 2; }
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-functionargs.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-functionargs.nix
new file mode 100644
index 000000000000..11d6bb0e3ac9
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-undefined.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-undefined.exp
new file mode 100644
index 000000000000..19765bd501b6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-undefined.exp
@@ -0,0 +1 @@
+null
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-undefined.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-undefined.nix
new file mode 100644
index 000000000000..14dd38f7734c
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos-undefined.nix
@@ -0,0 +1 @@
+builtins.unsafeGetAttrPos "abort" builtins
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos.exp
new file mode 100644
index 000000000000..469249bbc646
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos.exp
@@ -0,0 +1 @@
+{ column = 5; file = "eval-okay-getattrpos.nix"; line = 3; }
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getattrpos.nix
new file mode 100644
index 000000000000..ca6b07961547
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getenv.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getenv.exp
new file mode 100644
index 000000000000..14e24d419005
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getenv.exp
@@ -0,0 +1 @@
+"foobar"
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getenv.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getenv.nix
new file mode 100644
index 000000000000..4cfec5f553d9
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-getenv.nix
@@ -0,0 +1 @@
+builtins.getEnv "TEST_VAR" + (if builtins.getEnv "NO_SUCH_VAR" == "" then "bar" else "bla")
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-groupBy.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-groupBy.exp
new file mode 100644
index 000000000000..bfca5652a59b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-groupBy.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-groupBy.nix
new file mode 100644
index 000000000000..7e0eab28b036
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashfile.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashfile.exp
new file mode 100644
index 000000000000..ff1e8293ef22
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashfile.exp
@@ -0,0 +1 @@
+[ "d3b07384d113edec49eaa6238ad5ff00" "0f343b0931126a20f133d67c2b018a3b" "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15" "60cacbf3d72e1e7834203da608037b1bf83b40e8" "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c" "5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef" "0cf9180a764aba863a67b6d72f0918bc131c6772642cb2dce5a34f0a702f9470ddc2bf125c12198b1995c233c34b4afd346c54a2334c350a948a51b6e8b4e6b6" "8efb4f73c5655351c444eb109230c556d39e2c7624e9c11abc9e3fb4b9b9254218cc5085b454a9698d085cfa92198491f07a723be4574adc70617b73eb0b6461" ]
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashfile.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashfile.nix
new file mode 100644
index 000000000000..8c9de66b7ecf
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashstring.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashstring.exp
new file mode 100644
index 000000000000..d720a082ddb3
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashstring.exp
@@ -0,0 +1 @@
+[ "d41d8cd98f00b204e9800998ecf8427e" "6c69ee7f211c640419d5366cc076ae46" "bb3438fbabd460ea6dbd27d153e2233b" "da39a3ee5e6b4b0d3255bfef95601890afd80709" "cd54e8568c1b37cf1e5badb0779bcbf382212189" "6d12e10b1d331dad210e47fd25d4f260802b7e77" "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" "900a4469df00ccbfd0c145c6d1e4b7953dd0afafadd7534e3a4019e8d38fc663" "ad0387b3bd8652f730ca46d25f9c170af0fd589f42e7f23f5a9e6412d97d7e56" "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" "9d0886f8c6b389398a16257bc79780fab9831c7fc11c8ab07fa732cb7b348feade382f92617c9c5305fefba0af02ab5fd39a587d330997ff5bd0db19f7666653" "21644b72aa259e5a588cd3afbafb1d4310f4889680f6c83b9d531596a5a284f34dbebff409d23bcc86aee6bad10c891606f075c6f4755cb536da27db5693f3a7" ]
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashstring.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-hashstring.nix
new file mode 100644
index 000000000000..b0f62b245ca8
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-import.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-import.exp
new file mode 100644
index 000000000000..c508125b55be
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-import.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 5 6 7 8 9 10 ]
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-import.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-import.nix
new file mode 100644
index 000000000000..76213a9541e3
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-overrides.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-overrides.exp
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-overrides.exp
@@ -0,0 +1 @@
+2
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-overrides.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-overrides.nix
new file mode 100644
index 000000000000..358742b36e22
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-overrides.nix
@@ -0,0 +1,9 @@
+let
+
+  overrides = { a = 2; };
+
+in (rec {
+  __overrides = overrides;
+  x = a;
+  a = 1;
+}).x
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-path.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-path.nix
new file mode 100644
index 000000000000..e67168cf3edf
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.exp
new file mode 100644
index 000000000000..bf8d2c14ea4f
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.exp
@@ -0,0 +1 @@
+{ bar = "regular"; foo = "directory"; }
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.nix.disabled b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.nix.disabled
new file mode 100644
index 000000000000..a7ec9292aae2
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-readDir.nix.disabled
@@ -0,0 +1 @@
+builtins.readDir ./readDir
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.exp
new file mode 100644
index 000000000000..4519bc406db5
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.exp
@@ -0,0 +1 @@
+"abccX"
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.flags b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.flags
new file mode 100644
index 000000000000..a28e6821004a
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.flags
@@ -0,0 +1 @@
+-I lang/dir1 -I lang/dir2 -I dir5=lang/dir3
\ No newline at end of file
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-search-path.nix
new file mode 100644
index 000000000000..6fe33decc019
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-xml.exp.xml b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-xml.exp.xml
new file mode 100644
index 000000000000..20099326cc96
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-xml.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-xml.nix
new file mode 100644
index 000000000000..9ee9f8a0b4f5
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-zipAttrsWith.exp b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-zipAttrsWith.exp
new file mode 100644
index 000000000000..9c0b15d22ba4
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-zipAttrsWith.nix b/tvix/eval/src/tests/nix_tests/notyetpassing/eval-okay-zipAttrsWith.nix
new file mode 100644
index 000000000000..e5d4cdccb74e
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/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/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/bar b/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/bar
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/bar
diff --git a/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/foo/git-hates-directories b/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/foo/git-hates-directories
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/notyetpassing/readDir/foo/git-hates-directories
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-1.nix b/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-1.nix
new file mode 100644
index 000000000000..2c02317d2a19
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-1.nix
@@ -0,0 +1,4 @@
+{ x = 123;
+  y = 456;
+  x = 789;
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-2.nix b/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-2.nix
new file mode 100644
index 000000000000..864d9865e07d
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-3.nix b/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-3.nix
new file mode 100644
index 000000000000..114d19779f86
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-4.nix b/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-4.nix
new file mode 100644
index 000000000000..77417432b347
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-4.nix
@@ -0,0 +1,4 @@
+{
+  services.ssh.port = 22;
+  services.ssh.port = 23;
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-7.nix b/tvix/eval/src/tests/nix_tests/parse-fail-dup-attrs-7.nix
new file mode 100644
index 000000000000..bbc3eb08c0f6
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-fail-dup-formals.nix b/tvix/eval/src/tests/nix_tests/parse-fail-dup-formals.nix
new file mode 100644
index 000000000000..a0edd91a9666
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-dup-formals.nix
@@ -0,0 +1 @@
+{x, y, x}: x
\ No newline at end of file
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-eof-in-string.nix b/tvix/eval/src/tests/nix_tests/parse-fail-eof-in-string.nix
new file mode 100644
index 000000000000..19775d2ec810
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-fail-mixed-nested-attrs1.nix b/tvix/eval/src/tests/nix_tests/parse-fail-mixed-nested-attrs1.nix
new file mode 100644
index 000000000000..11e40e66fd1b
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-mixed-nested-attrs1.nix
@@ -0,0 +1,4 @@
+{ 
+  x.z = 3; 
+  x = { y = 3; z = 3; }; 
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-mixed-nested-attrs2.nix b/tvix/eval/src/tests/nix_tests/parse-fail-mixed-nested-attrs2.nix
new file mode 100644
index 000000000000..17da82e5f0c7
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-mixed-nested-attrs2.nix
@@ -0,0 +1,4 @@
+{ 
+  x.y.y = 3; 
+  x = { y.y= 3; z = 3; }; 
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-patterns-1.nix b/tvix/eval/src/tests/nix_tests/parse-fail-patterns-1.nix
new file mode 100644
index 000000000000..7b40616417b8
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-patterns-1.nix
@@ -0,0 +1 @@
+args@{args, x, y, z}: x
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-regression-20060610.nix b/tvix/eval/src/tests/nix_tests/parse-fail-regression-20060610.nix
new file mode 100644
index 000000000000..b1934f7e1e82
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-regression-20060610.nix
@@ -0,0 +1,11 @@
+let {
+  x =
+    {gcc}:
+    {
+      inherit gcc;
+    };
+
+  body = ({
+    inherit gcc;
+  }).gcc;
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-uft8.nix b/tvix/eval/src/tests/nix_tests/parse-fail-uft8.nix
new file mode 100644
index 000000000000..34948d48aed2
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-uft8.nix
@@ -0,0 +1 @@
+123 รฉ 4
diff --git a/tvix/eval/src/tests/nix_tests/parse-fail-undef-var-2.nix b/tvix/eval/src/tests/nix_tests/parse-fail-undef-var-2.nix
new file mode 100644
index 000000000000..c10a52b1ea42
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-fail-undef-var.nix b/tvix/eval/src/tests/nix_tests/parse-fail-undef-var.nix
new file mode 100644
index 000000000000..7b63008110db
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-fail-undef-var.nix
@@ -0,0 +1 @@
+x: y
diff --git a/tvix/eval/src/tests/nix_tests/parse-okay-1.nix b/tvix/eval/src/tests/nix_tests/parse-okay-1.nix
new file mode 100644
index 000000000000..23a58ed109b1
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-okay-1.nix
@@ -0,0 +1 @@
+{x, y, z}: x + y + z
diff --git a/tvix/eval/src/tests/nix_tests/parse-okay-crlf.nix b/tvix/eval/src/tests/nix_tests/parse-okay-crlf.nix
new file mode 100644
index 000000000000..21518d4c6d80
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-okay-dup-attrs-5.nix b/tvix/eval/src/tests/nix_tests/parse-okay-dup-attrs-5.nix
new file mode 100644
index 000000000000..f4b9efd0c596
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-okay-dup-attrs-5.nix
@@ -0,0 +1,4 @@
+{
+  services.ssh = { enable = true; };
+  services.ssh.port = 23;
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-okay-dup-attrs-6.nix b/tvix/eval/src/tests/nix_tests/parse-okay-dup-attrs-6.nix
new file mode 100644
index 000000000000..ae6d7a769305
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-okay-dup-attrs-6.nix
@@ -0,0 +1,4 @@
+{
+  services.ssh.port = 23;
+  services.ssh = { enable = true; };
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-1.nix b/tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-1.nix
new file mode 100644
index 000000000000..fd1001c8cafc
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-1.nix
@@ -0,0 +1,4 @@
+{ 
+  x = { y = 3; z = 3; }; 
+  x.q = 3; 
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-2.nix b/tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-2.nix
new file mode 100644
index 000000000000..ad066b680384
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-2.nix
@@ -0,0 +1,4 @@
+{ 
+  x.q = 3; 
+  x = { y = 3; z = 3; }; 
+}
diff --git a/tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-3.nix b/tvix/eval/src/tests/nix_tests/parse-okay-mixed-nested-attrs-3.nix
new file mode 100644
index 000000000000..45a33e480373
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-okay-regression-20041027.nix b/tvix/eval/src/tests/nix_tests/parse-okay-regression-20041027.nix
new file mode 100644
index 000000000000..ae2e256eeaaa
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-okay-regression-751.nix b/tvix/eval/src/tests/nix_tests/parse-okay-regression-751.nix
new file mode 100644
index 000000000000..05c78b3016d3
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/parse-okay-regression-751.nix
@@ -0,0 +1,2 @@
+let const = a: "const"; in
+''${ const { x = "q"; }}''
diff --git a/tvix/eval/src/tests/nix_tests/parse-okay-subversion.nix b/tvix/eval/src/tests/nix_tests/parse-okay-subversion.nix
new file mode 100644
index 000000000000..356272815d26
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/nix_tests/parse-okay-url.nix b/tvix/eval/src/tests/nix_tests/parse-okay-url.nix
new file mode 100644
index 000000000000..08de27d0a4ce
--- /dev/null
+++ b/tvix/eval/src/tests/nix_tests/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/tvix/eval/src/tests/one_offs.rs b/tvix/eval/src/tests/one_offs.rs
new file mode 100644
index 000000000000..23bc9465d6bb
--- /dev/null
+++ b/tvix/eval/src/tests/one_offs.rs
@@ -0,0 +1,36 @@
+use crate::*;
+
+#[test]
+fn test_source_builtin() {
+    // Test an evaluation with a source-only builtin. The test ensures
+    // that the artificially constructed thunking is correct.
+
+    let mut eval = Evaluation::new_impure("builtins.testSourceBuiltin", None);
+    eval.src_builtins.push(("testSourceBuiltin", "42"));
+
+    let result = eval.evaluate();
+    assert!(
+        result.errors.is_empty(),
+        "evaluation failed: {:?}",
+        result.errors
+    );
+
+    let value = result.value.unwrap();
+    assert!(
+        matches!(value, Value::Integer(42)),
+        "expected the integer 42, but got {}",
+        value,
+    );
+}
+
+#[test]
+fn skip_broken_bytecode() {
+    let result = Evaluation::new(/* code = */ "x", None).evaluate();
+
+    assert_eq!(result.errors.len(), 1);
+
+    assert!(matches!(
+        result.errors[0].kind,
+        ErrorKind::UnknownStaticVariable
+    ));
+}
diff --git a/tvix/eval/src/tests/tvix_tests/README.md b/tvix/eval/src/tests/tvix_tests/README.md
new file mode 100644
index 000000000000..b493aa81f12f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/README.md
@@ -0,0 +1,19 @@
+These tests are "native" to Tvix and exist in addition to the Nix test
+suite.
+
+All of these are straightforward code snippets which are expected to
+produce a certain result.
+
+# `identity-*` tests
+
+Files named `identity-*.nix` contain code that is supposed to produce
+itself exactly after evaluation.
+
+These are useful for testing literals.
+
+# `eval-okay-*` tests
+
+Files named `eval-okay-*.nix` contain code which is supposed to
+evaluate to the output in the corresponding `eval-okay-*.exp` file.
+
+This convention is taken from the original Nix test suite.
diff --git a/tvix/eval/src/tests/tvix_tests/directory/default.nix b/tvix/eval/src/tests/tvix_tests/directory/default.nix
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/directory/default.nix
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-thunk-error.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-thunk-error.nix
new file mode 100644
index 000000000000..bb0d5920d757
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-thunk-error.nix
@@ -0,0 +1 @@
+builtins.genList (_: {}.foo) 1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-tojson-tostring-notcallable.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-tojson-tostring-notcallable.nix
new file mode 100644
index 000000000000..345b76fde037
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-tojson-tostring-notcallable.nix
@@ -0,0 +1,5 @@
+# attribute sets with a non-callable `__toString` can not be
+# serialised to JSON.
+builtins.toJSON {
+  __toString = 42;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-tojson-tostring-strong.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-tojson-tostring-strong.nix
new file mode 100644
index 000000000000..d1c72dc6783a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-tojson-tostring-strong.nix
@@ -0,0 +1,6 @@
+# String coercions when using builtins.toJSON on an attribute set with
+# a `__toString` attribute should be weak.
+builtins.toJSON {
+  __toString = self: self.x;
+  x = 42;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-closed-formals.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-closed-formals.nix
new file mode 100644
index 000000000000..937604c563e9
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-closed-formals.nix
@@ -0,0 +1 @@
+({x}: x) {x = 1; y = 2;}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-deep-forced-thunk-error.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-deep-forced-thunk-error.nix
new file mode 100644
index 000000000000..b7a758302266
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-deep-forced-thunk-error.nix
@@ -0,0 +1 @@
+[ (throw "error!") ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-deepseq.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-deepseq.nix
new file mode 100644
index 000000000000..9baa49b063ec
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-deepseq.nix
@@ -0,0 +1 @@
+builtins.deepSeq { x = abort "foo"; } 456
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-foldlStrict-strict-op-application.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-foldlStrict-strict-op-application.nix
new file mode 100644
index 000000000000..adc029b2f29e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-foldlStrict-strict-op-application.nix
@@ -0,0 +1,4 @@
+builtins.foldl'
+  (_: f: f null)
+  (throw "This doesn't explode")
+  [ (_: throw "Not the final value, but is still forced!") (_: 23) ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-force-before-value-pointer-equality.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-force-before-value-pointer-equality.nix
new file mode 100644
index 000000000000..de6c94325661
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-force-before-value-pointer-equality.nix
@@ -0,0 +1,5 @@
+let
+  x = throw "I have been forced";
+in
+
+x == x
\ No newline at end of file
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-getEnv-coercion.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-getEnv-coercion.nix
new file mode 100644
index 000000000000..fe48a5690c46
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-getEnv-coercion.nix
@@ -0,0 +1 @@
+builtins.getEnv { var = "PATH"; __toString = self: self.var; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-infinite-recursion.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-infinite-recursion.nix
new file mode 100644
index 000000000000..5e4fd3789cd6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-infinite-recursion.nix
@@ -0,0 +1 @@
+let x = x; in x
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-outer-value-never-pointer-equal.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-outer-value-never-pointer-equal.nix
new file mode 100644
index 000000000000..a8c3cedf61d7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-outer-value-never-pointer-equal.nix
@@ -0,0 +1,7 @@
+# For an explanation of this behavior see //tvix/docs/value-pointer-equality.md
+let
+  x = { foo = throw "foo"; };
+in
+
+# while `builtins.seq x null` would succeed, this fails!
+x == x
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-parsedrvname-coerce.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-parsedrvname-coerce.nix
new file mode 100644
index 000000000000..a1218de3fe58
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-parsedrvname-coerce.nix
@@ -0,0 +1 @@
+builtins.parseDrvName { outPath = "lol"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-remove.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-remove.nix
new file mode 100644
index 000000000000..539e0eb0a6f6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/eval-fail-seq.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-seq.nix
new file mode 100644
index 000000000000..cddbbfd3261e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-seq.nix
@@ -0,0 +1 @@
+builtins.seq (abort "foo") 2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-access-strange-identifier.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-access-strange-identifier.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-access-strange-identifier.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-access-strange-identifier.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-access-strange-identifier.nix
new file mode 100644
index 000000000000..8e282d1280f1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-access-strange-identifier.nix
@@ -0,0 +1,8 @@
+let
+  # There is no syntax for accessing this identifier in an ordinary
+  # way.
+  "foo bar" = 42;
+in ({
+  # but we *can* inherit it back out
+  inherit "foo bar";
+})."foo bar"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.exp
new file mode 100644
index 000000000000..94ba9a881ae6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.exp
@@ -0,0 +1 @@
+[ /bin /binbar /binbar /binbar /binbar /bin/bar /bin/bin ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.nix
new file mode 100644
index 000000000000..462f670882a0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-add-paths.nix
@@ -0,0 +1,9 @@
+[
+  (/bin + "/")
+  (/bin + "bar")
+  (let name = "bar"; in /bin + name)
+  (let name = "bar"; in /bin + "${name}")
+  (let name = "bar"; in /bin + "/" + "${name}")
+  (let name = "bar"; in /bin + "/${name}")
+  (/bin + /bin)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-float.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-float.exp
new file mode 100644
index 000000000000..08ef6079f899
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-float.exp
@@ -0,0 +1 @@
+{ add = 37.34; div = 1.05714; mul = 105.154; sub = 14.35; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-float.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-float.nix
new file mode 100644
index 000000000000..9d12aee061b2
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-float.nix
@@ -0,0 +1,6 @@
+{
+  add = 12.34 + 25.0;
+  sub = 20.05 - 5.7;
+  mul = 28.42 * 3.70;
+  div = 18.5 / 17.5;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-int.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-int.exp
new file mode 100644
index 000000000000..a5711e8bfe9b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-int.exp
@@ -0,0 +1 @@
+{ add = 20; div = 3; mul = 8; sub = 15; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-int.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-int.nix
new file mode 100644
index 000000000000..c53790db099b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-arithmetic-int.nix
@@ -0,0 +1,6 @@
+{
+  add = 15 + 5;
+  sub = 20 - 5;
+  mul = 4 * 2;
+  div = 9 / 3;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-assert-thunk-condition.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-assert-thunk-condition.exp
new file mode 100644
index 000000000000..aabe6ec3909c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-assert-thunk-condition.exp
@@ -0,0 +1 @@
+21
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-assert-thunk-condition.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-assert-thunk-condition.nix
new file mode 100644
index 000000000000..8934b3d8cf02
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-assert-thunk-condition.nix
@@ -0,0 +1,7 @@
+let
+  condition = x: y: x < y;
+in
+
+# The function application here will become a thunk which verifies that
+# assert forces the condition expression correctly.
+assert condition 21 42; 21
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-inherit-literal.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-inherit-literal.exp
new file mode 100644
index 000000000000..60d3b2f4a4cd
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-inherit-literal.exp
@@ -0,0 +1 @@
+15
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-inherit-literal.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-inherit-literal.nix
new file mode 100644
index 000000000000..587aec893372
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-inherit-literal.nix
@@ -0,0 +1,2 @@
+# the 'from' part of an `inherit` can be any expression.
+{ inherit ({a = 15;}) a; }.a
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-simple-inherit.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-simple-inherit.exp
new file mode 100644
index 000000000000..a779fce51abc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-simple-inherit.exp
@@ -0,0 +1 @@
+{ a = 1; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-simple-inherit.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-simple-inherit.nix
new file mode 100644
index 000000000000..68880bcfd857
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-simple-inherit.nix
@@ -0,0 +1,4 @@
+let
+  a = 1;
+in
+{ inherit a; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-lhs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-lhs.exp
new file mode 100644
index 000000000000..fedf8f25a693
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-lhs.exp
@@ -0,0 +1 @@
+{ a = "ok"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-lhs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-lhs.nix
new file mode 100644
index 000000000000..9596be22b831
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-lhs.nix
@@ -0,0 +1 @@
+{} // { a = "ok"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-rhs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-rhs.exp
new file mode 100644
index 000000000000..fedf8f25a693
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-rhs.exp
@@ -0,0 +1 @@
+{ a = "ok"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-rhs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-rhs.nix
new file mode 100644
index 000000000000..117c01141357
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-empty-rhs.nix
@@ -0,0 +1 @@
+{ a = "ok"; } // {}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-kv-lhs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-kv-lhs.exp
new file mode 100644
index 000000000000..c2234a47e2b8
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-kv-lhs.exp
@@ -0,0 +1 @@
+{ name = "foo"; other = 42; value = "bar"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-kv-lhs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-kv-lhs.nix
new file mode 100644
index 000000000000..6f71684902e5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update-kv-lhs.nix
@@ -0,0 +1 @@
+{ name = "foo"; value = "bar"; } // { other = 42; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update.exp
new file mode 100644
index 000000000000..57f4d541bd85
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update.exp
@@ -0,0 +1 @@
+{ a = 15; b = "works"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update.nix
new file mode 100644
index 000000000000..735602fe02d5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-attrs-update.nix
@@ -0,0 +1 @@
+{ a = 15; } // { b = "works"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-basenameof.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-basenameof.exp
new file mode 100644
index 000000000000..60a773f4af69
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-basenameof.exp
@@ -0,0 +1 @@
+[ "bar" "foo" "" "bar" "." "" "" "" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-basenameof.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-basenameof.nix
new file mode 100644
index 000000000000..bc59613f541d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-basenameof.nix
@@ -0,0 +1,10 @@
+[
+  (builtins.baseNameOf /foo/bar)
+  (builtins.baseNameOf "foo")
+  (builtins.baseNameOf "foo///")
+  (builtins.baseNameOf "foo/bar")
+  (builtins.baseNameOf "./.")
+  (builtins.baseNameOf "")
+  (builtins.baseNameOf /.)
+  (builtins.toString (builtins.baseNameOf /.))
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-add.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-add.exp
new file mode 100644
index 000000000000..c3ac813de6b9
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-add.exp
@@ -0,0 +1 @@
+[ 18 18.9 18.9 19.1 19 42 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-add.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-add.nix
new file mode 100644
index 000000000000..b04b1d1fa6ba
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-add.nix
@@ -0,0 +1,8 @@
+[
+  (builtins.add 7 11)
+  (builtins.add 7.9 11)
+  (builtins.add 7 11.9)
+  (builtins.add 7.2 11.9)
+  (builtins.add 7.1 11.9)
+  (builtins.add (builtins.add 21 10) 11)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-all.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-all.exp
new file mode 100644
index 000000000000..82ca7e6b6db7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-all.exp
@@ -0,0 +1 @@
+[ true true false false false false true true false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-all.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-all.nix
new file mode 100644
index 000000000000..12d62632dd6c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-all.nix
@@ -0,0 +1,15 @@
+[
+  (builtins.all (x: x) [ ])
+  (builtins.all (x: x) [ true true true ])
+  (builtins.all (x: x) [ false false false ])
+  (builtins.all (x: x) [ true true false ])
+  (builtins.all (x: x) [ false true true ])
+
+  # evaluation should short-circuit
+  (builtins.all (x: x) [ true false (builtins.abort "should be unreachable") ])
+
+  # arbitrary functions supported
+  (builtins.all (x: x * 2 == 42) [ ])
+  (builtins.all (x: x * 2 == 42) [ 21 21 21 ])
+  (builtins.all (x: x * 2 == 42) [ 1 2 3 ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-any.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-any.exp
new file mode 100644
index 000000000000..d6846ac3f756
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-any.exp
@@ -0,0 +1 @@
+[ false true false true true true false true false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-any.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-any.nix
new file mode 100644
index 000000000000..2c659f130b65
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-any.nix
@@ -0,0 +1,15 @@
+[
+  (builtins.any (x: x) [ ])
+  (builtins.any (x: x) [ true true true ])
+  (builtins.any (x: x) [ false false false ])
+  (builtins.any (x: x) [ true true false ])
+  (builtins.any (x: x) [ false true true ])
+
+  # evaluation should short-circuit
+  (builtins.any (x: x) [ false true (builtins.abort "should be unreachable") ])
+
+  # arbitrary functions supported
+  (builtins.any (x: x * 2 == 42) [ ])
+  (builtins.any (x: x * 2 == 42) [ 7 21 42 ])
+  (builtins.any (x: x * 2 == 42) [ 1 2 3 ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrnames.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrnames.exp
new file mode 100644
index 000000000000..6521066a8ea5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrnames.exp
@@ -0,0 +1 @@
+[ [ ] [ "bar" "baz" "foo" ] [ "Baz" "Foo" "bar" ] [ "Eric Idle" "Graham Chapman" "John Cleese" "Michael Palin" "Terry Gilliam" "Terry Jones" ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrnames.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrnames.nix
new file mode 100644
index 000000000000..67f7dcee5672
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrnames.nix
@@ -0,0 +1,13 @@
+[
+  (builtins.attrNames {})
+  (builtins.attrNames { foo = 1; bar = 2; baz = 3; })
+  (builtins.attrNames { Foo = 1; bar = 2; Baz = 3; })
+  (builtins.attrNames {
+    "Graham Chapman" = true;
+    "John Cleese" = true;
+    "Terry Gilliam" = true;
+    "Eric Idle" = true;
+    "Terry Jones" = true;
+    "Michael Palin" = true;
+  })
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrvalues.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrvalues.exp
new file mode 100644
index 000000000000..35c369772038
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrvalues.exp
@@ -0,0 +1 @@
+[ [ ] [ 2 3 1 ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrvalues.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrvalues.nix
new file mode 100644
index 000000000000..5eced31f0d2d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-attrvalues.nix
@@ -0,0 +1,4 @@
+[
+  (builtins.attrValues {})
+  (builtins.attrValues { foo = 1; bar = 2; baz = 3; })
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitand.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitand.exp
new file mode 100644
index 000000000000..30b348853e44
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitand.exp
@@ -0,0 +1 @@
+[ 0 0 0 1 8 8 8 8 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitand.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitand.nix
new file mode 100644
index 000000000000..af40005ed983
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitand.nix
@@ -0,0 +1,10 @@
+[
+  (builtins.bitAnd 0 0)
+  (builtins.bitAnd 0 1)
+  (builtins.bitAnd 1 0)
+  (builtins.bitAnd 1 1)
+  (builtins.bitAnd 8 8)
+  (builtins.bitAnd 8 (builtins.add 4 4))
+  (builtins.bitAnd (builtins.add 4 4) 8)
+  (builtins.bitAnd (builtins.add 4 4) (builtins.add 4 4))
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitor.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitor.exp
new file mode 100644
index 000000000000..2556b4183c77
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitor.exp
@@ -0,0 +1 @@
+[ 0 1 1 1 8 8 8 8 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitor.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitor.nix
new file mode 100644
index 000000000000..9c28f6d7acee
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitor.nix
@@ -0,0 +1,10 @@
+[
+  (builtins.bitOr 0 0)
+  (builtins.bitOr 1 0)
+  (builtins.bitOr 0 1)
+  (builtins.bitOr 1 1)
+  (builtins.bitOr 8 8)
+  (builtins.bitOr 8 (builtins.add 4 4))
+  (builtins.bitOr (builtins.add 4 4) 8)
+  (builtins.bitOr (builtins.add 4 4) (builtins.add 4 4))
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitxor.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitxor.exp
new file mode 100644
index 000000000000..457157d45970
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitxor.exp
@@ -0,0 +1 @@
+[ 0 1 1 0 8 8 0 0 0 0 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitxor.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitxor.nix
new file mode 100644
index 000000000000..80e363fb0748
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-bitxor.nix
@@ -0,0 +1,12 @@
+[
+  (builtins.bitXor 0 0)
+  (builtins.bitXor 1 0)
+  (builtins.bitXor 0 1)
+  (builtins.bitXor 1 1)
+  (builtins.bitXor 8 0)
+  (builtins.bitXor 0 8)
+  (builtins.bitXor 8 8)
+  (builtins.bitXor 8 (builtins.add 4 4))
+  (builtins.bitXor (builtins.add 4 4) 8)
+  (builtins.bitXor (builtins.add 4 4) (builtins.add 4 4))
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-builtins.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-builtins.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-builtins.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-builtins.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-builtins.nix
new file mode 100644
index 000000000000..cfbcbbb7684d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-builtins.nix
@@ -0,0 +1 @@
+[ builtins ]  == [ builtins.builtins ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-catAttrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-catAttrs.exp
new file mode 100644
index 000000000000..f8c0b2de5fba
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-catAttrs.exp
@@ -0,0 +1 @@
+[ 21 "+" 21 "=" 42 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-catAttrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-catAttrs.nix
new file mode 100644
index 000000000000..edac76d4461a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-catAttrs.nix
@@ -0,0 +1,10 @@
+builtins.catAttrs "foo" [
+  { foo = 21; }
+  { bar = 23; foo = "+"; }
+  { }
+  { bar = 12; }
+  { foo = 21 + 0; }
+  { foo = "="; }
+  ({ bar = 13; } // { baz = 89; })
+  { foo = 42; bar = 33; }
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-compareVersions.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-compareVersions.exp
new file mode 100644
index 000000000000..e69498c3e1c3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-compareVersions.exp
@@ -0,0 +1 @@
+[ 0 -1 -1 0 0 0 1 1 -1 1 -1 1 -1 -1 -1 -1 0 1 -1 -1 1 -1 -1 0 1 1 1 1 -1 -1 -1 -1 -1 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-compareVersions.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-compareVersions.nix
new file mode 100644
index 000000000000..cce554b4494a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-compareVersions.nix
@@ -0,0 +1,46 @@
+let
+  cmp = a: b:
+    let
+      ord1 = builtins.compareVersions a b;
+      ord2 = builtins.compareVersions b a;
+    in
+      assert ord1 == -ord2; ord1;
+in
+
+[
+  (cmp "1.2.3" "1.2.3")
+  (cmp "1.2.2" "1.2.3")
+  (cmp "1.2.3" "1.2.40")
+  (cmp "1.2.3" ".1.2.3")
+  (cmp "1.2.3" "1..2.3")
+  (cmp "1.2.3" "1.2.3.")
+  (cmp "1.2.3" "1.2")
+  (cmp "1.2.3" "1.2.a")
+  (cmp "1a.b" "1a.2")
+  (cmp "1" "")
+  (cmp "1.0" "1.0.0")
+  (cmp "2.3" "2.3pre")
+  (cmp "2.3" "2.3.0pre")
+  (cmp "2.3pre" "2.3.0pre")
+  (cmp "2.3" "2.3prepre")
+  (cmp "2.3pre" "2.3prepre")
+  (cmp "2.3prepre" "2.3prepre")
+  # check that the plain word comparison (via Ord) behaves the same
+  (cmp "foo" "bar")
+  (cmp "FoO" "fOo")
+  (cmp "foo" "fooo")
+  (cmp "foopre" "foo")
+  # Subset of test cases from eval-okay-versions.nix shipped by C++ Nix
+  (cmp "1.0" "2.3")
+  (cmp "2.1" "2.3")
+  (cmp "2.3" "2.3")
+  (cmp "2.5" "2.3")
+  (cmp "3.1" "2.3")
+  (cmp "2.3.1" "2.3")
+  (cmp "2.3.1" "2.3a")
+  (cmp "2.3pre1" "2.3")
+  (cmp "2.3pre3" "2.3pre12")
+  (cmp "2.3a" "2.3c")
+  (cmp "2.3pre1" "2.3c")
+  (cmp "2.3pre1" "2.3q")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-concat-lists.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-concat-lists.exp
new file mode 100644
index 000000000000..64ae529ac257
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-concat-lists.exp
@@ -0,0 +1 @@
+[ [ ] [ 1 2 3 4 5 6 ] [ [ 1 ] [ 2 ] [ 3 ] ] [ 1 2 3 4 5 6 ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-concat-lists.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-concat-lists.nix
new file mode 100644
index 000000000000..19ef5eba1145
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-concat-lists.nix
@@ -0,0 +1,6 @@
+[
+  (builtins.concatLists [ ])
+  (builtins.concatLists [ [ 1 2 ] [ 3 4 ] [ 5 6 ] ])
+  (builtins.concatLists [ [ [ 1 ] [ 2 ] ] [ [ 3 ] ] [ ] ])
+  (builtins.concatLists [ [ 1 2 ] [ ] [ 3 4 ] [ ] [ 5 6 ] ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.exp
new file mode 100644
index 000000000000..73e9bc33b083
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.exp
@@ -0,0 +1 @@
+[ 3 7 0 1 0 0.5 0.5 0.5 42 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.nix
new file mode 100644
index 000000000000..98b8b74bdf2b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.nix
@@ -0,0 +1,11 @@
+[
+  (builtins.div 9 3)
+  (builtins.div 7 1)
+  (builtins.div 3 9)
+  (builtins.div 4 4)
+  (builtins.div 1 2)
+  (builtins.div 1.0 2)
+  (builtins.div 1 2.0)
+  (builtins.div 1.0 2.0)
+  (builtins.div (builtins.div 84 4) 0.5)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-elemat.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-elemat.exp
new file mode 100644
index 000000000000..3701c9d75f94
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-elemat.exp
@@ -0,0 +1 @@
+[ "foo" "bar" "baz" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-elemat.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-elemat.nix
new file mode 100644
index 000000000000..762adeebbf0a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-elemat.nix
@@ -0,0 +1,5 @@
+[
+  (builtins.elemAt [ "foo" "bar" "baz" ] 0)
+  (builtins.elemAt [ "foo" "bar" "baz" ] 1)
+  (builtins.elemAt [ "foo" "bar" "baz" ] 2)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-filter.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-filter.exp
new file mode 100644
index 000000000000..fb94ebaa492c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-filter.exp
@@ -0,0 +1 @@
+[ [ 1 2 3 4 5 ] [ ] [ 2 2 2 ] [ [ 1 2 ] [ 3 4 ] ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-filter.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-filter.nix
new file mode 100644
index 000000000000..b621fdb43e7c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-filter.nix
@@ -0,0 +1,13 @@
+[
+  (builtins.filter (_: true) [ 1 2 3 4 5 ])
+  (builtins.filter (_: false) [ 1 2 3 4 5 ])
+  (builtins.filter (x: x == 2) [ 1 2 1 2 1 2 ])
+
+  (builtins.filter (x: (builtins.length x) > 0) [
+    [ ]
+    [ 1 2 ]
+    [ ]
+    [ ]
+    [ 3 4 ]
+  ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-getattr.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-getattr.exp
new file mode 100644
index 000000000000..89fa6c681064
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-getattr.exp
@@ -0,0 +1 @@
+[ 1 2 3 { bar = { baz = 3; }; } ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-getattr.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-getattr.nix
new file mode 100644
index 000000000000..87a2adbcd3dd
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-getattr.nix
@@ -0,0 +1,6 @@
+[
+  (builtins.getAttr "foo" { foo = 1; bar = 2; baz = 3; })
+  (builtins.getAttr "bar" { foo = 1; bar = 2; baz = 3; })
+  (builtins.getAttr "baz" { foo = 1; bar = 2; baz = 3; })
+  (builtins.getAttr "foo" { foo = { bar = { baz = 3; }; }; })
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-groupby-thunk.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-groupby-thunk.exp
new file mode 100644
index 000000000000..94649819caab
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-groupby-thunk.exp
@@ -0,0 +1 @@
+{ fred = [ { x = "fred"; y = "fred"; } ]; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-groupby-thunk.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-groupby-thunk.nix
new file mode 100644
index 000000000000..d62ae628dc71
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-groupby-thunk.nix
@@ -0,0 +1,6 @@
+
+builtins.groupBy
+  (v: v.x)
+  [ (rec { y = x; x = "fred"; }) ]
+
+
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-hasattr.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-hasattr.exp
new file mode 100644
index 000000000000..541fe347cbcd
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-hasattr.exp
@@ -0,0 +1 @@
+[ true true true false false true false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-hasattr.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-hasattr.nix
new file mode 100644
index 000000000000..e87e186b641d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-hasattr.nix
@@ -0,0 +1,9 @@
+[
+  (builtins.hasAttr "foo" { foo = 1; bar = 2; baz = 3; })
+  (builtins.hasAttr "bar" { foo = 1; bar = 2; baz = 3; })
+  (builtins.hasAttr "baz" { foo = 1; bar = 2; baz = 3; })
+  (builtins.hasAttr "FOO" { foo = 1; bar = 2; baz = 3; })
+  (builtins.hasAttr "foo" {})
+  (builtins.hasAttr ("f" + "o" + "o") { foo = 1; })
+  (builtins.hasAttr ("b" + "a" + "r") { foo = 1; })
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-head.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-head.exp
new file mode 100644
index 000000000000..afe288459f2e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-head.exp
@@ -0,0 +1 @@
+[ "foo" 1 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-head.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-head.nix
new file mode 100644
index 000000000000..1741a7aac4bb
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-head.nix
@@ -0,0 +1,4 @@
+[
+  (builtins.head [ "foo" ])
+  (builtins.head [ 1 2 3 ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-length.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-length.exp
new file mode 100644
index 000000000000..e80eb6ef1465
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-length.exp
@@ -0,0 +1 @@
+[ 0 1 3 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-length.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-length.nix
new file mode 100644
index 000000000000..ef1f638cbbdc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-length.nix
@@ -0,0 +1,5 @@
+[
+  (builtins.length [])
+  (builtins.length [ 1 ])
+  (builtins.length [ "one" "two" "three" ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-lessThan.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-lessThan.exp
new file mode 100644
index 000000000000..31f4598bb504
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-lessThan.exp
@@ -0,0 +1 @@
+[ true true true true false false false false true true true true false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-lessThan.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-lessThan.nix
new file mode 100644
index 000000000000..cd2d0c209c3a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-lessThan.nix
@@ -0,0 +1,15 @@
+[
+  (builtins.lessThan 2 3)
+  (builtins.lessThan 2.0 3)
+  (builtins.lessThan 2 3.0)
+  (builtins.lessThan 2.0 3.0)
+  (builtins.lessThan 3 2)
+  (builtins.lessThan 3.0 2)
+  (builtins.lessThan 3 2.0)
+  (builtins.lessThan 3.0 2.0)
+  (builtins.lessThan 10 (builtins.add 9 2))
+  (builtins.lessThan (builtins.add 9 1) 11)
+  (builtins.lessThan (builtins.add 9 1) (builtins.add 9 2))
+  (builtins.lessThan "a" "b")
+  (builtins.lessThan "b" "a")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.exp
new file mode 100644
index 000000000000..6cf53040320f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.exp
@@ -0,0 +1 @@
+[ [ 1 2 3 4 5 ] [ 2 4 6 8 10 ] [ 2 4 6 8 10 ] [ 2 4 6 8 10 ] [ 1 2 3 4 5 ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.nix
new file mode 100644
index 000000000000..71b351fd55b0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.nix
@@ -0,0 +1,19 @@
+[
+  # identity function
+  (builtins.map (x: x) [ 1 2 3 4 5 ])
+
+  # double stuff
+  (builtins.map (x: x * 2) [ 1 2 3 4 5 ])
+
+  # same but with a closure this time
+  (
+    let n = 2;
+    in builtins.map (x: x * n) [ 1 2 3 4 5 ]
+  )
+
+  # same, but with a builtin
+  (builtins.map (builtins.mul 2) [ 1 2 3 4 5 ])
+
+  # from global scope
+  (map (x: x) [ 1 2 3 4 5 ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-mul.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-mul.exp
new file mode 100644
index 000000000000..e3e0f03a8af5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-mul.exp
@@ -0,0 +1 @@
+[ 36 0 0 14 42 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-mul.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-mul.nix
new file mode 100644
index 000000000000..2a8d6c4214c3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-mul.nix
@@ -0,0 +1,7 @@
+[
+  (builtins.mul 4 9)
+  (builtins.mul 0 7)
+  (builtins.mul 7 0)
+  (builtins.mul 7 2)
+  (builtins.mul (builtins.mul 4 0.5) 21)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-partition.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-partition.exp
new file mode 100644
index 000000000000..d2390db4f528
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-partition.exp
@@ -0,0 +1 @@
+[ { right = [ 1 2 3 4 5 ]; wrong = [ ]; } { right = [ ]; wrong = [ 1 2 3 4 5 ]; } { right = [ 2 ]; wrong = [ 1 3 4 5 ]; } { right = [ [ 1 2 ] [ 3 4 ] ]; wrong = [ [ 1 ] [ 2 ] [ 3 ] ]; } ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-partition.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-partition.nix
new file mode 100644
index 000000000000..0587330ff917
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-partition.nix
@@ -0,0 +1,13 @@
+[
+  (builtins.partition (_: true) [ 1 2 3 4 5])
+  (builtins.partition (_: false) [ 1 2 3 4 5])
+  (builtins.partition (x: x == 2) [ 1 2 3 4 5])
+
+  (builtins.partition (x: (builtins.length x) > 1) [
+    [ 1 ]
+    [ 1 2 ]
+    [ 2 ]
+    [ 3 ]
+    [ 3 4 ]
+  ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.exp
new file mode 100644
index 000000000000..c2cb89bac663
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.exp
@@ -0,0 +1 @@
+[ "fabir" "a" "1a1" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.nix
new file mode 100644
index 000000000000..b8101c448bb0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.nix
@@ -0,0 +1,5 @@
+[
+  (builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar")
+  (builtins.replaceStrings ["o"] ["a"] "a")
+  (builtins.replaceStrings ["" ""] ["1" "2"] "a")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-splitVersion.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-splitVersion.exp
new file mode 100644
index 000000000000..222a0093f570
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-splitVersion.exp
@@ -0,0 +1 @@
+[ [ "1" "2" "3" ] [ "2" "3" "16" ] [ "22" "11" "pre" "408963" "823" "e" "2" "c" "9" "b" "0" "a" "0" ] [ "9" "4" "1" "rc" "1" ] [ "9" "4" "0" "20220721" ] [ "0" "1" "alpha" ] [ "unstable" "2022" "09" "20" ] [ "30" "pre" "9" ] [ "0" "pre+date=" "2021" "11" "30" ] [ "1" "2" "0" "_pre" "23" ] [ "0" "1" "0" "pre" "71" "_" "170" "f" "840" ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-splitVersion.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-splitVersion.nix
new file mode 100644
index 000000000000..4083e86714fc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-splitVersion.nix
@@ -0,0 +1,13 @@
+[
+  (builtins.splitVersion "1.2.3")
+  (builtins.splitVersion "2.3.16")
+  (builtins.splitVersion "22.11pre408963.823e2c9b0a0")
+  (builtins.splitVersion "9.4.1-rc1")
+  (builtins.splitVersion "9.4.0.20220721")
+  (builtins.splitVersion "0.1-alpha")
+  (builtins.splitVersion "unstable-2022-09-20")
+  (builtins.splitVersion "30.pre9")
+  (builtins.splitVersion "0.pre+date=2021-11-30")
+  (builtins.splitVersion "1.2.0_pre23")
+  (builtins.splitVersion "0.1.0pre71_170f840")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-string-length.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-string-length.exp
new file mode 100644
index 000000000000..b019be4bfd7a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-string-length.exp
@@ -0,0 +1 @@
+[ 3 "hello" 9 4 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-string-length.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-string-length.nix
new file mode 100644
index 000000000000..b7d51db3c578
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-string-length.nix
@@ -0,0 +1,10 @@
+[
+  (builtins.stringLength "foo")
+  (let s = "hello"; in (builtins.substring 0 (builtins.stringLength s) s))
+  (builtins.stringLength ("foo" + "${"bar" + "baz"}"))
+
+  # feel free to delete this test case at any time, it's just to show: This is a
+  # thing at the moment. We may want to break compatibility with this aspect of
+  # the C++ Nix implementation at any time.
+  (builtins.stringLength "๐Ÿ˜€")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-sub.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-sub.exp
new file mode 100644
index 000000000000..51842eccfac5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-sub.exp
@@ -0,0 +1 @@
+[ -4 -3.1 -4.9 -4.7 -4 42 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-sub.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-sub.nix
new file mode 100644
index 000000000000..2929c4dddd81
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-sub.nix
@@ -0,0 +1,8 @@
+[
+  (builtins.sub 7 11)
+  (builtins.sub 7.9 11)
+  (builtins.sub 7 11.9)
+  (builtins.sub 7.2 11.9)
+  (builtins.sub 7.9 11.9)
+  (builtins.sub (builtins.sub 123 23) 58)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-coerce.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-coerce.exp
new file mode 100644
index 000000000000..192548e94978
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-coerce.exp
@@ -0,0 +1 @@
+"42"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-coerce.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-coerce.nix
new file mode 100644
index 000000000000..626ae1d1be55
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-coerce.nix
@@ -0,0 +1,5 @@
+# builtins.substring uses string coercion internally
+
+builtins.substring 0 2 {
+  __toString = _: "4200";
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring.exp
new file mode 100644
index 000000000000..168276022898
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring.exp
@@ -0,0 +1 @@
+[ "tes" "testing" "" "estin" "ting" "" "" "" "" "est" "est" "est" "est" "est" "est" "" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring.nix
new file mode 100644
index 000000000000..f4ee82e2736f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring.nix
@@ -0,0 +1,18 @@
+[
+  (builtins.substring 0 3 "testing")
+  (builtins.substring 0 300 "testing")
+  (builtins.substring 3 0 "testing")
+  (builtins.substring 1 5 "testing")
+  (builtins.substring 3 5 "testing")
+  (builtins.substring 300 300 "testing")
+  (builtins.substring 301 300 "testing")
+  (builtins.substring 0 0 "")
+  (builtins.substring 0 1 "")
+  (builtins.substring (builtins.add 0 1) 3 "testing")
+  (builtins.substring 1 (builtins.add 3 0) "testing")
+  (builtins.substring (builtins.add 0 1) (builtins.add 3 0) "testing")
+  (builtins.substring (builtins.add 0 1) (builtins.add 3 0) "testing")
+  (builtins.substring (builtins.add 0 1) (builtins.add 3 0) ("test" + "ing"))
+  (builtins.substring (builtins.add 0 1) (builtins.add 3 0) ("test" + "ing"))
+  (builtins.substring 300 (-10) "testing")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tail.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tail.exp
new file mode 100644
index 000000000000..b9e3aa1ef79d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tail.exp
@@ -0,0 +1 @@
+[ [ ] [ 2 3 ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tail.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tail.nix
new file mode 100644
index 000000000000..2be9496a98e2
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tail.nix
@@ -0,0 +1,4 @@
+[
+  (builtins.tail [ "foo" ])
+  (builtins.tail [ 1 2 3 ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-thunked-function-calls.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-thunked-function-calls.exp
new file mode 100644
index 000000000000..3d4204d5a83e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-thunked-function-calls.exp
@@ -0,0 +1 @@
+[ 2 [ "Hans" "James" "Joachim" ] 2 [ "Clawdia" "Mynheer" ] 981 3 2 2 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-thunked-function-calls.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-thunked-function-calls.nix
new file mode 100644
index 000000000000..d96ddb3bd16d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-thunked-function-calls.nix
@@ -0,0 +1,31 @@
+[
+  # This is independent of builtins
+  (builtins.length [ (builtins.throw "Ferge") (builtins.throw "Wehsal") ])
+  (builtins.attrNames {
+    Hans = throw "Castorp";
+    Joachim = throw "ZiemรŸen";
+    James = "Tienappel";
+  })
+
+  (builtins.length (builtins.map builtins.throw [ "Settembrini" "Naphta" ]))
+
+  (builtins.attrNames (builtins.mapAttrs builtins.throw {
+    Clawdia = "Chauchat";
+    Mynheer = "Peeperkorn";
+  }))
+
+  (builtins.length (builtins.genList (builtins.add "Marusja") 981))
+  (builtins.length (builtins.genList builtins.throw 3))
+
+  # These are hard to get wrong since the outer layer needs to be forced anyways
+  (builtins.length (builtins.genericClosure {
+    startSet = [
+      { key = 1; initial = true; }
+    ];
+    operator = { key, initial, ... }:
+      if initial
+      then [ { key = key - 1; initial = false;  value = throw "lol"; } ]
+      else [ ];
+  }))
+  (builtins.length (builtins.concatMap (m: [ m (builtins.throw m) ]) [ "Marusja" ]))
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-toString.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-toString.exp
new file mode 100644
index 000000000000..a148ebc3b53f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-toString.exp
@@ -0,0 +1 @@
+[ "1" "4.200000" "" "" "1" "foo" "/etc" "Hello World" "Hello World" "1" "out" "2" "1 4.200000   1 foo /etc Hello World Hello World 1 out 2" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-toString.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-toString.nix
new file mode 100644
index 000000000000..e4dc18ac96a7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-toString.nix
@@ -0,0 +1,23 @@
+let
+  toStringableSet = {
+    __toString = self: self.content;
+    content = "Hello World";
+  };
+
+  toStringExamples = [
+    (toString 1)
+    (toString 4.2)
+    (toString null)
+    (toString false)
+    (toString true)
+    (toString "foo")
+    (toString /etc)
+    (toString toStringableSet)
+    (toString { __toString = _: toStringableSet; })
+    (toString { __toString = _: true; })
+    (toString { outPath = "out"; })
+    (toString { outPath = { outPath = { __toString = _: 2; }; }; })
+  ];
+in
+
+toStringExamples ++ [ (toString toStringExamples) ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-literals.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-literals.exp
new file mode 100644
index 000000000000..0a274c201fa8
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-literals.exp
@@ -0,0 +1 @@
+"[42,\"hello\",13.37,[],[1,2,3],{},{\"name\":\"foo\",\"value\":42},{\"foo\":42}]"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-literals.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-literals.nix
new file mode 100644
index 000000000000..12e8c03b171d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-literals.nix
@@ -0,0 +1,11 @@
+# tests serialisation of literal data
+builtins.toJSON [
+  42
+  "hello"
+  13.37
+  [ ]
+  [ 1 2 3 ]
+  { }
+  { name = "foo"; value = 42; }
+  { foo = 42; }
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath-nested.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath-nested.exp
new file mode 100644
index 000000000000..69667de5a1c3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath-nested.exp
@@ -0,0 +1 @@
+"{\"a\":40,\"b\":2}"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath-nested.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath-nested.nix
new file mode 100644
index 000000000000..70755c8c6dbe
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath-nested.nix
@@ -0,0 +1,8 @@
+# Attribute sets with an `outPath` can contain _any_ serialisable
+# value in that field.
+builtins.toJSON {
+  outPath = {
+    a = 40;
+    b = 2;
+  };
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath.exp
new file mode 100644
index 000000000000..82dd08179843
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath.exp
@@ -0,0 +1 @@
+"\"/nix/store/jzka5ndnygkkfjfvpqwjipqp75lhz138-emacs-28.2\""
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath.nix
new file mode 100644
index 000000000000..7f9d95ac60f4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-outpath.nix
@@ -0,0 +1,5 @@
+# Attribute sets with an `outPath` have that outPath itself serialised
+# to string.
+builtins.toJSON {
+  outPath = "/nix/store/jzka5ndnygkkfjfvpqwjipqp75lhz138-emacs-28.2";
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-thunks.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-thunks.exp
new file mode 100644
index 000000000000..9ccd94224ba8
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-thunks.exp
@@ -0,0 +1 @@
+"[42,42,\"42\"]"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-thunks.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-thunks.nix
new file mode 100644
index 000000000000..16234ab4514a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-thunks.nix
@@ -0,0 +1,9 @@
+let
+  a = b * 2;
+  b = 21;
+in
+builtins.toJSON [
+  a
+  ((n: n * 2) 21)
+  (builtins.toJSON a)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-tostring.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-tostring.exp
new file mode 100644
index 000000000000..2661fd257bf9
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-tostring.exp
@@ -0,0 +1 @@
+"\"it's 42\""
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-tostring.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-tostring.nix
new file mode 100644
index 000000000000..ec6f8d947cec
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-tojson-tostring.nix
@@ -0,0 +1,8 @@
+# Attribute sets with a `__toString` attribute JSON-serialise with a
+# string coercion of the function call result.
+
+builtins.toJSON {
+  __toString = self: "it's " + (builtins.toString (self.x * self.y));
+  x = 21;
+  y = 2;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-of.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-of.exp
new file mode 100644
index 000000000000..1ea054fc2d72
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-of.exp
@@ -0,0 +1 @@
+[ "null" "bool" "bool" "int" "int" "float" "string" "string" "set" "set" "list" "lambda" "path" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-of.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-of.nix
new file mode 100644
index 000000000000..a3cb659ecfde
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-of.nix
@@ -0,0 +1,22 @@
+let
+  fix = f: let x = f x; in x;
+in
+
+fix (self:
+  [
+    (builtins.typeOf null)
+    (builtins.typeOf true)
+    (builtins.typeOf (true && false))
+    (builtins.typeOf 12)
+    (builtins.typeOf (builtins.add 21 21))
+    (builtins.typeOf 1.2)
+    (builtins.typeOf "foo")
+    (builtins.typeOf "${"foo" + "bar"}baz")
+    (builtins.typeOf {})
+    # (builtins.typeOf { foo.bar = 32; }.foo) # TODO: re-enable when nested keys are done
+    (builtins.typeOf ({ name = "foo"; value = 13; } // { name = "bar"; }))
+    (builtins.typeOf self)
+    (builtins.typeOf fix)
+    (builtins.typeOf /nix/store)
+  ]
+)
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-predicates.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-predicates.exp
new file mode 100644
index 000000000000..724c1f9c34b9
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-predicates.exp
@@ -0,0 +1 @@
+[ true true false true true false true true false true true false true true false true true false true true false true true false true true true false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-predicates.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-predicates.nix
new file mode 100644
index 000000000000..3d688cb8bd68
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-type-predicates.nix
@@ -0,0 +1,34 @@
+let
+  # apply is thunked, so we can create a thunked value using the identity function
+  thunk = x: x;
+in
+[
+  (builtins.isAttrs { bar = throw "baz"; })
+  (builtins.isAttrs (thunk { foo = 13; }))
+  (builtins.isAttrs (thunk 123))
+  (builtins.isBool true)
+  (builtins.isBool (thunk false))
+  (builtins.isBool (thunk "lol"))
+  (builtins.isFloat 1.2)
+  (builtins.isFloat (thunk (1 * 1.0)))
+  (builtins.isFloat 1)
+  (builtins.isFunction thunk)
+  (builtins.isFunction (thunk thunk))
+  (builtins.isFunction {})
+  (builtins.isInt 1)
+  (builtins.isInt (thunk 42))
+  (builtins.isInt 1.0)
+  (builtins.isList [ (throw "oh no") (abort "it's over") ])
+  (builtins.isList (thunk [ 21 21 ]))
+  (builtins.isList (thunk {}))
+  (builtins.isNull null)
+  (builtins.isNull (thunk null))
+  (builtins.isNull 42)
+  (builtins.isPath ./relative)
+  (builtins.isPath (thunk /absolute))
+  (builtins.isPath "/not/a/path")
+  (builtins.isString "simple")
+  (builtins.isString "${{ outPath = "coerced"; }}")
+  (builtins.isString "hello ${"interpolation"}")
+  (builtins.isString true)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-ceil.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-ceil.exp
new file mode 100644
index 000000000000..dffbbe59f0a0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-ceil.exp
@@ -0,0 +1 @@
+[ 4 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-ceil.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-ceil.nix
new file mode 100644
index 000000000000..5835bf829b03
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-ceil.nix
@@ -0,0 +1 @@
+[ (builtins.ceil 3.4) ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-closure-pointer-compare.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-pointer-compare.exp
new file mode 100644
index 000000000000..c3bb809c9ffb
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-pointer-compare.exp
@@ -0,0 +1 @@
+[ false false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-closure-pointer-compare.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-pointer-compare.nix
new file mode 100644
index 000000000000..7c4333668df8
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-pointer-compare.nix
@@ -0,0 +1,14 @@
+# For an explanation of this behavior see //tvix/docs/value-pointer-equality.md
+let
+  g = x:
+    owo: "th" + x;
+in
+[
+  (
+    { q = g "ia"; } == { q = g ("i"+"a"); }
+  )
+
+  (
+    [ (g "ia") ] == [ (g ("i"+"a")) ]
+  )
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-closure-self.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-self.exp
new file mode 100644
index 000000000000..be54b4b4e39e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-self.exp
@@ -0,0 +1 @@
+"done"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-closure-self.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-self.nix
new file mode 100644
index 000000000000..bda364f42992
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-self.nix
@@ -0,0 +1,4 @@
+let
+  # self-recursive function should be able to close over itself
+  f = n: if n <= 0 then "done" else f (n - 1);
+in f 10
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-closure-with-shadowing.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-with-shadowing.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-with-shadowing.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-closure-with-shadowing.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-with-shadowing.nix
new file mode 100644
index 000000000000..305463775217
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-closure-with-shadowing.nix
@@ -0,0 +1,14 @@
+# If a closure closes over a variable that is statically known *and*
+# available dynamically through `with`, the statically known one must
+# have precedence.
+
+let
+  # introduce statically known `a` (this should be the result)
+  a = 1;
+in
+
+# introduce some closure depth to force both kinds of upvalue
+# resolution, and introduce a dynamically known `a` within the
+# closures
+let f = b: with { a = 2; }; c: a + b + c;
+in f 0 0
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-false.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-false.exp
new file mode 100644
index 000000000000..95a0e7378b5e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-false.exp
@@ -0,0 +1 @@
+{ eq = false; ge = false; gt = false; le = false; lt = false; ne = false; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-false.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-false.nix
new file mode 100644
index 000000000000..2b511f56eecb
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-false.nix
@@ -0,0 +1,8 @@
+{
+  eq = 6.9 == 4.2;
+  ne = 4.2 != 4.2;
+  lt = 2.5 < 1.5;
+  le = 2.5 <= 1.5;
+  gt = 1.5 > 2.5;
+  ge = 1.5 >= 2.5;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-true.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-true.exp
new file mode 100644
index 000000000000..9160829dde78
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-true.exp
@@ -0,0 +1 @@
+{ eq = true; ge = true; gt = true; le = true; lt = true; ne = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-true.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-true.nix
new file mode 100644
index 000000000000..c505a85b1f3c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-float-true.nix
@@ -0,0 +1,8 @@
+{
+  eq = 4.2 == 4.2;
+  ne = 6.9 != 4.2;
+  lt = 1.5 < 2.5;
+  le = 2.5 <= 2.5;
+  gt = 2.3 > 1.2;
+  ge = 2.3 >= 2.3;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-false.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-false.exp
new file mode 100644
index 000000000000..95a0e7378b5e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-false.exp
@@ -0,0 +1 @@
+{ eq = false; ge = false; gt = false; le = false; lt = false; ne = false; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-false.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-false.nix
new file mode 100644
index 000000000000..7d6b30419fac
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-false.nix
@@ -0,0 +1,8 @@
+{
+  eq = 69 == 42;
+  ne = 42 != 42;
+  lt = 2 < 1;
+  le = 2 <= 1;
+  gt = 1 > 2;
+  ge = 1 >= 2;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-true.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-true.exp
new file mode 100644
index 000000000000..9160829dde78
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-true.exp
@@ -0,0 +1 @@
+{ eq = true; ge = true; gt = true; le = true; lt = true; ne = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-true.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-true.nix
new file mode 100644
index 000000000000..0bf474e53fd0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-int-true.nix
@@ -0,0 +1,8 @@
+{
+  eq = 42 == 42;
+  ne = 69 != 42;
+  lt = 1 < 2;
+  le = 2 <= 2;
+  gt = 2 > 1;
+  ge = 2 >= 2;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-false.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-false.exp
new file mode 100644
index 000000000000..95a0e7378b5e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-false.exp
@@ -0,0 +1 @@
+{ eq = false; ge = false; gt = false; le = false; lt = false; ne = false; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-false.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-false.nix
new file mode 100644
index 000000000000..61b206c03376
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-false.nix
@@ -0,0 +1,8 @@
+{
+  eq = 6.9 == 4;
+  ne = 4.0 != 4;
+  lt = 2.5 < 1;
+  le = 2 <= 1.5;
+  gt = 1 > 1.1;
+  ge = 1.5 >= 2;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-true.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-true.exp
new file mode 100644
index 000000000000..9160829dde78
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-true.exp
@@ -0,0 +1 @@
+{ eq = true; ge = true; gt = true; le = true; lt = true; ne = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-true.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-true.nix
new file mode 100644
index 000000000000..ad77074710ca
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-num-true.nix
@@ -0,0 +1,8 @@
+{
+  eq = 42.0 == 42;
+  ne = 6.9 != 4;
+  lt = 1.5 < 2;
+  le = 2.0 <= 2.0;
+  gt = 1.1 > 1;
+  ge = 2.3 >= 2.3;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-false.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-false.exp
new file mode 100644
index 000000000000..95a0e7378b5e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-false.exp
@@ -0,0 +1 @@
+{ eq = false; ge = false; gt = false; le = false; lt = false; ne = false; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-false.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-false.nix
new file mode 100644
index 000000000000..b5773a21d374
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-false.nix
@@ -0,0 +1,8 @@
+{
+  eq = "test" == "not test";
+  ne = "test" != "test";
+  lt = "bcd" < "abc";
+  le = "bcd" <= "abc";
+  gt = "abc" > "bcd";
+  ge = "abc" >= "bcd";
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-true.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-true.exp
new file mode 100644
index 000000000000..9160829dde78
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-true.exp
@@ -0,0 +1 @@
+{ eq = true; ge = true; gt = true; le = true; lt = true; ne = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-true.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-true.nix
new file mode 100644
index 000000000000..172d2237e9e2
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-cmp-str-true.nix
@@ -0,0 +1,8 @@
+{
+  eq = "test" == "test";
+  ne = "test" != "not test";
+  lt = "abc" < "bcd";
+  le = "bcd" <= "bcd";
+  gt = "bcd" > "abc";
+  ge = "bcd" >= "bcd";
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-coerce-opadd.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-coerce-opadd.exp
new file mode 100644
index 000000000000..d874518a37ed
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-coerce-opadd.exp
@@ -0,0 +1 @@
+[ "lordnikon" "zerocool" /tmp/31337h4x0r "fooblah" "blahfoo" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-coerce-opadd.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-coerce-opadd.nix
new file mode 100644
index 000000000000..6ddd30e7a189
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-coerce-opadd.nix
@@ -0,0 +1,7 @@
+[
+  ({ __toString = _: "lord"; } + "nikon")
+  ("zero" + { __toString = _: "cool"; })
+  (/tmp/31337 + "h4x0r")
+  ("foo" + { outPath="blah"; })
+  ({ outPath="blah"; } + "foo")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-compare-lists.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-compare-lists.exp
new file mode 100644
index 000000000000..3b7fd398198a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-compare-lists.exp
@@ -0,0 +1 @@
+[ false true true true false true false false false true false false false true true ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-compare-lists.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-compare-lists.nix
new file mode 100644
index 000000000000..9b73df61d84e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-compare-lists.nix
@@ -0,0 +1,17 @@
+[
+  ([1 2] < [1])
+  ([1 2] < [2 3])
+  ([1 2] < [2])
+  ([1 2] < [1 2 3])
+  ([3 4] < [1])
+  ([1 2] > [1])
+  ([1 2] > [2 3])
+  ([1 2] > [2])
+  ([1 2] > [1 2 3])
+  ([3 4] > [1])
+  ([1 2] <= [1])
+  ([1 2] >= [2 3])
+  ([1 2] >= [2])
+  ([1 2] <= [1 2 3])
+  ([3 4] >= [1])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-concat-lists.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-concat-lists.exp
new file mode 100644
index 000000000000..3bed31f76e3f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-concat-lists.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-concat-lists.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-concat-lists.nix
new file mode 100644
index 000000000000..de332cd29f3a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-concat-lists.nix
@@ -0,0 +1 @@
+[ 1 2 ] ++ [ 3 4 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-concat-strings.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-concat-strings.exp
new file mode 100644
index 000000000000..cd4bc1ab64cc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-concat-strings.exp
@@ -0,0 +1 @@
+"hello world"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-concat-strings.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-concat-strings.nix
new file mode 100644
index 000000000000..1fc708929989
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-concat-strings.nix
@@ -0,0 +1 @@
+"hello " + "world"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-concatmap.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-concatmap.exp
new file mode 100644
index 000000000000..14d804aa22f5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-concatmap.exp
@@ -0,0 +1 @@
+[ "a" "z" "b" "z" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-concatmap.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-concatmap.nix
new file mode 100644
index 000000000000..149a0722b11d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-concatmap.nix
@@ -0,0 +1 @@
+(builtins.concatMap (x: [x] ++ ["z"]) ["a" "b"])
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-concatstringssep.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-concatstringssep.exp
new file mode 100644
index 000000000000..93987647ffe6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-concatstringssep.exp
@@ -0,0 +1 @@
+[ "" "foobarxyzzy" "foo, bar, xyzzy" "foo" "" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-concatstringssep.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-concatstringssep.nix
new file mode 100644
index 000000000000..adc4c41bd551
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/eval-okay-contains-nested-non-set.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-nested-non-set.exp
new file mode 100644
index 000000000000..c508d5366f70
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-nested-non-set.exp
@@ -0,0 +1 @@
+false
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-contains-nested-non-set.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-nested-non-set.nix
new file mode 100644
index 000000000000..361ba9144594
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-nested-non-set.nix
@@ -0,0 +1,3 @@
+# ? operator should work even if encountering a non-set value on the
+# walk
+{ a.b = 42; } ? a.b.c
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp
new file mode 100644
index 000000000000..ca00e3c049d6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.exp
@@ -0,0 +1 @@
+[ false false false false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix
new file mode 100644
index 000000000000..c086759f456b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-contains-non-set.nix
@@ -0,0 +1,3 @@
+# Nix allows using the ? operator on non-set types, in which case it
+# should always return false.
+[ (123 ? key) ("foo" ? key) (null ? key) ([ "key" ] ? key) ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-attrs.exp
new file mode 100644
index 000000000000..7cf54d959611
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-attrs.exp
@@ -0,0 +1 @@
+{ a = { b = { c = { d = { e = { f = { g = "deep!"; }; }; }; }; }; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-attrs.nix
new file mode 100644
index 000000000000..91649d0c6dd4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-attrs.nix
@@ -0,0 +1 @@
+{ a.b.c.d.e.f.g = "deep!"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with-closure.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with-closure.exp
new file mode 100644
index 000000000000..3bed31f76e3f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with-closure.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with-closure.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with-closure.nix
new file mode 100644
index 000000000000..7f13f1f27030
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with-closure.nix
@@ -0,0 +1,18 @@
+# This convoluted test constructs a situation in which dynamically
+# resolved upvalues refer `with` blocks introduced at different lambda
+# context boundaries, i.e. the access to a, b in the innermost closure
+# must be threaded through upvalues in several levels.
+
+(_:
+with { a = 1; b = 1; };
+
+_:
+with { b = 2; c = 2; };
+
+_:
+with { c = 3; d = 3; };
+
+_:
+with { d = 4; };
+
+[ a b c d ]) null null null null
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with.exp
new file mode 100644
index 000000000000..3bed31f76e3f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with.nix
new file mode 100644
index 000000000000..7f1128b6707b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deeply-nested-with.nix
@@ -0,0 +1,6 @@
+with { a = 1; b = 1; };
+with { b = 2; c = 2; };
+with { c = 3; d = 3; };
+with { d = 4; };
+
+[ a b c d ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deepseq.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-deepseq.exp
new file mode 100644
index 000000000000..8d38505c1686
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deepseq.exp
@@ -0,0 +1 @@
+456
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deepseq.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-deepseq.nix
new file mode 100644
index 000000000000..53aa4b1dc251
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deepseq.nix
@@ -0,0 +1 @@
+builtins.deepSeq (let as = { x = 123; y = as; }; in as) 456
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.exp
new file mode 100644
index 000000000000..5993db7ccc5a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.exp
@@ -0,0 +1 @@
+[ false -2 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.nix
new file mode 100644
index 000000000000..1fbb3e853af4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-unary-formals.nix
@@ -0,0 +1,6 @@
+# Application of unary operators on deferred formals arguments (via
+# defaulting), see also b/255.
+[
+  (({ b ? !a, a }: b) { a = true; })
+  (({ b ? -a, a }: b) { a = 2; })
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-with.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-with.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-with.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-with.nix
new file mode 100644
index 000000000000..af227ae28e87
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-deferred-with.nix
@@ -0,0 +1,8 @@
+# Tests using `with` on a set that does not yet exist on the stack.
+
+let
+  result = with set; value;
+  set = {
+    value = 42;
+  };
+in result
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-dirof.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-dirof.exp
new file mode 100644
index 000000000000..ff464e4c30d4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-dirof.exp
@@ -0,0 +1 @@
+[ /foo "." "foo//" "foo" "." "." / "/" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-dirof.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-dirof.nix
new file mode 100644
index 000000000000..13cf47320515
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-dirof.nix
@@ -0,0 +1,10 @@
+[
+  (builtins.dirOf /foo/bar)
+  (builtins.dirOf "foo")
+  (builtins.dirOf "foo///")
+  (builtins.dirOf "foo/bar")
+  (builtins.dirOf "./.")
+  (builtins.dirOf "")
+  (builtins.dirOf /.)
+  (builtins.toString (builtins.dirOf /.))
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-elem.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-elem.exp
new file mode 100644
index 000000000000..3cf6c0e962f0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-elem.exp
@@ -0,0 +1 @@
+[ true false 30 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-elem.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-elem.nix
new file mode 100644
index 000000000000..71ea7a4ed03d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.exp
new file mode 100644
index 000000000000..ffcd4415b08f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.exp
@@ -0,0 +1 @@
+{ }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.nix
new file mode 100644
index 000000000000..a1181431deca
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-empty-rec-inherit.nix
@@ -0,0 +1 @@
+rec { inherit; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-eq-float.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-float.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-float.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-eq-float.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-float.nix
new file mode 100644
index 000000000000..398f4a9dfc55
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-float.nix
@@ -0,0 +1 @@
+4.2 == 4.2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-eq-int.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-int.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-int.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-eq-int.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-int.nix
new file mode 100644
index 000000000000..dc52ba112a60
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-int.nix
@@ -0,0 +1 @@
+42 == 42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-eq-nested-list.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-nested-list.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-nested-list.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-eq-nested-list.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-nested-list.nix
new file mode 100644
index 000000000000..5dbcb515295b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-eq-nested-list.nix
@@ -0,0 +1 @@
+[["f" ""]] == [["f" ""]]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-escapify-integer-keys.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-escapify-integer-keys.exp
new file mode 100644
index 000000000000..aa98a082a8ac
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-escapify-integer-keys.exp
@@ -0,0 +1 @@
+{ "3" = 3; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-escapify-integer-keys.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-escapify-integer-keys.nix
new file mode 100644
index 000000000000..aa98a082a8ac
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-escapify-integer-keys.nix
@@ -0,0 +1 @@
+{ "3" = 3; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-fib.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-fib.exp
new file mode 100644
index 000000000000..8643cf6debac
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-fib.exp
@@ -0,0 +1 @@
+89
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-fib.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-fib.nix
new file mode 100644
index 000000000000..9a22d85ac5f1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-fib.nix
@@ -0,0 +1,7 @@
+let
+  fib' = i: n: m: if i == 0
+    then n
+    else fib' (i - 1) m (n + m);
+
+  fib = n: fib' n 1 1;
+in fib 10
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-fix.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-fix.exp
new file mode 100644
index 000000000000..c1581543511f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-fix.exp
@@ -0,0 +1 @@
+{ a = 1; b = 21; c = 42; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-fix.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-fix.nix
new file mode 100644
index 000000000000..27d2fae1042e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-fix.nix
@@ -0,0 +1,7 @@
+let
+  fix = f: let x = f x; in x;
+in fix(self: {
+  a = 1;
+  b = self.a + 20;
+  c = self.b * 2;
+})
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-float-repr.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-float-repr.exp
new file mode 100644
index 000000000000..c55d2be717f1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-float-repr.exp
@@ -0,0 +1 @@
+1.23457
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-float-repr.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-float-repr.nix
new file mode 100644
index 000000000000..447bd5af7f5c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-float-repr.nix
@@ -0,0 +1,2 @@
+# Floats are displayed with a maximum of 5 digits
+1.23456789
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-floor.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-floor.exp
new file mode 100644
index 000000000000..6f98a7f48f2f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-floor.exp
@@ -0,0 +1 @@
+[ 3 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-floor.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-floor.nix
new file mode 100644
index 000000000000..c6b79c91a1b4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-floor.nix
@@ -0,0 +1 @@
+[ (builtins.floor 3.4) ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-elements.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-elements.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-elements.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-elements.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-elements.nix
new file mode 100644
index 000000000000..fc4129a2543a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-elements.nix
@@ -0,0 +1,8 @@
+let
+  lst = builtins.foldl'
+    (acc: x: acc ++ [ x ])
+    [ ]
+    [ 42 (throw "this shouldn't be evaluated") ];
+in
+
+builtins.head lst
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-initial-accumulator.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-initial-accumulator.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-initial-accumulator.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-initial-accumulator.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-initial-accumulator.nix
new file mode 100644
index 000000000000..59fd29b55237
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict-lazy-initial-accumulator.nix
@@ -0,0 +1,4 @@
+builtins.foldl'
+  (_: x: x)
+  (throw "This is never forced")
+  [ "but the results of applying op are" 42 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict.exp
new file mode 100644
index 000000000000..8d683a20fab7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict.exp
@@ -0,0 +1 @@
+[ 6 [ 0 1 2 3 ] 2 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict.nix
new file mode 100644
index 000000000000..44c0349387ff
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-foldlStrict.nix
@@ -0,0 +1,5 @@
+[
+  (builtins.foldl' builtins.add 0 [1 2 3])
+  (builtins.foldl' (l1: l2: l1 ++ l2) [0] [[1] [2 3]])
+  (builtins.foldl' (x: y: if x == 0 then y else x * y) 0 [1 2])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson-escapes.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson-escapes.exp
new file mode 100644
index 000000000000..add5505a8287
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson-escapes.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson-escapes.nix
new file mode 100644
index 000000000000..f00713507732
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson.exp
new file mode 100644
index 000000000000..24aa21d78ff7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson.exp
@@ -0,0 +1 @@
+[ { Image = { Animated = false; Height = 600; IDs = [ 116 943 234 38793 true false null -100 ]; Latitude = 37.7668; Longitude = -122.396; Thumbnail = { Height = 125; Url = "http://www.example.com/image/481989943"; Width = 100; }; Title = "View from 15th Floor"; Width = 800; }; } { name = "a"; value = "b"; } [ 1 2 3 4 ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson.nix
new file mode 100644
index 000000000000..e530789446ef
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-fromjson.nix
@@ -0,0 +1,24 @@
+[
+# RFC 7159, section 13.
+  (builtins.fromJSON
+    ''
+    {
+      "Image": {
+          "Width":  800,
+          "Height": 600,
+          "Title":  "View from 15th Floor",
+          "Thumbnail": {
+              "Url":    "http://www.example.com/image/481989943",
+              "Height": 125,
+              "Width":  100
+          },
+          "Animated" : false,
+          "IDs": [116, 943, 234, 38793, true  ,false,null, -100],
+          "Latitude":  37.7668,
+          "Longitude": -122.396
+      }
+    }
+  '')
+  (builtins.fromJSON ''{"name": "a", "value": "b"}'')
+  (builtins.fromJSON "[ 1, 2, 3, 4 ]")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-functionargs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-functionargs.exp
new file mode 100644
index 000000000000..c1c9f8ffaf69
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/eval-okay-functionargs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-functionargs.nix
new file mode 100644
index 000000000000..cd95b971f8a9
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/eval-okay-functor-call.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-functor-call.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-functor-call.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-functor-call.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-functor-call.nix
new file mode 100644
index 000000000000..80ae345d836b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-functor-call.nix
@@ -0,0 +1 @@
+{ x = 21; __functor = self: y: self.x * y; } 2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-genlist.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-genlist.exp
new file mode 100644
index 000000000000..cd4ca34f14df
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-genlist.exp
@@ -0,0 +1 @@
+[ 0 1 4 9 16 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-genlist.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-genlist.nix
new file mode 100644
index 000000000000..2c4dfba20324
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-genlist.nix
@@ -0,0 +1 @@
+builtins.genList (x: x * x) 5
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.exp
new file mode 100644
index 000000000000..074f5f07f5f0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.exp
@@ -0,0 +1 @@
+{ "'quoted'" = false; "-20ยฐ" = false; "2normal" = false; "45 44 43-'3 2 1" = false; "9front" = false; Very2Normal = true; VeryNormal = true; _'12 = true; "_'12.5" = false; __internal = true; _internal = true; abort = true; assert = true; "attr.path" = false; false = true; foldl' = true; normal = true; normal2 = true; null = true; or = true; throw = true; true = true; x = true; x' = true; x'' = true; "๐Ÿ˜€" = false; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.nix
new file mode 100644
index 000000000000..8f9aa2823801
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.nix
@@ -0,0 +1,30 @@
+{
+  __internal = true;
+  _internal = true;
+  normal = true;
+  VeryNormal = true;
+  normal2 = true;
+  Very2Normal = true;
+  _'12 = true;
+  foldl' = true;
+  x = true;
+  x' = true;
+  x'' = true;
+
+  true = true;
+  false = true;
+  null = true;
+  or = true;
+  "assert" = true; # -ish
+  throw = true;
+  abort = true;
+
+  "9front" = false;
+  "2normal" = false;
+  "-20ยฐ" = false;
+  "45 44 43-'3 2 1" = false;
+  "attr.path" = false;
+  "'quoted'" = false;
+  "_'12.5" = false;
+  "๐Ÿ˜€" = false;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-import.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-import.exp
new file mode 100644
index 000000000000..5ba7f64d78a7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-import.exp
@@ -0,0 +1 @@
+[ 42 42 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-import.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-import.nix
new file mode 100644
index 000000000000..49cd244f06c1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-import.nix
@@ -0,0 +1,4 @@
+[
+  (import ./directory)
+  (import ./directory/default.nix)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-inherit-string-ident.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-inherit-string-ident.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-inherit-string-ident.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-inherit-string-ident.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-inherit-string-ident.nix
new file mode 100644
index 000000000000..dde81e5a7c30
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-inherit-string-ident.nix
@@ -0,0 +1,7 @@
+# identifiers in inherits can be string-like expressions
+
+let
+  set = {
+    inherit ({ value = 42; }) "value";
+  };
+in set.value
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals-deferred.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals-deferred.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals-deferred.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals-deferred.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals-deferred.nix
new file mode 100644
index 000000000000..5c6702120fc4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals-deferred.nix
@@ -0,0 +1,3 @@
+# Tests formals which have internal default values that must be deferred.
+
+({ optional ? defaultValue, defaultValue }: optional) { defaultValue = 42; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals.nix
new file mode 100644
index 000000000000..c6dd5e9d54cf
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-internal-formals.nix
@@ -0,0 +1,3 @@
+# Tests formals which have internal default values.
+
+({ defaultValue, optional ? defaultValue }: optional) { defaultValue = 42; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-intersectattrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-intersectattrs.exp
new file mode 100644
index 000000000000..25001b211fb8
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-intersectattrs.exp
@@ -0,0 +1 @@
+{ a = 100; b = 200; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-intersectattrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-intersectattrs.nix
new file mode 100644
index 000000000000..3534132ed48b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-intersectattrs.nix
@@ -0,0 +1,3 @@
+builtins.intersectAttrs
+  { a = 1; b = 2; c = 3; }
+  { a = 100; b = 200; d = 5; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lambda-identity.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-lambda-identity.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lambda-identity.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lambda-identity.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-lambda-identity.nix
new file mode 100644
index 000000000000..f2ee49df8092
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lambda-identity.nix
@@ -0,0 +1,2 @@
+# Identity function is the simplest possible function.
+(x: x) 42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding-closure.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding-closure.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding-closure.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding-closure.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding-closure.nix
new file mode 100644
index 000000000000..dae170b06bad
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding-closure.nix
@@ -0,0 +1,4 @@
+let
+  f = n: n + a;
+  a = 2;
+in f 40
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding.nix
new file mode 100644
index 000000000000..41c4c53ea271
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-late-binding.nix
@@ -0,0 +1,4 @@
+let
+  a = b;
+  b = 42;
+in a
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-assert.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-assert.exp
new file mode 100644
index 000000000000..48082f72f087
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-assert.exp
@@ -0,0 +1 @@
+12
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-assert.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-assert.nix
new file mode 100644
index 000000000000..5a36964976ca
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-assert.nix
@@ -0,0 +1,8 @@
+assert true;
+
+let
+  x = assert false; 13;
+  y = 12;
+in
+
+{ inherit x y; }.y
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.exp
new file mode 100644
index 000000000000..1c70d1bcf188
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.exp
@@ -0,0 +1 @@
+[ true true false true true ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.nix
new file mode 100644
index 000000000000..d19d1213d695
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-equality.nix
@@ -0,0 +1,15 @@
+let
+  attrs1 = { x = 1 + 2; };
+  attrs2 = { x = 2 + 1; };
+  list1 = [ (1 + 2) ];
+  list2 = [ (2 + 1) ];
+  list3 = [ (2 + 2) ];
+  list4 = [ (2 + 2) ];
+  list5 = [ (2 + 2) ];
+in [
+  (attrs1 == attrs2)
+  (list1 == list2)
+  (list3 == list2)
+  (list4 == [ 4 ])
+  ([ 4 ] == list5)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.nix
new file mode 100644
index 000000000000..22ac14b3f19e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with-nested.nix
@@ -0,0 +1,5 @@
+# The 'namespace' of a with should only be evaluated if an identifier
+# from it is actually accessed.
+
+with (abort "should not be evaluated");
+let a = dynamic; in 42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.nix
new file mode 100644
index 000000000000..8b1a0191dcc0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-lazy-with.nix
@@ -0,0 +1,6 @@
+# The 'namespace' of a with should only be evaluated if an identifier
+# from it is actually accessed.
+
+with (abort "should not be evaluated");
+
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-fix.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-fix.exp
new file mode 100644
index 000000000000..5d2955ffd5e1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-fix.exp
@@ -0,0 +1 @@
+{ one = 42; two = 42; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-fix.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-fix.nix
new file mode 100644
index 000000000000..87fcffadee5f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-fix.nix
@@ -0,0 +1,9 @@
+let {
+  a = 21;
+  b = body.one;
+
+  body = {
+    one = a * 2;
+    two = b;
+  };
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-in-with.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-in-with.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-in-with.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-in-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-in-with.nix
new file mode 100644
index 000000000000..a5b05426689e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let-in-with.nix
@@ -0,0 +1 @@
+with {}; let { body = 42; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let.nix
new file mode 100644
index 000000000000..850e0252c2b6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-legacy-let.nix
@@ -0,0 +1,4 @@
+let {
+  a = 21;
+  body = a * 2;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-identifiers.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-let-identifiers.exp
new file mode 100644
index 000000000000..5776134d0e41
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-identifiers.exp
@@ -0,0 +1 @@
+[ 1 2 3 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-identifiers.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-let-identifiers.nix
new file mode 100644
index 000000000000..b6c37c34f949
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-identifiers.nix
@@ -0,0 +1,5 @@
+let
+  a = 1;
+  "b" = 2;
+  ${"c"} = 3;
+in [ a b c ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit-from-later-bound.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit-from-later-bound.exp
new file mode 100644
index 000000000000..409940768f2a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit-from-later-bound.exp
@@ -0,0 +1 @@
+23
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit-from-later-bound.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit-from-later-bound.nix
new file mode 100644
index 000000000000..21196f48bcbe
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit-from-later-bound.nix
@@ -0,0 +1,13 @@
+let
+  inherit (c) d;
+  inherit (a) b c;
+
+  a = {
+    b = 20;
+    c = {
+      d = 3;
+    };
+  };
+in
+
+b + d
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.exp
@@ -0,0 +1 @@
+2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix
new file mode 100644
index 000000000000..4ec270e3bf43
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-inherit.nix
@@ -0,0 +1,12 @@
+let
+  set = {
+    a = 1;
+  };
+in
+  let
+    set2 = {
+      b = 1;
+    };
+    inherit (set) a;
+    inherit (set2) b;
+  in a + b
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-sibling-access.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-let-sibling-access.exp
new file mode 100644
index 000000000000..00750edc07d6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-sibling-access.exp
@@ -0,0 +1 @@
+3
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-sibling-access.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-let-sibling-access.nix
new file mode 100644
index 000000000000..7a65a5b1cc9f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-sibling-access.nix
@@ -0,0 +1,5 @@
+let
+  a = 1;
+  b = 2;
+  c = a + b;
+in c
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit-mixed.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit-mixed.exp
new file mode 100644
index 000000000000..3bed31f76e3f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit-mixed.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit-mixed.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit-mixed.nix
new file mode 100644
index 000000000000..30981099cbde
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit-mixed.nix
@@ -0,0 +1,20 @@
+# This test mixes different ways of creating bindings in a let โ€ฆ in expression
+# to make sure that the compiler initialises the locals in the same order as
+# they are declared.
+
+let
+  d = 4;
+in
+
+# Trick to allow useless inherits in the following let
+with { _unused = null; };
+
+let
+  set = { b = 2; };
+  a = 1;
+  inherit (set) b;
+  c = 3;
+  inherit d;
+in
+
+[ a b c d ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit.nix
new file mode 100644
index 000000000000..3d1c46b10bb2
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-let-useful-plain-inherit.nix
@@ -0,0 +1,9 @@
+with { a = 1; };
+
+let
+  inherit a;
+in
+
+with { a = 2; };
+
+a
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-listtoattrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-listtoattrs.exp
new file mode 100644
index 000000000000..74abef7bc6ed
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-listtoattrs.exp
@@ -0,0 +1 @@
+"AAbar"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-listtoattrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-listtoattrs.nix
new file mode 100644
index 000000000000..89888fd56178
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-listtoattrs.nix
@@ -0,0 +1,15 @@
+with builtins;
+let
+  fold = op: nul: list:
+    if list == []
+    then nul
+    else op (head list) (fold op nul (tail list));
+  concat =
+    fold (x: y: x + y) "";
+  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/tvix/eval/src/tests/tvix_tests/eval-okay-manual-rec.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-manual-rec.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-manual-rec.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-manual-rec.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-manual-rec.nix
new file mode 100644
index 000000000000..8e1256d764e3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-manual-rec.nix
@@ -0,0 +1,9 @@
+# Manual desugaring of something similar to `rec`, to test lower level
+# recursion primitives.
+
+let
+  set = with set; {
+    a = 21;
+    b = a * 2;
+  };
+in set.b
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-attrs.exp
new file mode 100644
index 000000000000..911ab51de5ca
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-attrs.exp
@@ -0,0 +1 @@
+{ set = { a = 1; b = 2; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-attrs.nix
new file mode 100644
index 000000000000..78b28909a29c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-attrs.nix
@@ -0,0 +1,9 @@
+{
+  set = {
+    a = 1;
+  };
+
+  set = {
+    b = 2;
+  };
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-rec-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-rec-attrs.exp
new file mode 100644
index 000000000000..768eaae61cfc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-rec-attrs.exp
@@ -0,0 +1 @@
+{ set = { a = 21; b = 42; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-rec-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-rec-attrs.nix
new file mode 100644
index 000000000000..cea4cb1b4f0d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-merge-nested-rec-attrs.nix
@@ -0,0 +1,12 @@
+{
+  set = rec {
+    a = 21;
+  };
+
+  set = {
+    # Fun fact: This might be the only case in Nix where a lexical
+    # resolution of an identifier can only be resolved by looking at
+    # *siblings* in the AST.
+    b = 2 * a;
+  };
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-multiline-string.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-multiline-string.exp
new file mode 100644
index 000000000000..9839e480b781
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-multiline-string.exp
@@ -0,0 +1 @@
+"hello\nworld"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-multiline-string.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-multiline-string.nix
new file mode 100644
index 000000000000..84beb22ed5c3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-multiline-string.nix
@@ -0,0 +1,2 @@
+''hello
+world''
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-multiple-nested-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-multiple-nested-attrs.exp
new file mode 100644
index 000000000000..b5c707cf462e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-multiple-nested-attrs.exp
@@ -0,0 +1 @@
+{ a = { b = 15; }; b = { c = "test"; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-multiple-nested-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-multiple-nested-attrs.nix
new file mode 100644
index 000000000000..5d611930ca7a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-multiple-nested-attrs.nix
@@ -0,0 +1 @@
+{ a.b = 15; b.c = "test"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-mutually-recursive-let-binding.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-mutually-recursive-let-binding.exp
new file mode 100644
index 000000000000..edca9baca9c0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-mutually-recursive-let-binding.exp
@@ -0,0 +1 @@
+{ a = 1; b = 2; c = 3; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-mutually-recursive-let-binding.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-mutually-recursive-let-binding.nix
new file mode 100644
index 000000000000..1b3feda432ef
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-mutually-recursive-let-binding.nix
@@ -0,0 +1,14 @@
+let
+  a = {
+    a = 3;
+    b = b.b;
+  };
+
+  b = {
+    a = a.a - 2;
+    b = 2;
+    c = a.c or 3;
+  };
+in
+
+a // b
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-ne-int.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-ne-int.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-ne-int.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-ne-int.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-ne-int.nix
new file mode 100644
index 000000000000..e06b571a28bf
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-ne-int.nix
@@ -0,0 +1 @@
+42 != 69
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-ne-string.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-ne-string.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-ne-string.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-ne-string.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-ne-string.nix
new file mode 100644
index 000000000000..a83471e500ce
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-ne-string.nix
@@ -0,0 +1 @@
+"this" != "that"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-closure.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-closure.exp
new file mode 100644
index 000000000000..b6a7d89c68e0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-closure.exp
@@ -0,0 +1 @@
+16
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-closure.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-closure.nix
new file mode 100644
index 000000000000..97bff7f07758
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-closure.nix
@@ -0,0 +1 @@
+(a: b: c: d: a + b + c + d) 1 3 5 7
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-deferred-upvalue.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-deferred-upvalue.exp
new file mode 100644
index 000000000000..209e3ef4b624
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-deferred-upvalue.exp
@@ -0,0 +1 @@
+20
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-deferred-upvalue.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-deferred-upvalue.nix
new file mode 100644
index 000000000000..358925e992c7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-deferred-upvalue.nix
@@ -0,0 +1,6 @@
+let
+  doubler = n: outer n;
+  outer = let inner = n: a * n;
+            a = 2;
+          in inner;
+in doubler 10
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.exp
new file mode 100644
index 000000000000..d2c1c04da3c4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.exp
@@ -0,0 +1 @@
+[ true true true true true true true false false false false false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.nix
new file mode 100644
index 000000000000..47dcec7a95f4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-has-attrs.nix
@@ -0,0 +1,26 @@
+let
+  set = {
+    a.b.c = 123;
+    foo = {
+      bar = 23;
+    };
+    baz = 1;
+  };
+
+  tes = "random value";
+in
+
+[
+  (set ? a)
+  (set ? a.b)
+  (set ? a.b.c)
+  (set ? foo)
+  (set ? foo.bar)
+  (set.foo ? bar)
+  (set ? baz)
+  (set ? x)
+  (set ? x.y.z)
+  (tes ? bar)
+  (tes ? x.y.z)
+  (null ? null)
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-let.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-let.exp
new file mode 100644
index 000000000000..6db47b033efb
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-let.exp
@@ -0,0 +1 @@
+{ a = { b = 42; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-let.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-let.nix
new file mode 100644
index 000000000000..c75b7130e1ba
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-let.nix
@@ -0,0 +1,4 @@
+let
+  inner = 21;
+  set.a.b = inner * 2;
+in set
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-rec.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-rec.exp
new file mode 100644
index 000000000000..77eb325dde19
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-rec.exp
@@ -0,0 +1 @@
+{ a = { b = { c = 42; }; }; outer = 21; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-rec.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-rec.nix
new file mode 100644
index 000000000000..797d11108ff4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-keys-rec.nix
@@ -0,0 +1,4 @@
+rec {
+  outer = 21;
+  a.b.c = outer * 2;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let-slots.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let-slots.exp
new file mode 100644
index 000000000000..e45ef1da2f54
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let-slots.exp
@@ -0,0 +1 @@
+[ 1 2 3 4 5 6 7 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let-slots.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let-slots.nix
new file mode 100644
index 000000000000..811bb4361bf7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let-slots.nix
@@ -0,0 +1,17 @@
+# This test deals with a tricky edge-case around scopes, where the
+# stack slot accounting must correctly account for the position at
+# which the body of a let expression is being initialised when
+# resolving upvalues.
+
+let
+  a = 1;
+  b = 2;
+  outer = let
+    c = 3;
+    d = 4;
+    inner = let
+      e = 5;
+      f = 6;
+    in g: [ a b c d e f g ];
+  in inner;
+in outer 7
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let.exp
new file mode 100644
index 000000000000..7f8f011eb73d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let.exp
@@ -0,0 +1 @@
+7
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let.nix
new file mode 100644
index 000000000000..caaa20211928
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-let.nix
@@ -0,0 +1,7 @@
+let
+  a = let
+    b = 1;
+    c = 2;
+  in b + c;
+  b = 4;
+in a + b
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-poisoning.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-poisoning.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-poisoning.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-poisoning.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-poisoning.nix
new file mode 100644
index 000000000000..8d0280bb8973
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-poisoning.nix
@@ -0,0 +1,4 @@
+let
+  null = 1;
+  f = n: n + null;
+in f 41
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-set-thunks.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-set-thunks.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-set-thunks.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-set-thunks.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-set-thunks.nix
new file mode 100644
index 000000000000..f3ad8293540f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-set-thunks.nix
@@ -0,0 +1,5 @@
+({
+  x = {
+    y = 42;
+  };
+}).x.y
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-siblings.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-siblings.exp
new file mode 100644
index 000000000000..d757cae1f588
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-siblings.exp
@@ -0,0 +1 @@
+{ outer = 42; sibling = 42; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-siblings.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-siblings.nix
new file mode 100644
index 000000000000..31111d80810c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-siblings.nix
@@ -0,0 +1,7 @@
+rec {
+  outer =
+    let inner = sibling;
+    in inner;
+
+  sibling = 42;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-thunks.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-thunks.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-thunks.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-thunks.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-thunks.nix
new file mode 100644
index 000000000000..133929dd1961
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-thunks.nix
@@ -0,0 +1,7 @@
+# If a thunk yields another thunk, OpForce should keep forcing until
+# there is a value.
+let
+  a = b;
+  b = c;
+  c = 42;
+in a
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-with.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-with.exp
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-with.exp
@@ -0,0 +1 @@
+2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nested-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-with.nix
new file mode 100644
index 000000000000..ea5ef568edab
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nested-with.nix
@@ -0,0 +1,4 @@
+let
+  set1 = { a = 1; };
+  set2 = { a = 2; };
+in with set1; with set2; a
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nix-version-cmp.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-nix-version-cmp.exp
new file mode 100644
index 000000000000..3a2e3f4984a0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nix-version-cmp.exp
@@ -0,0 +1 @@
+-1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-nix-version-cmp.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-nix-version-cmp.nix
new file mode 100644
index 000000000000..6f353056127c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-nix-version-cmp.nix
@@ -0,0 +1,5 @@
+# nixpkgs checks against the `builtins.nixVersion` and fails if it
+# doesn't like what it sees. To work around this we have a "user-agent
+# style" version (see cl/6858) that ensures compatibility.
+
+builtins.compareVersions "2.3" builtins.nixVersion
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-observe-infinite-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-observe-infinite-attrs.exp
new file mode 100644
index 000000000000..bbb332a5eea0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-observe-infinite-attrs.exp
@@ -0,0 +1 @@
+[ "x" "y" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-observe-infinite-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-observe-infinite-attrs.nix
new file mode 100644
index 000000000000..684c88f80067
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-observe-infinite-attrs.nix
@@ -0,0 +1,4 @@
+# The below attribute set is infinitely large, but we should be able
+# to observe it as long as we don't access its entire value.
+
+let as = { x = 123; y = as; }; in builtins.attrNames as.y.y
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-optimised-bools.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-optimised-bools.exp
new file mode 100644
index 000000000000..9d9185fcd155
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-optimised-bools.exp
@@ -0,0 +1 @@
+[ true true false false true true false false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-optimised-bools.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-optimised-bools.nix
new file mode 100644
index 000000000000..650d7f028df2
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-optimised-bools.nix
@@ -0,0 +1,21 @@
+let
+  makeTrue = _: true;
+  makeFalse = _: false;
+in
+[
+  # useless `false`
+  (false || makeTrue null) # true
+  (makeTrue null || false) # true
+
+  # useless `true`
+  (true && makeFalse null) # false
+  (makeFalse null && true) # false
+
+  # useless `||`
+  (true || makeFalse null) # true
+  (makeFalse null || true) # true
+
+  # useless `&&`
+  (false && makeTrue null) # false
+  (makeTrue null && false) # false
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-default.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-default.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-default.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-default.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-default.nix
new file mode 100644
index 000000000000..444f270af637
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-default.nix
@@ -0,0 +1 @@
+{ b = 1; }.b or 2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested-default.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested-default.exp
new file mode 100644
index 000000000000..0cfbf08886fc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested-default.exp
@@ -0,0 +1 @@
+2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested-default.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested-default.nix
new file mode 100644
index 000000000000..ceffd0697b28
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested-default.nix
@@ -0,0 +1 @@
+{ a.b = 1; }.a.c or 2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested.nix
new file mode 100644
index 000000000000..1a76594546b3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-nested.nix
@@ -0,0 +1 @@
+{ a.b = 1; }.a.b or 2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.exp
new file mode 100644
index 000000000000..a833e32892e4
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.exp
@@ -0,0 +1 @@
+"works fine"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.nix
new file mode 100644
index 000000000000..fd09bfee64c2
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator-non-set.nix
@@ -0,0 +1,2 @@
+# `or` operator should keep working if it encounters a non-set type.
+{ a.b = 42; }.a.b.c or "works fine"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator.nix
new file mode 100644
index 000000000000..ce1e6e67c289
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-or-operator.nix
@@ -0,0 +1 @@
+{ a = 1; }.a or 2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-overlapping-nested-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-overlapping-nested-attrs.exp
new file mode 100644
index 000000000000..2483a2718301
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-overlapping-nested-attrs.exp
@@ -0,0 +1 @@
+{ a = { b = 15; c = "test"; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-overlapping-nested-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-overlapping-nested-attrs.nix
new file mode 100644
index 000000000000..4154ff9da29f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-overlapping-nested-attrs.nix
@@ -0,0 +1,4 @@
+{
+  a.b = 15;
+  a.c = "test";
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-parsedrvname.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-parsedrvname.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-parsedrvname.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-parsedrvname.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-parsedrvname.nix
new file mode 100644
index 000000000000..fea6e234dcfd
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-parsedrvname.nix
@@ -0,0 +1,12 @@
+
+# the first dash followed by a non-alphabetic character separates
+# the "name" from the "version"
+
+assert builtins.parseDrvName "ripgrep-1.2"       == { name = "ripgrep";       version = "1.2"; };
+assert builtins.parseDrvName "rip-grep-1.2"      == { name = "rip-grep";      version = "1.2"; };
+assert builtins.parseDrvName "7zip_archiver-0.2" == { name = "7zip_archiver"; version = "0.2"; };
+assert builtins.parseDrvName "gcc-1-2"           == { name = "gcc";           version = "1-2"; };
+assert builtins.parseDrvName "bash--1-2"         == { name = "bash";          version = "-1-2"; };
+assert builtins.parseDrvName "xvidtune-?1-2"     == { name = "xvidtune";      version = "?1-2"; };
+
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-pathexists.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-pathexists.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-pathexists.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-pathexists.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-pathexists.nix
new file mode 100644
index 000000000000..ab3d0369401c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-pathexists.nix
@@ -0,0 +1,2 @@
+builtins.pathExists ./lib.nix
+&& !builtins.pathExists ./bla.nix
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-poisoned-scopes.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-poisoned-scopes.exp
new file mode 100644
index 000000000000..5776134d0e41
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-poisoned-scopes.exp
@@ -0,0 +1 @@
+[ 1 2 3 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-poisoned-scopes.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-poisoned-scopes.nix
new file mode 100644
index 000000000000..81f03d9e2b09
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-poisoned-scopes.nix
@@ -0,0 +1,6 @@
+let
+  true = 1;
+  false = 2;
+  null = 3;
+in
+[ true false null ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.exp
new file mode 100644
index 000000000000..bf8d2c14ea4f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.exp
@@ -0,0 +1 @@
+{ bar = "regular"; foo = "directory"; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.nix.disabled b/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.nix.disabled
new file mode 100644
index 000000000000..a7ec9292aae2
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-readDir.nix.disabled
@@ -0,0 +1 @@
+builtins.readDir ./readDir
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-readfile.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-readfile.exp
new file mode 100644
index 000000000000..a2c87d0c439f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-readfile.exp
@@ -0,0 +1 @@
+"builtins.readFile ./eval-okay-readfile.nix\n"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-readfile.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-readfile.nix
new file mode 100644
index 000000000000..82f7cb17435a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-readfile.nix
@@ -0,0 +1 @@
+builtins.readFile ./eval-okay-readfile.nix
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-rec-dynamic-keys.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-rec-dynamic-keys.exp
new file mode 100644
index 000000000000..ac8d062a6911
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-rec-dynamic-keys.exp
@@ -0,0 +1 @@
+{ barbaz = 42; foobar = 42; val = 21; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-rec-dynamic-keys.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-rec-dynamic-keys.nix
new file mode 100644
index 000000000000..8d7a8cef8e10
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-rec-dynamic-keys.nix
@@ -0,0 +1,5 @@
+rec {
+  val = 21;
+  ${"foo" + "bar"} = 42;
+  ${"bar" + "baz"} = val * 2;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-rec-nested-access.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-rec-nested-access.exp
new file mode 100644
index 000000000000..a1dca9bb6860
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-rec-nested-access.exp
@@ -0,0 +1 @@
+{ a = { b = 1; c = 2; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-rec-nested-access.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-rec-nested-access.nix
new file mode 100644
index 000000000000..7d037c6b37bc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-rec-nested-access.nix
@@ -0,0 +1,4 @@
+rec {
+  a.b = 1;
+  a.c = a.b * 2;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-recursive-attrs-all-features.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-recursive-attrs-all-features.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-recursive-attrs-all-features.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-recursive-attrs-all-features.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-recursive-attrs-all-features.nix
new file mode 100644
index 000000000000..a234705b5e53
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-recursive-attrs-all-features.nix
@@ -0,0 +1,13 @@
+let a = 1;
+in
+(rec {
+  inherit a;
+
+  b = {
+    c = a + 20;
+  };
+
+  inherit (b) c;
+
+  d = c * 2;
+}).d
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-regex-match.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-regex-match.exp
new file mode 100644
index 000000000000..950103539123
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-regex-match.exp
@@ -0,0 +1 @@
+[ true true false true true true true false false true false [ "foobar" ] [ "FOO" ] [ "/path/to/" "/path/to" "foobar" "nix" ] [ null null "foobar" "cc" ] ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-regex-match.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-regex-match.nix
new file mode 100644
index 000000000000..f774e00a215a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-regex-match.nix
@@ -0,0 +1,29 @@
+with builtins;
+
+let
+
+  matches = pat: s: match pat s != null;
+
+  splitFN = match "((.*)/)?([^/]*)\\.(nix|cc)";
+
+in
+
+[
+  (matches "foobar" "foobar")
+  (matches "fo*" "f")
+  (matches "fo+" "f")
+  (matches "fo*" "fo")
+  (matches "fo*" "foo")
+  (matches "fo+" "foo")
+  (matches "fo{1,2}" "foo")
+  (matches "fo{1,2}" "fooo")
+  (matches "fo*" "foobar")
+  (matches "[[:space:]]+([^[:space:]]+)[[:space:]]+" "  foo   ")
+  (matches "[[:space:]]+([[:upper:]]+)[[:space:]]+" "  foo   ")
+
+  (match "(.*)\\.nix" "foobar.nix")
+  (match "[[:space:]]+([[:upper:]]+)[[:space:]]+" "  FOO   ")
+
+  (splitFN "/path/to/foobar.nix")
+  (splitFN "foobar.cc")
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-remove.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-remove.exp
new file mode 100644
index 000000000000..8d38505c1686
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-remove.exp
@@ -0,0 +1 @@
+456
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-remove.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-remove.nix
new file mode 100644
index 000000000000..4ad5ba897fa7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/eval-okay-repeated-list-to-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-repeated-list-to-attrs.exp
new file mode 100644
index 000000000000..b4a1e66d6b8a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-repeated-list-to-attrs.exp
@@ -0,0 +1 @@
+[ 1 2 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-repeated-list-to-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-repeated-list-to-attrs.nix
new file mode 100644
index 000000000000..2f719dcef5be
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-repeated-list-to-attrs.nix
@@ -0,0 +1,13 @@
+# Ensure that builtins.listToAttrs returns the first instance of a key.
+
+let
+  inherit (builtins) foldl' listToAttrs;
+
+  input = [ { name = "result"; value = 1; } { name = "result"; value = 2; } ];
+
+  # foldl-based version of listToAttrs with the _opposite_ behaviour.
+  listToAttrs' = list: foldl' ( acc: elem: acc // { ${elem.name} = elem.value; }) {} list;
+in [
+  (listToAttrs input).result
+  (listToAttrs' input).result
+]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-seq.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-seq.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-seq.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-seq.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-seq.nix
new file mode 100644
index 000000000000..fd0806c199a5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-seq.nix
@@ -0,0 +1 @@
+(builtins.seq 1 2) + (builtins.seq [ (throw "list") ] 20) + (builtins.seq { boing = throw "set"; } 20)
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-closure.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-closure.exp
new file mode 100644
index 000000000000..7f8f011eb73d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-closure.exp
@@ -0,0 +1 @@
+7
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-closure.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-closure.nix
new file mode 100644
index 000000000000..56445454fec7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-closure.nix
@@ -0,0 +1 @@
+(a: b: a + b) 2 5
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-interpol.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-interpol.exp
new file mode 100644
index 000000000000..cd4bc1ab64cc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-interpol.exp
@@ -0,0 +1 @@
+"hello world"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-interpol.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-interpol.nix
new file mode 100644
index 000000000000..125b0859ac42
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-interpol.nix
@@ -0,0 +1 @@
+"hello ${"world"}"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-let.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-let.exp
new file mode 100644
index 000000000000..00750edc07d6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-let.exp
@@ -0,0 +1 @@
+3
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-let.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-let.nix
new file mode 100644
index 000000000000..b440a220ff6d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-let.nix
@@ -0,0 +1,4 @@
+let
+  a = 1;
+  b = 2;
+in a + b
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-nested-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-nested-attrs.exp
new file mode 100644
index 000000000000..6db47b033efb
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-nested-attrs.exp
@@ -0,0 +1 @@
+{ a = { b = 42; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-nested-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-nested-attrs.nix
new file mode 100644
index 000000000000..a97394d16523
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-nested-attrs.nix
@@ -0,0 +1 @@
+{ a.b = 42; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-recursive-attrs.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-recursive-attrs.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-recursive-attrs.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-recursive-attrs.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-recursive-attrs.nix
new file mode 100644
index 000000000000..c86ff80383c0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-recursive-attrs.nix
@@ -0,0 +1,4 @@
+(rec {
+  a = 21;
+  b = a * 2;
+}).b
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-with.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-with.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-with.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-simple-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-with.nix
new file mode 100644
index 000000000000..64962b50ff63
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-simple-with.nix
@@ -0,0 +1,5 @@
+let
+  set = {
+    a = 1;
+  };
+in with set; a
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-stable-sort.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-stable-sort.exp
new file mode 100644
index 000000000000..9d783762143e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-stable-sort.exp
@@ -0,0 +1 @@
+[ { index = 7; key = 0; } { index = 0; key = 1; } { index = 13; key = 1; } { index = 1; key = 2; } { index = 3; key = 2; } { index = 4; key = 2; } { index = 5; key = 2; } { index = 12; key = 2; } { index = 14; key = 2; } { index = 2; key = 3; } { index = 11; key = 3; } { index = 15; key = 3; } { index = 10; key = 4; } { index = 6; key = 5; } { index = 8; key = 5; } { index = 9; key = 5; } { index = 16; key = 22; } ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-stable-sort.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-stable-sort.nix
new file mode 100644
index 000000000000..9969e0a29433
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-stable-sort.nix
@@ -0,0 +1,7 @@
+let
+  keys = [ 1 2 3 2 2 2 5 0 5 5 4 3 2 1 2 3 22 ];
+in
+
+builtins.sort
+  (a: b: a.key < b.key)
+  (builtins.genList (index: { inherit index; key = builtins.elemAt keys index; }) (builtins.length keys))
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-functor.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-functor.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-functor.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-functor.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-functor.nix
new file mode 100644
index 000000000000..f8eba2ac2fc0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-functor.nix
@@ -0,0 +1,7 @@
+let
+  __functor = f;
+  f = self: x: self.out * x;
+in {
+  inherit __functor;
+  out = 21;
+} 2
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.exp
new file mode 100644
index 000000000000..ffcd4415b08f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.exp
@@ -0,0 +1 @@
+{ }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.nix
new file mode 100644
index 000000000000..65e9e66d74dc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-if.nix
@@ -0,0 +1,6 @@
+let
+  a = {};
+in let
+  c = if builtins.isFunction a then a b else a;
+  b = {};
+in c
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-string-interpolation.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-string-interpolation.exp
new file mode 100644
index 000000000000..fc2f21e9305c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-string-interpolation.exp
@@ -0,0 +1 @@
+"strict literal"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-string-interpolation.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-string-interpolation.nix
new file mode 100644
index 000000000000..bd3555bb2412
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-string-interpolation.nix
@@ -0,0 +1,7 @@
+let
+  final = { text = "strict literal"; inherit x y; };
+  x = "lazy ${throw "interpolation"}";
+  y = "${throw "also lazy!"}";
+in
+
+final.text
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-with.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-with.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-with.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-with.nix
new file mode 100644
index 000000000000..6f32660c4c33
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-thunked-with.nix
@@ -0,0 +1,7 @@
+# Creates a `with` across multiple thunk boundaries.
+
+let
+  set = {
+    a = with { b = 42; }; b;
+  };
+in set.a
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.exp
new file mode 100644
index 000000000000..edca9baca9c0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.exp
@@ -0,0 +1 @@
+{ a = 1; b = 2; c = 3; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.nix
new file mode 100644
index 000000000000..4c6884bec3df
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-toplevel-finaliser.nix
@@ -0,0 +1,10 @@
+# A simple expression with upvalue resolution beyond the target stack
+# index of the root expression.
+
+let
+  a = 1;
+  b = 2;
+  c = 3;
+in {
+  inherit a b c;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval.exp
new file mode 100644
index 000000000000..8b6ed7dbac6b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval.exp
@@ -0,0 +1 @@
+{ v = false; w = { success = false; value = false; }; x = { success = true; value = "x"; }; y = { success = false; value = false; }; z = { success = false; value = false; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval.nix
new file mode 100644
index 000000000000..e2357c798753
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval.nix
@@ -0,0 +1,7 @@
+{
+  v = (builtins.tryEval (toString <oink>)).value;
+  w = builtins.tryEval <nope>;
+  x = builtins.tryEval "x";
+  y = builtins.tryEval (assert false; "y");
+  z = builtins.tryEval (throw "bla");
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-unpoison-scope.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-unpoison-scope.exp
new file mode 100644
index 000000000000..5462431496bc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-unpoison-scope.exp
@@ -0,0 +1 @@
+[ true false null 1 2 3 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-unpoison-scope.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-unpoison-scope.nix
new file mode 100644
index 000000000000..30e9667da821
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-unpoison-scope.nix
@@ -0,0 +1,7 @@
+let
+  poisoned = let
+    true = 1;
+    false = 2;
+    null = 3;
+  in [ true false null ];
+in [ true false null ] ++ poisoned
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-useless-inherit-with.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-useless-inherit-with.exp
new file mode 100644
index 000000000000..d00491fd7e5b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-useless-inherit-with.exp
@@ -0,0 +1 @@
+1
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-useless-inherit-with.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-useless-inherit-with.nix
new file mode 100644
index 000000000000..d335e5363000
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-useless-inherit-with.nix
@@ -0,0 +1,15 @@
+# Normally using an `inherit` without a source attribute set within a
+# `let` is a no-op, *unless* there is a with in-scope that might
+# provide the value.
+
+# Provide a dynamic `x` identifier in the scope.
+with ({ x = 1;});
+
+# inherit this `x` as a static identifier
+let inherit x;
+
+# Provide another dynamic `x` identifier
+in with ({ x = 3; });
+
+# Inherited static identifier should have precedence
+x
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-compare.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-compare.exp
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-compare.exp
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-compare.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-compare.nix
new file mode 100644
index 000000000000..f60d27d38157
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-compare.nix
@@ -0,0 +1,6 @@
+# For an explanation of this behavior see //tvix/docs/value-pointer-equality.md
+let
+  f = owo: "thia";
+in
+
+[ f 42 ] > [ f 21 ]
\ No newline at end of file
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-equality.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-equality.exp
new file mode 100644
index 000000000000..aec30f297af9
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-equality.exp
@@ -0,0 +1 @@
+[ true true true true false false false true true true true true true true true true false false ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-equality.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-equality.nix
new file mode 100644
index 000000000000..206881d7d9c2
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-value-pointer-equality.nix
@@ -0,0 +1,46 @@
+# For an explanation of this behavior see //tvix/docs/value-pointer-equality.md
+let
+  # Some incomparable values
+  f = MC: "Boing";
+  t = [ (throw "is a little blue man") ];
+  a = { "with" = abort "headphones and a big smile."; };
+
+  # Aliases
+  f' = f;
+  t' = t;
+  a' = a;
+
+  peq1 = a: b: [ a ] == [ b ];
+  peq2 = a: b: { x = a; } == { x = b; };
+in
+
+[
+  # pointer equality of functions
+  (peq1 f f)
+  (peq2 f f)
+  (peq1 f f')
+  (peq2 f f')
+
+  # encapsulation is necessary for pointer equality
+  (f == f)
+  (f == f')
+  # works with !=
+  ([ f ] != [ f' ])
+
+  # thunks that fail to evaluated wrapped in sets/lists
+  (peq1 t t)
+  (peq2 t t)
+  (peq1 a a)
+  (peq2 a a)
+  (peq1 t t')
+  (peq2 t t')
+  (peq1 a' a)
+  (peq2 a' a)
+
+  # function equality with builtins.elem
+  (builtins.elem f [ 21 f 42 ])
+
+  # pointer inequality
+  (peq1 f (x: x))
+  (peq2 (x: x) f)
+]
\ No newline at end of file
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-with-closure.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-with-closure.exp
new file mode 100644
index 000000000000..fa8f08cb6ff8
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-with-closure.exp
@@ -0,0 +1 @@
+150
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-with-closure.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-with-closure.nix
new file mode 100644
index 000000000000..7e2f7c073bfc
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-with-closure.nix
@@ -0,0 +1,5 @@
+# Upvalues from `with` require special runtime handling. Do they work?
+let
+  f = with { a = 15; }; n: n * a;
+in
+f 10
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-dynamic-key.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-dynamic-key.exp
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-dynamic-key.exp
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-dynamic-key.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-dynamic-key.nix
new file mode 100644
index 000000000000..c44455a5bf83
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-dynamic-key.nix
@@ -0,0 +1,12 @@
+# Tests correct tracking of stack indices within construction of an
+# attribute set. Dynamic keys can be any expression, so something that
+# is extremely sensitive to stack offsets (like `with`) can be tricky.
+
+let
+  set1 = { key = "b"; };
+  set2 = {
+    a = 20;
+    ${with set1; key} = 20;
+    ${with { key = "c"; }; key} = 2;
+  };
+in set2.a + set2.b + set2.c
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-list.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-list.exp
new file mode 100644
index 000000000000..5776134d0e41
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-list.exp
@@ -0,0 +1 @@
+[ 1 2 3 ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-list.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-list.nix
new file mode 100644
index 000000000000..bb62fdf31cd7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-with-in-list.nix
@@ -0,0 +1,13 @@
+# This code causes a situation where a list element causes an
+# additional phantom value to temporarily be placed on the locals
+# stack, which must be correctly accounted for by the compiler.
+
+let
+  set = {
+    value = 2;
+  };
+in [
+  1
+  (with set; value)
+  3
+]
diff --git a/tvix/eval/src/tests/tvix_tests/identity-bool-false.nix b/tvix/eval/src/tests/tvix_tests/identity-bool-false.nix
new file mode 100644
index 000000000000..c508d5366f70
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-bool-false.nix
@@ -0,0 +1 @@
+false
diff --git a/tvix/eval/src/tests/tvix_tests/identity-bool-true.nix b/tvix/eval/src/tests/tvix_tests/identity-bool-true.nix
new file mode 100644
index 000000000000..27ba77ddaf61
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-bool-true.nix
@@ -0,0 +1 @@
+true
diff --git a/tvix/eval/src/tests/tvix_tests/identity-dollar-escape.nix b/tvix/eval/src/tests/tvix_tests/identity-dollar-escape.nix
new file mode 100644
index 000000000000..08951d7637a6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-dollar-escape.nix
@@ -0,0 +1 @@
+"\${foobar}"
diff --git a/tvix/eval/src/tests/tvix_tests/identity-empty-attrs.nix b/tvix/eval/src/tests/tvix_tests/identity-empty-attrs.nix
new file mode 100644
index 000000000000..ffcd4415b08f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-empty-attrs.nix
@@ -0,0 +1 @@
+{ }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-empty-list.nix b/tvix/eval/src/tests/tvix_tests/identity-empty-list.nix
new file mode 100644
index 000000000000..1e3ec7217afb
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-empty-list.nix
@@ -0,0 +1 @@
+[ ]
diff --git a/tvix/eval/src/tests/tvix_tests/identity-flat-attrs.nix b/tvix/eval/src/tests/tvix_tests/identity-flat-attrs.nix
new file mode 100644
index 000000000000..e7c2ae18a661
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-flat-attrs.nix
@@ -0,0 +1 @@
+{ a = 15; b = "string"; c = null; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-float.nix b/tvix/eval/src/tests/tvix_tests/identity-float.nix
new file mode 100644
index 000000000000..bf77d549685a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-float.nix
@@ -0,0 +1 @@
+4.2
diff --git a/tvix/eval/src/tests/tvix_tests/identity-heterogeneous-list.nix b/tvix/eval/src/tests/tvix_tests/identity-heterogeneous-list.nix
new file mode 100644
index 000000000000..87f7fb0d0668
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-heterogeneous-list.nix
@@ -0,0 +1 @@
+[ 1 2.1 "three" null ]
diff --git a/tvix/eval/src/tests/tvix_tests/identity-homogeneous-float-list.nix b/tvix/eval/src/tests/tvix_tests/identity-homogeneous-float-list.nix
new file mode 100644
index 000000000000..48e6655fb169
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-homogeneous-float-list.nix
@@ -0,0 +1 @@
+[ 4.2 6.9 13.37 ]
diff --git a/tvix/eval/src/tests/tvix_tests/identity-homogeneous-int-list.nix b/tvix/eval/src/tests/tvix_tests/identity-homogeneous-int-list.nix
new file mode 100644
index 000000000000..d23a5c38147b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-homogeneous-int-list.nix
@@ -0,0 +1 @@
+[ 0 1 2 3 4 5 7 8 9 ]
diff --git a/tvix/eval/src/tests/tvix_tests/identity-homogeneous-string-list.nix b/tvix/eval/src/tests/tvix_tests/identity-homogeneous-string-list.nix
new file mode 100644
index 000000000000..d78a54e5b002
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-homogeneous-string-list.nix
@@ -0,0 +1 @@
+[ "string" "list" ]
diff --git a/tvix/eval/src/tests/tvix_tests/identity-int.nix b/tvix/eval/src/tests/tvix_tests/identity-int.nix
new file mode 100644
index 000000000000..d81cc0710eb6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-int.nix
@@ -0,0 +1 @@
+42
diff --git a/tvix/eval/src/tests/tvix_tests/identity-kv-attrs.nix b/tvix/eval/src/tests/tvix_tests/identity-kv-attrs.nix
new file mode 100644
index 000000000000..f1398b8d0592
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-kv-attrs.nix
@@ -0,0 +1 @@
+{ name = "foo"; value = 12; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-nested-attrs.nix b/tvix/eval/src/tests/tvix_tests/identity-nested-attrs.nix
new file mode 100644
index 000000000000..6a139452ef28
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-nested-attrs.nix
@@ -0,0 +1 @@
+{ a = { b = null; }; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-null.nix b/tvix/eval/src/tests/tvix_tests/identity-null.nix
new file mode 100644
index 000000000000..19765bd501b6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-null.nix
@@ -0,0 +1 @@
+null
diff --git a/tvix/eval/src/tests/tvix_tests/identity-signed-float.nix b/tvix/eval/src/tests/tvix_tests/identity-signed-float.nix
new file mode 100644
index 000000000000..50c9d06aa52c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-signed-float.nix
@@ -0,0 +1 @@
+-4.2
diff --git a/tvix/eval/src/tests/tvix_tests/identity-signed-int.nix b/tvix/eval/src/tests/tvix_tests/identity-signed-int.nix
new file mode 100644
index 000000000000..6a0e60d48b17
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-signed-int.nix
@@ -0,0 +1 @@
+-42
diff --git a/tvix/eval/src/tests/tvix_tests/identity-string.nix b/tvix/eval/src/tests/tvix_tests/identity-string.nix
new file mode 100644
index 000000000000..d71ddbcf823f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-string.nix
@@ -0,0 +1 @@
+"test string"
diff --git a/tvix/eval/src/tests/tvix_tests/lib.nix b/tvix/eval/src/tests/tvix_tests/lib.nix
new file mode 100644
index 000000000000..028a538314b7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/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/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-minimal-2.3-builtins.exp b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-minimal-2.3-builtins.exp
new file mode 100644
index 000000000000..967fc858bc3d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-minimal-2.3-builtins.exp
@@ -0,0 +1 @@
+[ "abort" "add" "addErrorContext" "all" "any" "appendContext" "attrNames" "attrValues" "baseNameOf" "bitAnd" "bitOr" "bitXor" "builtins" "catAttrs" "compareVersions" "concatLists" "concatMap" "concatStringsSep" "currentSystem" "currentTime" "deepSeq" "derivation" "derivationStrict" "dirOf" "div" "elem" "elemAt" "false" "fetchGit" "fetchMercurial" "fetchTarball" "fetchurl" "filter" "filterSource" "findFile" "foldl'" "fromJSON" "fromTOML" "functionArgs" "genList" "genericClosure" "getAttr" "getContext" "getEnv" "hasAttr" "hasContext" "hashFile" "hashString" "head" "import" "intersectAttrs" "isAttrs" "isBool" "isFloat" "isFunction" "isInt" "isList" "isNull" "isPath" "isString" "langVersion" "length" "lessThan" "listToAttrs" "map" "mapAttrs" "match" "mul" "nixPath" "nixVersion" "null" "parseDrvName" "partition" "path" "pathExists" "placeholder" "readDir" "readFile" "removeAttrs" "replaceStrings" "scopedImport" "seq" "sort" "split" "splitVersion" "storeDir" "storePath" "stringLength" "sub" "substring" "tail" "throw" "toFile" "toJSON" "toPath" "toString" "toXML" "trace" "true" "tryEval" "typeOf" "unsafeDiscardOutputDependency" "unsafeDiscardStringContext" "unsafeGetAttrPos" ]
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-minimal-2.3-builtins.nix b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-minimal-2.3-builtins.nix
new file mode 100644
index 000000000000..804355f34d10
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-minimal-2.3-builtins.nix
@@ -0,0 +1,35 @@
+# This tests verifies that the Nix implementation evaluating this has at least
+# all the builtins given in `minimalBuiltins`. We don't test a precise list of
+# builtins since we accept that there will always be difference between the
+# builtins sets of Tvix, C++ Nix 2.3 and newer C++ Nix versions, as new builtins
+# are added.
+#
+# Tvix also may choose never to implement some builtins if they are only useful
+# for flakes or perform well enough via the shims nixpkgs usually provides.
+
+let
+  # C++ Nix 2.3 builtins except valueSize which is removed in later versions
+  minimalBuiltins = [
+    "abort" "add" "addErrorContext" "all" "any" "appendContext" "attrNames"
+    "attrValues" "baseNameOf" "bitAnd" "bitOr" "bitXor" "builtins" "catAttrs"
+    "compareVersions" "concatLists" "concatMap" "concatStringsSep"
+    "currentSystem" "currentTime" "deepSeq" "derivation" "derivationStrict"
+    "dirOf" "div" "elem" "elemAt" "false" "fetchGit" "fetchMercurial"
+    "fetchTarball" "fetchurl" "filter" "filterSource" "findFile" "foldl'"
+    "fromJSON" "fromTOML" "functionArgs" "genList" "genericClosure" "getAttr"
+    "getContext" "getEnv" "hasAttr" "hasContext" "hashFile" "hashString" "head"
+    "import" "intersectAttrs" "isAttrs" "isBool" "isFloat" "isFunction" "isInt"
+    "isList" "isNull" "isPath" "isString" "langVersion" "length" "lessThan"
+    "listToAttrs" "map" "mapAttrs" "match" "mul" "nixPath" "nixVersion" "null"
+    "parseDrvName" "partition" "path" "pathExists" "placeholder" "readDir"
+    "readFile" "removeAttrs" "replaceStrings" "scopedImport" "seq" "sort"
+    "split" "splitVersion" "storeDir" "storePath" "stringLength" "sub"
+    "substring" "tail" "throw" "toFile" "toJSON" "toPath" "toString" "toXML"
+    "trace" "true" "tryEval" "typeOf" "unsafeDiscardOutputDependency"
+    "unsafeDiscardStringContext" "unsafeGetAttrPos"
+  ];
+
+  intersectLists = as: bs: builtins.filter (a: builtins.elem a bs) as;
+in
+
+intersectLists minimalBuiltins (builtins.attrNames builtins)
diff --git a/tvix/eval/src/tests/tvix_tests/readDir/bar b/tvix/eval/src/tests/tvix_tests/readDir/bar
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/readDir/bar
diff --git a/tvix/eval/src/tests/tvix_tests/readDir/foo/.keep b/tvix/eval/src/tests/tvix_tests/readDir/foo/.keep
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/readDir/foo/.keep