///|
/// Immutable counters. Attempts include target calls that fail.
pub(all) struct Statistics {
queries : Int32
cache_hits : Int32
resets : Int32
steps : Int32
completed_queries : Int32
cache_nodes : Int32
output_code_units : Int32
} derive(Debug, ToJson)
///|
pub extend Statistics with @debug.Debug::{to_repr}
///|
pub extend Statistics with ToJson::{to_json}
///|
priv struct TraceNode {
children : Map[String, Int32]
output : String?
}
///|
/// Synchronous compatibility facade over the IO-independent query session.
pub struct Experiment {
priv system : System
priv alphabet : Array[String]
priv session : QuerySession
}
///|
pub fn Experiment::new(
system : System,
alphabet : Array[String],
max_queries~ : Int32 = 100000,
max_steps~ : Int32 = 2000000,
max_word_length~ : Int32 = 4096,
max_cache_nodes~ : Int32 = 1000000,
max_output_code_units~ : Int32 = 16777216,
use_cache~ : Bool = true,
recheck_every~ : Int32 = 0,
) -> Experiment raise LensError {
{
system,
alphabet: alphabet.copy(),
session: QuerySession::new(
alphabet,
max_queries~,
max_steps~,
max_word_length~,
max_cache_nodes~,
max_output_code_units~,
use_cache~,
recheck_every~,
),
}
}
///|
pub fn Experiment::statistics(self : Experiment) -> Statistics {
self.session.statistics()
}
///|
pub fn Experiment::alphabet(self : Experiment) -> Array[String] {
self.alphabet.copy()
}
///|
pub fn Experiment::query(
self : Experiment,
requested_word : Array[String],
bypass_cache~ : Bool = false,
) -> Array[String] raise {
match self.session.start(requested_word, bypass_cache~) {
Cached(outputs) => outputs
Execute(request) => {
defer self.session.abort(request.id)
{
errdefer ((self.system.close)() catch { _ => () })
self.session.reset_started(request.id)
(self.system.reset)()
for input in request.inputs {
self.session.step_started(request.id)
self.session.accept_output(request.id, (self.system.step)(input))
}
}
(self.system.close)()
self.session.commit(request.id)
}
}
}
///|
/// Freshly replay a candidate word against both real targets.
pub fn confirm_difference(
left : Experiment,
right : Experiment,
inputs : Array[String],
) -> Difference? raise {
let word = inputs.copy()
let left_outputs = left.query(word, bypass_cache=true)
let right_outputs = right.query(word, bypass_cache=true)
if left_outputs == right_outputs {
None
} else {
Some({ inputs: word, left_outputs, right_outputs, })
}
}