about summary refs log tree commit diff
path: root/tvix/eval/src/tests/tvix_tests
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/eval/src/tests/tvix_tests')
-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-substring-negative-start.nix3
-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-division-by-zero-float.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-fail-division-by-zero-int.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-function-formals-typecheck.nix2
-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.nix34
-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-genericClosure-pointer-equality.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-pointer-equality.nix15
-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.nix6
-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-negative-length.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-negative-length.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-escape-string-correct-char-boundaries.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-escape-string-correct-char-boundaries.nix6
-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-formals-miscompilation-b-261-regression.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-formals-miscompilation-b-261-regression.nix20
-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.nix42
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-import-display.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-import-display.nix2
-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-observable-eval-cache.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-observable-eval-cache.nix7
-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-thunk-twice.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-tryeval-thunk-twice.nix1
-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-display.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/eval-okay-value-display.nix16
-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-quoted-attrname-assert.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-else.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-if.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-in.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-inherit.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-let.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-rec.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-then.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-with.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-fail-builtins-genericClosure-uncomparable-keys.nix9
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-fail-builtins-genericClosure-uncomparable-keys2.nix12
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix25
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-cycle-display-cpp-nix-2.13.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-cycle-display-cpp-nix-2.13.nix34
-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/notyetpassing/eval-okay-non-identifier-pointer-inequality.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.nix28
-rw-r--r--tvix/eval/src/tests/tvix_tests/observable-eval-cache1.nix1
l---------tvix/eval/src/tests/tvix_tests/observable-eval-cache2.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/observable-eval-cache3.nix1
-rw-r--r--tvix/eval/src/tests/tvix_tests/readDir/bar0
-rw-r--r--tvix/eval/src/tests/tvix_tests/readDir/foo/.keep0
441 files changed, 2108 insertions, 0 deletions
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-substring-negative-start.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-substring-negative-start.nix
new file mode 100644
index 000000000000..bc7a16ded8f3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-builtins-substring-negative-start.nix
@@ -0,0 +1,3 @@
+# Negative start is illegal, but negative length works, see
+# eval-okay-builtins-substring-negative-length.nix
+builtins.substring (-1) 1 "Wiggly Donkers"
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-division-by-zero-float.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-division-by-zero-float.nix
new file mode 100644
index 000000000000..82dd6873218e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-division-by-zero-float.nix
@@ -0,0 +1 @@
+1.0 / 0.0
diff --git a/tvix/eval/src/tests/tvix_tests/eval-fail-division-by-zero-int.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-division-by-zero-int.nix
new file mode 100644
index 000000000000..72dca4d5e478
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-division-by-zero-int.nix
@@ -0,0 +1 @@
+1 / 0
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-function-formals-typecheck.nix b/tvix/eval/src/tests/tvix_tests/eval-fail-function-formals-typecheck.nix
new file mode 100644
index 000000000000..0108f958bf89
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-fail-function-formals-typecheck.nix
@@ -0,0 +1,2 @@
+# A function with formal set arguments forces its argument set and verifies its type.
+({ ... }@args: 42) [ ]
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..44154ba6a6b2
--- /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 1 1 -1 -1 -1 1 1 -1 -1 -1 1 1 -1 -1 -1 -74711 -74711 -74711 ]
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..dc6ce2781593
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-div.nix
@@ -0,0 +1,34 @@
+[
+  (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)
+
+  # builtins.div should truncate towards 0
+  (builtins.div 3 2)
+  (builtins.div (-3) (-2))
+  (builtins.div (-3) 2)
+  (builtins.div 3 (-2))
+  (-(builtins.div 3 2))
+
+  (builtins.div 4 3)
+  (builtins.div (-4) (-3))
+  (builtins.div (-4) 3)
+  (builtins.div 4 (-3))
+  (-(builtins.div 4 3))
+
+  (builtins.div 5 3)
+  (builtins.div (-5) (-3))
+  (builtins.div (-5) 3)
+  (builtins.div 5 (-3))
+  (-(builtins.div 5 3))
+
+  (builtins.div 2147812578 (-28748))
+  (builtins.div (-2147812578) 28748)
+  (-(builtins.div 2147812578 28748))
+]
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-genericClosure-pointer-equality.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-pointer-equality.exp
new file mode 100644
index 000000000000..87977137a57b
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-pointer-equality.exp
@@ -0,0 +1 @@
+[ { key = [ { foo = <LAMBDA>; } ]; val = null; } ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-pointer-equality.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-pointer-equality.nix
new file mode 100644
index 000000000000..5e662cdaf75e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-genericClosure-pointer-equality.nix
@@ -0,0 +1,15 @@
+let
+  foo = x: x;
+in
+
+# key needs to be a list since it uses comparison, not equality checks:
+# lists are comparable in Nix if all non-comparable items in them are equal (e.g.
+# functions, attribute sets).
+builtins.genericClosure {
+  startSet = [
+    { key = [ { inherit foo; } ]; val = null; }
+  ];
+  operator = { val, ... }: if val != null then [] else [
+    { key = [ { inherit foo; } ]; val = throw "no pointer equality? 🥺👉👈"; }
+  ];
+}
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..9f20496c7aa0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.exp
@@ -0,0 +1 @@
+[ "fabir" "a" "1a1" "ABC" ]
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..24a58996094a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-replaceStrings.nix
@@ -0,0 +1,6 @@
+[
+  (builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar")
+  (builtins.replaceStrings ["o"] ["a"] "a")
+  (builtins.replaceStrings ["" ""] ["1" "2"] "a")
+  (builtins.replaceStrings ["a" "b" "c"] ["A" "B" "C"] "abc")
+]
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-negative-length.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-negative-length.exp
new file mode 100644
index 000000000000..e614d4994041
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-negative-length.exp
@@ -0,0 +1 @@
+[ "SIP dial" "Lounge" " Lounge" ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-negative-length.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-negative-length.nix
new file mode 100644
index 000000000000..062e2c0581d7
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-substring-negative-length.nix
@@ -0,0 +1,5 @@
+[
+  (builtins.substring 0 (-1) "SIP dial")
+  (builtins.substring 13 (-1) "Nichtraucher Lounge")
+  (builtins.substring 12 (-2) "Nichtraucher Lounge")
+]
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-escape-string-correct-char-boundaries.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-escape-string-correct-char-boundaries.exp
new file mode 100644
index 000000000000..d889063f9ab1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-escape-string-correct-char-boundaries.exp
@@ -0,0 +1 @@
+"💭(\":thonking:\")"
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-escape-string-correct-char-boundaries.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-escape-string-correct-char-boundaries.nix
new file mode 100644
index 000000000000..49f4b6273106
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-escape-string-correct-char-boundaries.nix
@@ -0,0 +1,6 @@
+# Regression test for a bug where tvix would crash in nix_escape_string
+# because it counted the string position by unicode code point count,
+# but then used it as a byte index for slicing. Consequently, it would
+# try slicing 💭 in half, thinking the first element to be escaped was
+# at byte index 2 (i.e. the quote).
+"💭(\":thonking:\")"
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-formals-miscompilation-b-261-regression.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-formals-miscompilation-b-261-regression.exp
new file mode 100644
index 000000000000..721a052bcc67
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-formals-miscompilation-b-261-regression.exp
@@ -0,0 +1 @@
+[ true null ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-formals-miscompilation-b-261-regression.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-formals-miscompilation-b-261-regression.nix
new file mode 100644
index 000000000000..43bef2938df5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-formals-miscompilation-b-261-regression.nix
@@ -0,0 +1,20 @@
+# This is a regression test for https://b.tvl.fyi/261.
+#
+# The bug occurred when Tvix would unconditionally finalise the stack slot of
+# `finalise` (as its default expression needs a finaliser): Finalising an
+# manually provided, already forced thunk would cause the VM to crash.
+let
+  thunk = x: x;
+  bomb = thunk true;
+  f =
+    { finalise ? later == null
+    , later ? null
+    }:
+    [ finalise later ];
+in
+
+# Note that the crash did not occur if the offending expression was the rhs
+# argument to `builtins.seq`, hence we need to put the assert in between.
+assert builtins.seq bomb true;
+
+f { finalise = bomb; }
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..9800c675fc91
--- /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" = false; "attr.path" = false; "else" = false; false = true; foldl' = true; "if" = false; "in" = false; "inherit" = false; "let" = false; normal = true; normal2 = true; null = true; or = true; "rec" = false; "then" = false; throw = true; true = true; "with" = false; 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..58af3d6d16ab
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-identifier-formatting.nix
@@ -0,0 +1,42 @@
+# Note: the attribute values in this set aren't just dummies!  They
+# are booleans which indicate whether or not the corresponding
+# attrname is valid without quotification.
+{
+  __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" = false;
+  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;
+
+  "if" = false;
+  "then" = false;
+  "else" = false;
+  "with" = false;
+  "let" = false;
+  "in" = false;
+  "rec" = false;
+  "inherit" = false;
+}
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-import-display.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-import-display.exp
new file mode 100644
index 000000000000..15d838950e7a
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-import-display.exp
@@ -0,0 +1 @@
+<PRIMOP>
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-import-display.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-import-display.nix
new file mode 100644
index 000000000000..411f3cd6ef63
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-import-display.nix
@@ -0,0 +1,2 @@
+# In C++ Nix 2.3 this used to be <PRIMOP-APP>
+import
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-observable-eval-cache.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-observable-eval-cache.exp
new file mode 100644
index 000000000000..aaa53b602586
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-observable-eval-cache.exp
@@ -0,0 +1 @@
+[ true true false false true ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-observable-eval-cache.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-observable-eval-cache.nix
new file mode 100644
index 000000000000..24003d0637ae
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-observable-eval-cache.nix
@@ -0,0 +1,7 @@
+[
+  (import ./observable-eval-cache1.nix == import ./observable-eval-cache1.nix)
+  (import ./observable-eval-cache1.nix == import ./observable-eval-cache2.nix)
+  (import ./observable-eval-cache1.nix == import ./observable-eval-cache3.nix)
+  (import ./observable-eval-cache2.nix == import ./observable-eval-cache3.nix)
+  (import ./observable-eval-cache3.nix == import ./observable-eval-cache3.nix)
+]
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-thunk-twice.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval-thunk-twice.exp
new file mode 100644
index 000000000000..b5ba0757c197
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval-thunk-twice.exp
@@ -0,0 +1 @@
+[ { success = false; value = false; } { success = false; value = false; } ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval-thunk-twice.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval-thunk-twice.nix
new file mode 100644
index 000000000000..1749643f82e6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-tryeval-thunk-twice.nix
@@ -0,0 +1 @@
+let x = throw "lol"; in builtins.map (f: f x) [ builtins.tryEval builtins.tryEval ]
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-display.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-value-display.exp
new file mode 100644
index 000000000000..c7e3fc6503a5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-value-display.exp
@@ -0,0 +1 @@
+[ null true false 42 42 "foo\t\nbar" /home/arthur [ 1 2 3 ] <LAMBDA> <PRIMOP> <PRIMOP-APP> { hello = "world"; } ]
diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-value-display.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-value-display.nix
new file mode 100644
index 000000000000..d34ed1697e77
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/eval-okay-value-display.nix
@@ -0,0 +1,16 @@
+# Sanity check of how values are rendered by tvix vs. nix-instantiate(1).
+# Ensures that we can use this test suite to compare against C++ Nix.
+[
+  null
+  true
+  false
+  42
+  42.0
+  "foo\t\nbar"
+  /home/arthur
+  [ 1 2 3 ]
+  (x: x)
+  builtins.add
+  (builtins.substring 0 1)
+  { hello = "world"; }
+]
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-quoted-attrname-assert.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-assert.nix
new file mode 100644
index 000000000000..575b1af5883d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-assert.nix
@@ -0,0 +1 @@
+{ "assert" = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-else.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-else.nix
new file mode 100644
index 000000000000..7601f14b32d1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-else.nix
@@ -0,0 +1 @@
+{ "else" = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-if.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-if.nix
new file mode 100644
index 000000000000..1c391fc9a355
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-if.nix
@@ -0,0 +1 @@
+{ "if" = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-in.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-in.nix
new file mode 100644
index 000000000000..b4f238651dc6
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-in.nix
@@ -0,0 +1 @@
+{ "in" = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-inherit.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-inherit.nix
new file mode 100644
index 000000000000..e62ed32b0435
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-inherit.nix
@@ -0,0 +1 @@
+{ "inherit" = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-let.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-let.nix
new file mode 100644
index 000000000000..196ec7cc887f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-let.nix
@@ -0,0 +1 @@
+{ "let" = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-rec.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-rec.nix
new file mode 100644
index 000000000000..d2c4f93a2ae1
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-rec.nix
@@ -0,0 +1 @@
+{ "rec" = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-then.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-then.nix
new file mode 100644
index 000000000000..f2af8d69701e
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-then.nix
@@ -0,0 +1 @@
+{ "then" = true; }
diff --git a/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-with.nix b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-with.nix
new file mode 100644
index 000000000000..cbcfa970c289
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/identity-quoted-attrname-with.nix
@@ -0,0 +1 @@
+{ "with" = true; }
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-fail-builtins-genericClosure-uncomparable-keys.nix b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-fail-builtins-genericClosure-uncomparable-keys.nix
new file mode 100644
index 000000000000..d4e93e1f28c0
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-fail-builtins-genericClosure-uncomparable-keys.nix
@@ -0,0 +1,9 @@
+# Attribute sets can't be compared, only checked for equality
+builtins.genericClosure {
+  startSet = [
+    { key = { foo = 21; }; }
+  ];
+  operator = _: [
+    { key = { bar = 21; }; }
+  ];
+}
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-fail-builtins-genericClosure-uncomparable-keys2.nix b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-fail-builtins-genericClosure-uncomparable-keys2.nix
new file mode 100644
index 000000000000..ca2825524546
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-fail-builtins-genericClosure-uncomparable-keys2.nix
@@ -0,0 +1,12 @@
+let
+  id = x: x;
+in
+
+builtins.genericClosure {
+  startSet = [ { key = id; first = true; } ];
+  operator =
+    { first, ... }:
+    if first then [
+      { key = id; first = false; }
+    ] else [];
+}
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp
new file mode 100644
index 000000000000..097eb2033aa5
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp
@@ -0,0 +1 @@
+[ true true true true true true true true true true ]
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix
new file mode 100644
index 000000000000..aa2a0a1e198f
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix
@@ -0,0 +1,25 @@
+let
+  alias = builtins;
+in
+
+[
+  (builtins == builtins)
+  (alias == builtins)
+  (builtins == builtins.builtins)
+  (builtins.builtins == builtins.builtins)
+  (builtins.builtins == builtins.builtins.builtins)
+  (alias == alias)
+  (alias == builtins.builtins)
+  ([ builtins ] == [ builtins ])
+
+  # Surprisingly the following expressions don't work. They are
+  # here for documentation purposes and covered only
+  # by eval-okay-select-pointer-inequality.nix. Reasoning is that
+  # we may not want / be able to replicate this behavior at all.
+  #   ([ builtins.add ] == [ builtins.add ])
+  #   ({ inherit (builtins) import; } == { inherit (builtins) import; })
+
+  # These expressions work as expected, however:
+  (let x = { inherit (builtins) add; }; in x == x)
+  (let inherit (builtins) add; in [ add ] == [ add ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-cycle-display-cpp-nix-2.13.exp b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-cycle-display-cpp-nix-2.13.exp
new file mode 100644
index 000000000000..9c44023f02dd
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-cycle-display-cpp-nix-2.13.exp
@@ -0,0 +1 @@
+[ { car = 42; cdr = «repeated»; } [ «repeated» «repeated» «repeated» ] { val = 42; wal = «repeated»; xal = «repeated»; } { tail1 = «repeated»; tail2 = «repeated»; val = 42; } { tail1 = «repeated»; tail2 = «repeated»; val = 21; } ]
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-cycle-display-cpp-nix-2.13.nix b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-cycle-display-cpp-nix-2.13.nix
new file mode 100644
index 000000000000..bd3b1429cef3
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-cycle-display-cpp-nix-2.13.nix
@@ -0,0 +1,34 @@
+let
+  linkedList = {
+    car = 42;
+    cdr = linkedList;
+  };
+
+  list = [
+    linkedList
+    linkedList
+    linkedList
+  ];
+
+  set = {
+    val = 42;
+    wal = set;
+    xal = set;
+  };
+
+  multiTail = {
+   val = 42;
+   tail1 = multiTail;
+   tail2 = multiTail;
+  };
+in
+
+[
+  linkedList
+  list
+  set
+
+  # In C++ Nix 2.3 these would be displayed differently
+  multiTail
+  (let multiTail = { val = 21; tail1 = multiTail; tail2 = multiTail; }; in multiTail)
+]
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/notyetpassing/eval-okay-non-identifier-pointer-inequality.exp b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.exp
new file mode 100644
index 000000000000..69fd1d084749
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.exp
@@ -0,0 +1 @@
+[ false false false false false true false false ]
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.nix b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.nix
new file mode 100644
index 000000000000..821aa47a0d2c
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.nix
@@ -0,0 +1,28 @@
+# C++ Nix frequently creates copies of Value structs when evaluating
+# a variety of expressions. As a result, pointer equality doesn't
+# work for many (all?) expressions that go beyond simple identifier
+# access from the scope: Even if the inner representation of the
+# value still has the same memory location, C++ Nix has created
+# a copy of the struct that holds the pointer to this memory.
+# Since pointer equality is established via the location of
+# the latter, not the former, the values are no longer equal
+# by pointer.
+let
+  foo = { bar = x: x; };
+
+  id = x: x;
+in
+
+[
+  ({ inherit (foo) bar; } == { inherit (foo) bar; })
+  ([ foo.bar ] == [ foo.bar ])
+
+  ([ builtins.add ] == [ builtins.add ])
+  ({ inherit (builtins) import; } == { inherit (builtins) import; })
+
+  ([ (id id) ] == [ (id id) ])
+  ([ id ] == [ id ])
+
+  (with foo; [ bar ] == [ bar ])
+  (with builtins; [ add ] == [ add ])
+]
diff --git a/tvix/eval/src/tests/tvix_tests/observable-eval-cache1.nix b/tvix/eval/src/tests/tvix_tests/observable-eval-cache1.nix
new file mode 100644
index 000000000000..b5f3f59a792d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/observable-eval-cache1.nix
@@ -0,0 +1 @@
+let id = x: x; in { inherit id; }
diff --git a/tvix/eval/src/tests/tvix_tests/observable-eval-cache2.nix b/tvix/eval/src/tests/tvix_tests/observable-eval-cache2.nix
new file mode 120000
index 000000000000..7f69c0eb47eb
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/observable-eval-cache2.nix
@@ -0,0 +1 @@
+observable-eval-cache1.nix
\ No newline at end of file
diff --git a/tvix/eval/src/tests/tvix_tests/observable-eval-cache3.nix b/tvix/eval/src/tests/tvix_tests/observable-eval-cache3.nix
new file mode 100644
index 000000000000..b5f3f59a792d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/observable-eval-cache3.nix
@@ -0,0 +1 @@
+let id = x: x; in { inherit id; }
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