diff --git a/rust/ares/src/interpreter.rs b/rust/ares/src/interpreter.rs index bf406af3..2dbbbe5c 100644 --- a/rust/ares/src/interpreter.rs +++ b/rust/ares/src/interpreter.rs @@ -267,6 +267,7 @@ pub struct Context { pub warm: Warm, pub hot: Hot, pub cache: Hamt, + pub keep: Hamt, // persistent cache pub scry_stack: Noun, pub trace_info: Option, } @@ -301,6 +302,7 @@ impl Context { let mut ret = f(self); ret.preserve(&mut self.stack); self.cache.preserve(&mut self.stack); + self.keep.preserve(&mut self.stack); self.cold.preserve(&mut self.stack); self.warm.preserve(&mut self.stack); self.stack.frame_pop(); @@ -403,6 +405,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res debug_assertions(stack, res); stack.preserve(&mut context.cache); + stack.preserve(&mut context.keep); stack.preserve(&mut context.cold); stack.preserve(&mut context.warm); stack.preserve(&mut res); @@ -422,6 +425,7 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res debug_assertions(stack, res); stack.preserve(&mut context.cache); + stack.preserve(&mut context.keep); stack.preserve(&mut context.cold); stack.preserve(&mut context.warm); stack.preserve(&mut res); @@ -743,6 +747,10 @@ pub fn interpret(context: &mut Context, mut subject: Noun, formula: Noun) -> Res } NockWork::Work11D(mut dint) => match dint.todo { Todo11D::ComputeHint => { + // XX support actual computation of %memo clues instead of just + // assuming the clue will be a constant (like [1 0] or /my/cache/path) + // i.e., we should support ~> %memo.[(turn /foo/bar/baz |=(a=@ (add a %offset)))] ... + // NB: vere doesn't support non-constant %memo clues yet either if let Some(ret) = hint::match_pre_hint(context, subject, dint.tag, dint.hint, dint.body) { @@ -1324,6 +1332,34 @@ mod hint { } } + /// Extracts a constant from a formula, skipping over + /// safe/static hints, doing no computation. + pub fn skip(formula: Noun) -> Option { + let mut fol = formula; + loop { + if fol.is_cell() { + let fol_cell = fol.as_cell().unwrap(); + let op = fol_cell.head().as_direct().unwrap().data(); + match op { + 1 => return Some(fol_cell.tail()), + 11 => { + let arg = fol_cell.tail().as_cell().unwrap(); + let hod = arg.head(); + if hod.is_cell() { + if skip(hod.as_cell().unwrap().tail()).is_none() { + return None; + } + } + fol = arg.tail(); + } + _ => return None, + } + } else { + break None; + } + } + } + /** Match dynamic hints before the hint formula is evaluated */ pub fn match_pre_hint( context: &mut Context, @@ -1406,7 +1442,17 @@ mod hint { tas!(b"memo") => { let stack = &mut context.stack; let mut key = Cell::new(stack, subject, body).as_noun(); - context.cache.lookup(stack, &mut key).map(Ok) + // XX this assumes the clue is a constant; i.e., it is *not* computed + if let Some(con) = skip(hint) { + if con.is_cell() { + eprintln!("serf: looking in keep\r"); + context.keep.lookup(stack, &mut key).map(Ok) + } else { + context.cache.lookup(stack, &mut key).map(Ok) + } + } else { + None + } } _ => None, } @@ -1509,12 +1555,24 @@ mod hint { let cold = &mut context.cold; let hot = &context.hot; let cache = &mut context.cache; + let keep = &mut context.keep; // XX: handle IndirectAtom tags match tag.direct()?.data() { tas!(b"memo") => { let mut key = Cell::new(stack, subject, body).as_noun(); - context.cache = cache.insert(stack, &mut key, res); + if let Some(clue) = hint { + if clue.is_cell() { + // if unsafe { context.scry_stack.raw_equals(D(0)) } { + eprintln!("serf: memoizing in keep\r"); + context.keep = keep.insert(stack, &mut key, res); + // } + // XX add a printf that says "userspace can't insert into + // persistent cache" + } else { + context.cache = cache.insert(stack, &mut key, res); + } + } } tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => { mean_pop(stack); diff --git a/rust/ares/src/jets.rs b/rust/ares/src/jets.rs index 5bff6b13..8dbcac82 100644 --- a/rust/ares/src/jets.rs +++ b/rust/ares/src/jets.rs @@ -319,6 +319,7 @@ pub mod util { let warm = Warm::new(); let hot = Hot::init(&mut stack, URBIT_HOT_STATE); let cache = Hamt::::new(); + let keep = Hamt::::new(); Context { stack, @@ -327,6 +328,7 @@ pub mod util { warm, hot, cache, + keep, scry_stack: D(0), trace_info: None, } diff --git a/rust/ares/src/jets/nock.rs b/rust/ares/src/jets/nock.rs index 2dfd2d0b..667d87d9 100644 --- a/rust/ares/src/jets/nock.rs +++ b/rust/ares/src/jets/nock.rs @@ -150,6 +150,7 @@ pub mod util { let scry_snapshot = context.scry_stack; context.cache = Hamt::::new(); + context.keep = Hamt::::new(); context.scry_stack = T(&mut context.stack, &[scry, context.scry_stack]); match interpret(context, subject, formula) { diff --git a/rust/ares/src/serf.rs b/rust/ares/src/serf.rs index 0ba34eaa..478044bf 100644 --- a/rust/ares/src/serf.rs +++ b/rust/ares/src/serf.rs @@ -61,6 +61,7 @@ impl Context { warm: Warm::new(), hot, cache: Hamt::::new(), + keep: Hamt::::new(), scry_stack: D(0), trace_info, };