Skip to main content

nickel_lang_core/eval/cache/
mod.rs

1/// The Nickel generic evaluation cache. This module abstracts away the details for managing
2/// suspended computations and their memoization strategies.
3///
4/// Terminology:
5/// An *element* of the cache is what is stored inside of it.
6/// An *index* into the cache points to a given element.
7use super::{Closure, value::NickelValue};
8use crate::{
9    identifier::Ident,
10    term::{BindingType, record::FieldDeps},
11};
12
13pub mod lazy;
14// pub mod incremental;
15
16/// An index to a specific item stored in the cache
17pub type CacheIndex = lazy::Thunk;
18// pub type CacheIndex = usize;
19
20/// The current Cache implementation
21pub type CacheImpl = lazy::CBNCache;
22// pub type CacheImpl = incremental::IncCache;
23
24/// A black-holed node was accessed, which would lead to infinite recursion.
25#[derive(Clone, Copy, Debug, Eq, PartialEq)]
26pub struct BlackholedError;
27
28pub trait Cache: Clone {
29    /// Temporary: as of now we only need this for [lazy::CBNCache].
30    type UpdateIndex;
31
32    /// Gets the [Closure] from the element at index `idx`.
33    fn get(&self, idx: CacheIndex) -> Closure;
34
35    /// Checks whether the element at index `idx` is blackholed and returns a
36    /// [BlackholedError] if it is. Otherwise, returns `Some(idx)` if the element
37    /// needs to be updated, returns `None` if not.
38    /// Should use [Cache::make_update_index].
39    fn get_update_index(
40        &mut self,
41        idx: &mut CacheIndex,
42    ) -> Result<Option<Self::UpdateIndex>, BlackholedError>;
43
44    /// Adds an element into the [Cache] and returns its index.
45    fn add(&mut self, clos: Closure, bty: BindingType) -> CacheIndex;
46
47    /// Applies `f` to the [Closure] stored inside the element at index `idx`.
48    fn patch<F: Fn(&mut Closure)>(&mut self, idx: CacheIndex, f: F);
49
50    /// Clones the [Closure] from the element at index `idx` and applies `f` to it.
51    fn get_then<T, F: FnOnce(&Closure) -> T>(&self, idx: CacheIndex, f: F) -> T;
52
53    /// Updates the [Closure] from the element at index `idx` with `clos`.
54    fn update(&mut self, clos: Closure, idx: Self::UpdateIndex);
55
56    /// Initializes a new [Cache].
57    fn new() -> Self;
58
59    /// Resets the state of the element at index `idx` to `Suspended`
60    fn reset_index_state(&mut self, idx: &mut Self::UpdateIndex);
61
62    fn map_at_index<F: FnMut(&mut Self, &Closure) -> Closure>(
63        &mut self,
64        idx: &CacheIndex,
65        f: F,
66    ) -> CacheIndex;
67
68    /// Initializes the cached value of the element at index `idx` with the given `rec_env`.
69    fn build_cached(&mut self, idx: &mut CacheIndex, rec_env: &[(Ident, CacheIndex)]);
70
71    /// Revert the element at index `idx`, abstract over its dependencies to get back a function,
72    /// and apply the function to the given variables. The function part is allocated in a new
73    /// cache entry, stored as a generated variable, with the same environment as the original
74    /// expression.
75    fn saturate<I: DoubleEndedIterator<Item = Ident> + Clone>(
76        &mut self,
77        idx: CacheIndex,
78        fields: I,
79    ) -> NickelValue;
80
81    /// Reverts the element stored at index `idx` to its original value.
82    fn revert(&mut self, idx: &CacheIndex) -> CacheIndex;
83
84    /// Returns the dependencies of the element stored at index `idx`, if it has any.
85    fn deps(&self, idx: &CacheIndex) -> Option<FieldDeps>;
86
87    /// Checks whether the element at index `idx` is blackholed and returns a
88    /// [BlackholedError] if it is. Otherwise, returns `idx`.
89    fn make_update_index(
90        &mut self,
91        idx: &mut CacheIndex,
92    ) -> Result<Self::UpdateIndex, BlackholedError>;
93}