///|
/// Compare only histories formed from the old input alphabet. Additional new
/// operations are outside this contract. Exact for supplied complete models;
/// this does not certify actual implementations or histories using new inputs.
pub fn backward_compatibility(
old : Machine,
next : Machine,
max_pairs~ : Int32 = 100000,
) -> Json raise {
let missing = old.alphabet().filter(x => !next.alphabet().contains(x))
let added = next.alphabet().filter(x => !old.alphabet().contains(x))
if !missing.is_empty() {
return Json::object({
"format": Json("moonstatelens.backward-compatibility"),
"version": Json(1),
"status": Json("missing-old-operations"),
"missing": Json(missing),
"added": Json(added),
"scope": Json("supplied models; old input histories only"),
})
}
let columns = old.alphabet().map(x => next.input_index(x))
let projection = Machine::new(
old.alphabet(),
next.table().map(row => columns.map(i => row[i])),
initial=next.initial_state(),
)
let difference = distinguish(old, projection, max_pairs~)
Json::object({
"format": Json("moonstatelens.backward-compatibility"),
"version": Json(1),
"status": Json(
if difference is None {
"compatible-on-old-inputs"
} else {
"changed-old-behavior"
},
),
"added": Json(added),
"missing": Json(missing),
"difference": difference.map(d => Json(d)).unwrap_or(Json::null()),
"scope": Json(
"exact supplied models; histories using new operations and actual implementation behavior are not certified",
),
})
}