This operator allows for accessing attribute sets (including nested
access) while also providing a default value.
This is one of the more complex operations to compile, as it needs to
keep track of a fairly large number of jumps that all need to be
patched correctly.
To make this easier to understand there's a small diagram included in
the comments.
Change-Id: Ia53bb20d8f779859bfd1692fa3f6d72af74c3a1f
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6167
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
This sentinel value is going to be used for certain nested accesses
into attribute sets.
There is a new instruction similar to `OpAttrsSelect` which leaves the
sentinel on the stack if a key is not found, instead of raising an
error.
Additionally, a new jump instruction makes its jump operation
conditional on finding such a sentinel value.
Change-Id: I2642f0a0bcc85bbe0ead68ea09a7dd794dbedeac
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6166
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
The only uses of the static variant were for `"name"` and `"value"`,
which are both small enough to fit into a SmolStr. The size of
NixString accomodates `String` anyways, so we may as well inline them.
Additionally smol_str is already in the dependency graph because rnix
uses it, and using it for representations of identifiers is sensible.
Change-Id: I9969312256d1657d69128e54c47dc7294a18ce58
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6165
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: grfn <grfn@gws.fyi>
Having these visible more explicitly is useful while debugging.
Change-Id: I86b497883063d32792b635eb4514b7aeae484af4
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6164
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: grfn <grfn@gws.fyi>
Implements the nested presence check operator for attribuet sets by
traversing the chain of lookups through instructions that push/pop
sequentially deeper attribute sets onto the stack.
Note that this commit introduces a bug in case of nested attributes
not being found, which is fixed in a later commit.
Change-Id: Ic8b4c8648736f6cb048e3aa52592e4d075bf0544
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6163
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: grfn <grfn@gws.fyi>
This makes it possible to check things like `{} ? a` with a single
level of nesting.
Change-Id: I567c36fcfd2f9e2f60071acd3ebfe56dea59b26f
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6161
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Reviewed-by: sterni <sternenseemann@systemli.org>
With this change, attribute set access is working as intended.
Change-Id: Ic5dbbd68aa59156106069289e7375a696909f78b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6159
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: grfn <grfn@gws.fyi>
Fairly straightforward, handling the optimised representations
manually and otherwise delegating to BTreeMap.
Note that parsing of raw identifiers is not yet implemented.
Encountering an identifier node usually means that there is locals
access going on, so we need a special case for compiling a node in
such a way that an identifier's literal value ends up on the stack.
Change-Id: I13fbab7ac657b17ef3f4c5859fe737c321890c8a
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6158
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: grfn <grfn@gws.fyi>
This operation is required because both sides of the logical operators
are strictly evaluated by Nix, even if the resulting value is not used
further.
For example, in our implementation of `&&`, if the left-hand side is
`true`, then the result of the expression is simply the right-hand
side value. This value must be asserted to be a boolean for the
semantics of the language to work correctly.
Change-Id: I34f5364f2a444753fa1d8b0a1a2b2d9cdf7c6700
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6157
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Reviewed-by: grfn <grfn@gws.fyi>
Bootstrap some (initially very simple, mostly proof-of-concept)
benchmarking infrastructure using Criterion, using the newly-exposed lib
from tvix-eval.
Change-Id: I4bb93c142ba8d018d7e67e58ac8907a0429398a5
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6156
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Autosubmit: grfn <grfn@gws.fyi>
Add a new `lib.rs` to tvix/eval, which `pub use`s the `interpret`
function, and all types mentioned in its return type, and then uses
*this* instead of direct `mod` statements in the `main.rs` to implement
the entrypoints to the interpreter. This is in preparation for calling
these functions from integrated benchmarking infrastructure using
Criterion, though other things (like integration tests) might want to do
that as well.
Change-Id: I7b585134a96b1c56a2ac64d2036b0e51d321bd27
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6155
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Autosubmit: grfn <grfn@gws.fyi>
Similar to `||`, but inverting the left-hand side.
In other words, `a -> b` is essentially rewritten as `!a || b`.
Change-Id: I8a62da65ff070b389e46048d047a54279060a97b
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6152
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Reviewed-by: sterni <sternenseemann@systemli.org>
This logical operator is implemented in terms of jumping operations
and thus requires slightly different treatment than other binary
operators.
Change-Id: Ib3d768b70dd7e16014c9b47d770aa74eec60ae92
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6150
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Reviewed-by: sterni <sternenseemann@systemli.org>
These expressions use simple jumps to skip the correct expression
conditionally in the bytecode by advancing the instruction pointer.
Note that these expressions are already covered by a test behind the
`nix_tests` feature flag, but adding more is probably sensible.
Change-Id: Ibe0eba95d216321c883d3b6b5816e2ab6fe7eef1
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6148
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Reviewed-by: sterni <sternenseemann@systemli.org>
Wraps the string representation in an additional newtype struct with a
private field in order to hide the representation from other modules.
This is done in order to avoid accidental leakage of the internals
outside of value::string.
In fact, this caught a mistake in the compiler module which was
directly constructing an internal variant.
Change-Id: If4b627d3cff7ab9cd50ca1a3ac73245d4dcf7aef
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6147
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Wraps the attrs representation in an additional newtype struct with a
private field in order to hide the representation from other modules.
This is done in order to avoid accidental leakage of the internals
outside of value::attrs.
Change-Id: I68d1d02514aa0443df4c39801001a3f1f6cc5d5c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6146
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Ensuring that the implementation is not leaking out of the module lets
us keep things open for optimisations (e.g. empty list or pairs
through tuples).
Change-Id: I18fd9b7740f28c55736471e16c6b4095a05dd6d0
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6145
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
This is accomplished by simply delegating to the Rust implementations
of (Partial)Ord and (Partial)Eq, which are implemented for Value and
underlying wrapper types to behave like they do in Nix.
To ease the implementation overhead, a new comparison operator macro
has been added to the VM module.
Incomparable types will raise a new error variant when a comparison is
attempted, containing both supplied types. This mimics the information
carried in the error thrown by C++ Nix.
Change-Id: Ia19634d69119d40722f3ca672387bc3a80096998
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6143
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
This can now fully delegate to PartialEq of Value
Change-Id: Iaa9f4ec9b8830d516d72f83a93ab2df9a6e5697c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6142
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
The underlying implementation does a few tricks based on which pair of
attrset representations is encountered.
Particularly the effect of short-circuiting the empty cases might be
relevant in nixpkgs/NixOS, due to the use of lib.optionalAttrs.
Change-Id: I22b978b1c69af12926489a71087c6a6219c012f3
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6140
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
I assumed that `Ord` is a marker trait like `Eq`, but it actually has
a member. Without this ordering was incoherent.
Change-Id: Id37cbdf333daf748d29b85243046c7e061b1ce29
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6139
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Instead of constructing another runtime value representing the pair on
which to perform arithmetic, implement the same logic in the shape of
a macro.
This is designed to be compatible with operators like `+` that work
both as an arithmetic operator AND as an operator on another pair of
types.
Change-Id: I1c83649ead6117f811f1fb45482d0cadf811125e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6136
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Nix displays a maximum of 5 digits for floating points.
Change-Id: Ifa3c0d96fa0b24e3be8f94dfebc99e602a258355
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6133
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
Once we have full coverage they should be enabled by default.
Change-Id: Iace9e1ae9a9f901a0979ad336434004b8028fe8a
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6129
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
When printing strings as identifiers (in attribute sets), the string
should only be quoted and escaped if it contains escape characters.
Change-Id: If2bcfa1e93dc8f00be4d7a57ec1d82fc679103c3
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6127
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Autosubmit: tazjin <tazjin@tvl.su>
This adds scaffolding code for running the Nix language test suite.
The majority of eval-okay-* tests should eventually be runnable as-is
by Tvix, however the eval-fail-* tests might not as we intend to have
more useful error messages than upstream Nix.
Change-Id: I4f3227f0889c55e4274b804a3072850fb78dd1bd
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6126
Tested-by: BuildkiteCI
Autosubmit: tazjin <tazjin@tvl.su>
Reviewed-by: grfn <grfn@gws.fyi>
This crate makes it easy to generate test cases from files on disk,
which is used for running the Nix test suite against Tvix.
Change-Id: I60ef26484d05e723982679dd42958adf52735916
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6125
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Nix strings displayed to users must be escaped the same way as they
are in C++ Nix. This adds the scaffolding for escapes, but is most
likely not yet complete.
Change-Id: Icfdcb2ac98d292c567ba894a92b6529a53e0cc17
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6124
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Instead of comparing the enum variants (which does not yield useful
behaviour), compare &str representations of the string instead.
Change-Id: I5e94b5f6c91b4561e1bc7c36d586f3d23c243764
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6112
Tested-by: BuildkiteCI
Reviewed-by: eta <tvl@eta.st>
For cases where the strings are statically known (such as the
oft-occuring name/value), this can be a useful optimisation.
It's also much more convenient in tests.
Change-Id: Ie462b684805bd4986ea5e85ca4bff663bc2d3c3c
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6111
Tested-by: BuildkiteCI
Reviewed-by: eta <tvl@eta.st>
These do not yet test nested attribute sets; we need to add some more
inspection primitives first.
Change-Id: Icfc99bf17c73ebefc0d882a84f0ca73ec688a54d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6110
Reviewed-by: eta <tvl@eta.st>
Tested-by: BuildkiteCI
With this change, nested attribute sets can now be created from
literals.
This required some logic for dealing with cases where at a deeper
nesting point a literal attribute set was constructed from an
optimised representation.
For example, this is valid Nix code:
```nix
{
a = {}; # creates optimised empty representation
a.b = 1; # wants to add a `b = 1` to it
b = { name = "foo"; value = "bar"; }; # creates optimised K/V repr
b.foo = 42; # wants to add an additional `foo = 42`
}
```
In these cases, the attribute set must be coerced to a map
representation first which is achieved by the new internal
NixAttr::map_mut helper.
Change-Id: Ia61d3d9d14c4e0f5e207c00f6a2f4daa3265afb2
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6109
Reviewed-by: eta <tvl@eta.st>
Tested-by: BuildkiteCI
The internal optimisations of the set representation were previously
leaking into the VM, which is highly undesirable.
Keeping it encapsulated allows us to do additional optimisations
within value::attrs without being concerned about its use in the VM.
Change-Id: I7e7020bb0983b9d355d3db747b049b2faa60131f
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6108
Reviewed-by: eta <tvl@eta.st>
Tested-by: BuildkiteCI
There are multiple points where an insertion needs to be done into an
attribute set, but copying the key or checking for presence before
insertion should be avoided
As that is a little bit noisy, it's been factored out into a helper
function in this commit.
Change-Id: Ibcb054ebeb25a1236c06c812f47c8e74180d4fc9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6107
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
This can construct non-overlapping nested attribute sets (i.e. `{ a.b
= 1; b.c = 2; }`, but not `{ a.b = 1; a.c = 2; }`).
In order to do the latter, it's necessary to gain the ability to
manipulate the in-progress attribute set construction. There's
multiple different options for this ...
Change-Id: If1a762a720b175e8eb4216cbf96a7434d22640fb
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6106
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
There are some notions of equality (due to e.g. different backing
variants for types, or Nix particularities) that don't work correctly
when deriving PartialEq.
Change-Id: Ide83ae67d051cc0b3ca89cefb283f17d0207acce
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6105
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>