//! pattern 17: look โ deterministic external lookup
//! step 1: evaluate ns_formula to get namespace
//! step 2: evaluate key_formula to get key
//! step 3: call LookProvider to read BBG state
//! step 4: return value as atom, or error if unavailable
//!
//! unlike call (pattern 16), look is deterministic โ the same namespace
//! and key always produce the same result. no prover witness needed.
use crate::noun::{Order, NounId};
use crate::reduce::{Outcome, ErrorKind, cell_pair, evaluate_field, make_field};
use crate::call::CallProvider;
pub fn look<const N: usize>(
order: &mut Order<N>, object: NounId, body: NounId, budget: u64, hints: &dyn CallProvider<N>,
) -> Outcome {
let (ns_formula, key_formula) = match cell_pair(order, body) {
Some(p) => p,
None => return Outcome::Error(ErrorKind::Malformed),
};
let (ns, budget) = match evaluate_field(order, object, ns_formula, budget, hints) {
Ok(v) => v, Err(o) => return o,
};
let (key, budget) = match evaluate_field(order, object, key_formula, budget, hints) {
Ok(v) => v, Err(o) => return o,
};
match hints.look(ns, key) {
Some(value) => make_field(order, value, budget),
None => Outcome::Error(ErrorKind::Unavailable),
}
}
#[cfg(test)]
mod tests {
use crate::reduce::reduce;
use crate::call::NullCalls;
use crate::noun::{Order, Tag};
use crate::reduce::{Outcome, ErrorKind};
use nebu::Goldilocks;
fn g(v: u64) -> Goldilocks { Goldilocks::new(v) }
/// look with NullCalls returns Unavailable โ no BBG state attached
#[test]
fn look_null_provider_returns_unavailable() {
let mut ar = Order::<1024>::new();
// object = atom 0 (dummy)
let obj = ar.atom(g(0), Tag::Field).unwrap();
// body = [ns_formula key_formula] where both are quote-literals
// ns_formula = [1 0] (quote 0 โ namespace 0)
let one = ar.atom(g(1), Tag::Field).unwrap();
let zero = ar.atom(g(0), Tag::Field).unwrap();
let ns_formula = ar.cell(one, zero).unwrap();
// key_formula = [1 42] (quote 42 โ key 42)
let forty_two = ar.atom(g(42), Tag::Field).unwrap();
let key_formula = ar.cell(one, forty_two).unwrap();
// body = [ns_formula key_formula]
let body = ar.cell(ns_formula, key_formula).unwrap();
// formula = [17 body]
let tag = ar.atom(g(17), Tag::Field).unwrap();
let formula = ar.cell(tag, body).unwrap();
match reduce(&mut ar, obj, formula, 1000, &NullCalls) {
Outcome::Error(ErrorKind::Unavailable) => {}
other => panic!("expected Unavailable, got {:?}", other),
}
}
/// look with a provider that returns a value succeeds
#[test]
fn look_with_value_returns_atom() {
use crate::call::{CallProvider, LookProvider};
use crate::noun::{Order, NounId};
struct TestLooks;
impl LookProvider for TestLooks {
fn look(&self, _ns: Goldilocks, _key: Goldilocks) -> Option<Goldilocks> {
Some(Goldilocks::new(99))
}
}
impl<const N: usize> CallProvider<N> for TestLooks {
fn provide(&self, _order: &mut Order<N>, _tag: Goldilocks, _object: NounId) -> Option<NounId> {
None
}
}
let mut ar = Order::<1024>::new();
let obj = ar.atom(g(0), Tag::Field).unwrap();
let one = ar.atom(g(1), Tag::Field).unwrap();
let zero = ar.atom(g(0), Tag::Field).unwrap();
let ns_formula = ar.cell(one, zero).unwrap();
let forty_two = ar.atom(g(42), Tag::Field).unwrap();
let key_formula = ar.cell(one, forty_two).unwrap();
let body = ar.cell(ns_formula, key_formula).unwrap();
let tag = ar.atom(g(17), Tag::Field).unwrap();
let formula = ar.cell(tag, body).unwrap();
match reduce(&mut ar, obj, formula, 1000, &TestLooks) {
Outcome::Ok(result, _budget) => {
let (v, _) = ar.atom_value(result).unwrap();
assert_eq!(v, Goldilocks::new(99));
}
other => panic!("expected Ok with value 99, got {:?}", other),
}
}
}
nox/rs/patterns/look.rs
ฯ 0.0%
//! pattern 17: look โ deterministic external lookup
//! step 1: evaluate ns_formula to get namespace
//! step 2: evaluate key_formula to get key
//! step 3: call LookProvider to read BBG state
//! step 4: return value as atom, or error if unavailable
//!
//! unlike call (pattern 16), look is deterministic โ the same namespace
//! and key always produce the same result. no prover witness needed.
use crate;
use crate;
use crateCallProvider;