diff options
author | Griffin Smith <root@gws.fyi> | 2022-09-18T20·53-0400 |
---|---|---|
committer | grfn <grfn@gws.fyi> | 2022-09-18T22·33+0000 |
commit | 69cbcc1eda13400d24dcb580713453bcba00fcc3 (patch) | |
tree | 6c92913c72e76b25b93d4b8aba31e729712558cf /tvix/eval/src/value/mod.rs | |
parent | bcbe1603c8d50b69705fb737961b6a4827a50591 (diff) |
refactor(tvix/eval): Simplify forcing in builtins r/4914
Refactor the `force!` macro to a method on `Value` which returns a smart-pointer-esque type, which simplifies the callsite and eliminates rightward drift, especially for high-arity builtins. Change-Id: I97a7837580accfb4bbd03b24f2acdbd38645efa5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6656 Autosubmit: grfn <grfn@gws.fyi> Reviewed-by: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/eval/src/value/mod.rs')
-rw-r--r-- | tvix/eval/src/value/mod.rs | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index b628d7c4ee8f..057d584fc6ff 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -1,5 +1,7 @@ //! This module implements the backing representation of runtime //! values in the Nix language. +use std::cell::Ref; +use std::ops::Deref; use std::rc::Rc; use std::{fmt::Display, path::PathBuf}; @@ -95,6 +97,26 @@ pub enum CoercionKind { Strong, } +/// A reference to a [`Value`] returned by a call to [`Value::force`], whether the value was +/// originally a thunk or not. +/// +/// Implements [`Deref`] to [`Value`], so can generally be used as a [`Value`] +pub(crate) enum ForceResult<'a> { + ForcedThunk(Ref<'a, Value>), + Immediate(&'a Value), +} + +impl<'a> Deref for ForceResult<'a> { + type Target = Value; + + fn deref(&self) -> &Self::Target { + match self { + ForceResult::ForcedThunk(r) => r, + ForceResult::Immediate(v) => v, + } + } +} + impl Value { /// Coerce a `Value` to a string. See `CoercionKind` for a rundown of what /// input types are accepted under what circumstances. @@ -292,6 +314,17 @@ impl Value { _ => Ok(false), } } + + /// Ensure `self` is forced if it is a thunk, and return a reference to the resulting value. + pub(crate) fn force(&self, vm: &mut VM) -> Result<ForceResult, ErrorKind> { + match self { + Self::Thunk(thunk) => { + thunk.force(vm)?; + Ok(ForceResult::ForcedThunk(thunk.value())) + } + _ => Ok(ForceResult::Immediate(self)), + } + } } impl Display for Value { |