use nebu::Goldilocks;
use crate::data::{Reduction, Order};
use crate::reduce::{Outcome, ErrorKind, pair_children};
use crate::call::CallProvider;
use crate::trace::{Tracer, TraceRow};
const DECIDER_COST: u64 = 825;
const DECIDER_CALL_TAG: u64 = 0xDEC1_DEC1;
pub fn decider_jet<const N: usize>(
reduction: &mut Reduction<N>, object: Order, _body: Order, budget: u64,
hints: &dyn CallProvider<N>, _tracer: &mut dyn Tracer, _depth: u64,
row: &mut TraceRow,
) -> Outcome {
let (proof_id, instance_id) = match pair_children(reduction, object) {
Some(p) => p,
None => return Outcome::Error(ErrorKind::Malformed),
};
if budget < DECIDER_COST {
return Outcome::Halt(budget);
}
let remaining = budget - DECIDER_COST;
row.r[4] = proof_id as u64;
row.r[5] = instance_id as u64;
let tag = Goldilocks::new(DECIDER_CALL_TAG);
let result = match hints.provide(reduction, tag, object) {
Some(r) => r,
None => match reduction.atom(Goldilocks::ZERO) {
Some(r) => r,
None => return Outcome::Error(ErrorKind::Unavailable),
},
};
Outcome::Ok(result, remaining)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::call::NullCalls;
use crate::trace::{NoTrace, TraceRow};
use crate::data::{Reduction};
fn g(v: u64) -> Goldilocks { Goldilocks::new(v) }
#[test]
fn decider_with_null_calls_returns_zero() {
let mut ar = Reduction::<256>::new();
let proof = ar.atom(g(1)).unwrap();
let instance = ar.atom(g(2)).unwrap();
let obj = ar.pair(proof, instance).unwrap();
let body = ar.atom(g(0)).unwrap();
let mut row = TraceRow::default();
match decider_jet(&mut ar, obj, body, 10_000, &NullCalls, &mut NoTrace, 0, &mut row) {
Outcome::Ok(r, rem) => {
assert_eq!(ar.atom_value(r).unwrap(), g(0));
assert_eq!(rem, 10_000 - 825);
}
o => panic!("{:?}", o),
}
}
#[test]
fn decider_exhausted_budget_halts() {
let mut ar = Reduction::<256>::new();
let proof = ar.atom(g(1)).unwrap();
let instance = ar.atom(g(2)).unwrap();
let obj = ar.pair(proof, instance).unwrap();
let body = ar.atom(g(0)).unwrap();
let mut row = TraceRow::default();
match decider_jet(&mut ar, obj, body, 100, &NullCalls, &mut NoTrace, 0, &mut row) {
Outcome::Halt(_) => {}
o => panic!("expected Halt, got {:?}", o),
}
}
}