Status quo: We have `force$Type` and `eval$Type`, both which first produce a value and then do a type check. The type checking logic is not consistently implemented, with lots of code duplication. This change does: - Introduce new `check*` functions which unify the logic (the error handling unfortunately still needs some duplication for now) - Make both `force*` and `eval*` use the `check*` function for the actual type checking - Inline and dismantle the `eval*` functions for being of little use and little used. This makes the `ExprOp*::eval` implementations for binary logic operators more verbose, but IMO that's a good thing: The implementation now needs to be a lot more explicit about the short-circuiting semantics, something which was previously hidden behind the short-circuiting semantics of the C++ language, in a way that could easily be overlooked and lead to confusion, which is something that happened to me twice in a year. - Changes `forceAttrs` and `forceList` to include the context in case `forceValue` fails (compared to only when the type check fails). This was done for code consistency, because I could not find any reason why list and attrs had different semantics here than int, float and bool. So far the visible change is minimal (see the diff on the err.exp), however this needs vetting for potential performance regressions. Change-Id: I33e5c706d46850c9e1126293ee01dab85ba07587
25 lines
722 B
Nix
25 lines
722 B
Nix
with import ./lib.nix;
|
|
|
|
let
|
|
|
|
as = { x.y.z = 123; a.b.c = 456; };
|
|
|
|
bs = { f-o-o.bar = "foo"; };
|
|
|
|
or = x: y: x || y;
|
|
|
|
in
|
|
[ as.x.y.z
|
|
as.foo or "foo"
|
|
as.x.y.bla or as.a.b.c
|
|
as.a.b.c or as.x.y.z
|
|
as.x.y.bla or bs.f-o-o.bar or "xyzzy"
|
|
as.x.y.bla or bs.bar.foo or "xyzzy"
|
|
(123).bla or null.foo or "xyzzy"
|
|
# Backwards compatibility test for `fun or` being handled as intended.
|
|
# n.b. this code contains a type error, because the nul value should be false instead of [].
|
|
# but the code expands to `true || (false || (false || [])))`, so as long as at least one value in the list is true
|
|
# it short-circuits and never runs into the type error
|
|
(fold or [] [true false false])
|
|
]
|