diff options
author | Vincent Ambo <mail@tazj.in> | 2022-08-28T20·50+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2022-09-06T14·58+0000 |
commit | 1f37275cfb42994ed23742b80055a7ab0485247d (patch) | |
tree | a4d29f0729323fd18dc83d0ad1b57286a4633e90 /tvix/eval/src/value/thunk.rs | |
parent | 49296cebe3c1b5644e24f6c3017a75db7c85683d (diff) |
feat(tvix/eval): introduce Value::Thunk variant r/4673
Introduces the representation of runtime thunks, that is lazily evaluated values. Their representation is very similar to closures. Change-Id: I24d1ab7947c070ae72ca6260a7bbe6198bc8c7c5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6343 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
Diffstat (limited to 'tvix/eval/src/value/thunk.rs')
-rw-r--r-- | tvix/eval/src/value/thunk.rs | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/tvix/eval/src/value/thunk.rs b/tvix/eval/src/value/thunk.rs new file mode 100644 index 000000000000..15179388dc86 --- /dev/null +++ b/tvix/eval/src/value/thunk.rs @@ -0,0 +1,55 @@ +//! This module implements the runtime representation of Thunks. +//! +//! Thunks are a special kind of Nix value, similar to a 0-argument +//! closure that yields some value. Thunks are used to implement the +//! lazy evaluation behaviour of Nix: +//! +//! Whenever the compiler determines that an expression should be +//! evaluated lazily, it creates a thunk instead of compiling the +//! expression value directly. At any point in the runtime where the +//! actual value of a thunk is required, it is "forced", meaning that +//! the encompassing computation takes place and the thunk takes on +//! its new value. +//! +//! Thunks have interior mutability to be able to memoise their +//! computation. Once a thunk is evaluated, its internal +//! representation becomes the result of the expression. It is legal +//! for the runtime to replace a thunk object directly with its value +//! object, but when forcing a thunk, the runtime *must* mutate the +//! memoisable slot. + +use std::{cell::RefCell, rc::Rc}; + +use crate::Value; + +use super::Lambda; + +/// Internal representation of the different states of a thunk. +#[derive(Debug)] +enum ThunkRepr { + /// Thunk is suspended and awaiting execution. + Suspended { lambda: Lambda }, + + /// Thunk is closed over some values, suspended and awaiting + /// execution. + ClosedSuspended { + lambda: Lambda, + upvalues: Vec<Value>, + }, + + /// Thunk currently under-evaluation; encountering a blackhole + /// value means that infinite recursion has occured. + Blackhole, + + /// Fully evaluated thunk. + Evaluated(Value), +} + +#[derive(Clone, Debug)] +pub struct Thunk(Rc<RefCell<ThunkRepr>>); + +impl Thunk { + pub fn new(lambda: Lambda) -> Self { + Thunk(Rc::new(RefCell::new(ThunkRepr::Suspended { lambda }))) + } +} |