use super::types::{
EvaluationPair, InterpretedExecutionRefusal, InterpretedMutationEvidence, InterpretedTrust,
InterpreterAvailability, MUTERPRATER_NAMESPACE, MissingTrustEvidence, MutationWitness,
NO_MUTATION_PAIRING, NoMutationObservationRefusal, NoMutationParityQualification,
NoMutationParityReading, NoMutationParityStanding, NoMutationReports, NoMutationResults,
PARITY_DECLARATION_SUBSTRATE, PARITY_RENDERING_SUBSTRATE, ParityQualificationRefusal,
ParityRefusal, RejectedNoMutationParity,
};
use crate::descriptor::NamespacedName;
use crate::muterprater::{
ActivationEvidence, ActiveSelection, AdmittedAlternative, CompiledProjectionPressure,
CompiledSuitePressure, DudPlant, EvaluationDirective, EvaluationSurface, FamilyAttribution,
MappingPosture, MutationIdentity, MutationPoint, MutationReport, MutationSite, MutationTarget,
PlanRefusal, PlannedDamage, PlannedRun, PressureLane, ProofPlan, ScopedInvocation,
SelectionRefusal,
};
use crate::properties::{SharedSubstrate, SubstrateRef, SubstrateRoster, agreement};
use crate::report::{FindingCause, HostTrialRecord, RunAttempt, TrialConclusion};
use crate::runner::{
Invocation, Selection, execution_key, lens_verdict, record_one, trial_identity,
};
use std::collections::BTreeSet;
fn no_mutation_substrate() -> Result<SharedSubstrate, ParityRefusal> {
let declaration = SubstrateRef::named(MUTERPRATER_NAMESPACE, PARITY_DECLARATION_SUBSTRATE)
.map_err(ParityRefusal::NameNotParsed)?;
let rendering = SubstrateRef::named(MUTERPRATER_NAMESPACE, PARITY_RENDERING_SUBSTRATE)
.map_err(ParityRefusal::NameNotParsed)?;
let roster = SubstrateRoster::declared(&[declaration, rendering])
.map_err(ParityRefusal::SubstrateNotDeclared)?;
Ok(SharedSubstrate::Standing(roster))
}
fn parity_cause() -> Result<FindingCause, ParityRefusal> {
let pairing = NamespacedName::named(MUTERPRATER_NAMESPACE, NO_MUTATION_PAIRING)
.map_err(ParityRefusal::NameNotParsed)?;
Ok(FindingCause::named(
pairing.namespace().written(),
pairing.stem().written(),
))
}
pub(in crate::muterprater) fn selected_alternative(
surface: &EvaluationSurface,
selection: ActiveSelection,
) -> Result<(&MutationPoint, &AdmittedAlternative), SelectionRefusal> {
surface.selected_alternative(selection)
}
pub fn plan_pass(
surface: &EvaluationSurface,
scope: ScopedInvocation,
) -> Result<ProofPlan, PlanRefusal> {
let budget = scope.budget();
let mut runs = Vec::new();
for point in surface.points() {
let claims = BTreeSet::from([point.owner_claim()]);
for alternative in point.admitted_alternatives() {
runs.push(PlannedRun::intended(
PressureLane::InterpretedMutation,
MutationIdentity::Interpreted {
point: point.identity(),
alternative: alternative.identity(),
},
PlannedDamage::Alternative(alternative.identity()),
Selection::ByClaim(claims.clone()),
budget,
));
}
}
ProofPlan::planned(scope, runs)
}
pub fn observe_no_mutation<'pair, 'input, Input, Meaning>(
pair: &'pair EvaluationPair<Input, Meaning>,
witness: MutationWitness<Meaning>,
input: &'input Input,
invocation: &Invocation,
) -> Result<NoMutationParityReading<'pair, 'input, Input, Meaning>, NoMutationObservationRefusal> {
let substrate = no_mutation_substrate().map_err(NoMutationObservationRefusal::Substrate)?;
let cause = parity_cause().map_err(NoMutationObservationRefusal::Substrate)?;
let trial = trial_identity(witness.binding().row());
let production_measurement = invocation.clock().begin();
let production = pair.production().evaluate(input);
let production_conclusion = witness.conclude(&production);
let production_report = record_one(
witness.binding(),
invocation,
HostTrialRecord::recorded(
trial,
RunAttempt::Executed(production_conclusion),
production_measurement.finish(),
),
)
.map_err(NoMutationObservationRefusal::ProductionReport)?;
let evaluation_measurement = invocation.clock().begin();
let observed = pair
.evaluation()
.evaluate(input, EvaluationDirective::no_mutation())
.map_err(NoMutationObservationRefusal::EvaluationCall)?;
let (evaluation, evaluation_firings) = observed.into_parts();
let evaluation_conclusion = witness.conclude(&evaluation);
let evaluation_report = record_one(
witness.binding(),
invocation,
HostTrialRecord::recorded(
trial,
RunAttempt::Executed(evaluation_conclusion),
evaluation_measurement.finish(),
),
)
.map_err(NoMutationObservationRefusal::EvaluationReport)?;
let conclusion = agreement(pair.equivalence(), &production, &evaluation, cause);
Ok(NoMutationParityReading::recorded(
pair,
witness,
input,
NoMutationResults::observed(production, evaluation, evaluation_firings),
substrate,
conclusion,
NoMutationReports::recorded(production_report, evaluation_report),
))
}
#[must_use]
pub fn qualify_no_mutation<'pair, 'input, Input, Meaning>(
reading: NoMutationParityReading<'pair, 'input, Input, Meaning>,
) -> NoMutationParityStanding<'pair, 'input, Input, Meaning> {
let cause = if lens_verdict(reading.production_report()).is_err() {
Some(ParityQualificationRefusal::ProductionDidNotQualify)
} else if lens_verdict(reading.evaluation_report()).is_err() {
Some(ParityQualificationRefusal::EvaluationDidNotQualify)
} else if reading.evaluation_firings() != 0 {
Some(ParityQualificationRefusal::NoMutationActivated {
firings: reading.evaluation_firings(),
})
} else if matches!(reading.conclusion(), TrialConclusion::Refused(_)) {
Some(ParityQualificationRefusal::MeaningsDisagreed)
} else {
None
};
match cause {
Some(refusal) => {
NoMutationParityStanding::Rejected(RejectedNoMutationParity::rejected(refusal, reading))
}
None => {
NoMutationParityStanding::Qualified(NoMutationParityQualification::qualified(reading))
}
}
}
#[must_use]
pub fn availability<'surface, 'suite, 'projection, 'parity, 'pair, 'input, Input, Meaning>(
surface: Option<&'surface EvaluationSurface>,
suite: Option<&'suite CompiledSuitePressure>,
projection: Option<
&'projection CompiledProjectionPressure<'parity, 'pair, 'input, Input, Meaning>,
>,
) -> InterpreterAvailability<'surface, 'suite, 'projection, 'parity, 'pair, 'input, Input, Meaning>
{
let Some(surface) = surface else {
return InterpreterAvailability::NoConformingSurface;
};
let Some(suite) = suite else {
return InterpreterAvailability::TrustNotOpened {
missing: MissingTrustEvidence::CompiledSuitePressure,
};
};
let Some(projection) = projection else {
return InterpreterAvailability::TrustNotOpened {
missing: MissingTrustEvidence::CompiledProjectionPressure,
};
};
let standing = projection.standing();
if standing.pair().family() != surface.family()
|| standing.pair().surface() != surface.identity()
|| standing.selection().surface() != surface.identity()
{
return InterpreterAvailability::TrustNotOpened {
missing: MissingTrustEvidence::ProjectionPressureForAnotherSurface,
};
}
InterpreterAvailability::Available(InterpretedTrust::opened(surface, suite, projection))
}
pub fn execute_active<'surface, 'suite, 'projection, 'parity, 'pair, 'input, Input, Meaning>(
trust: &InterpretedTrust<'surface, 'suite, 'projection, 'parity, 'pair, 'input, Input, Meaning>,
invocation: &Invocation,
) -> Result<
InterpretedMutationEvidence<
'surface,
'suite,
'projection,
'parity,
'pair,
'input,
Input,
Meaning,
>,
InterpretedExecutionRefusal,
> {
let selection = trust.selection();
let (point, alternative) = selected_alternative(trust.surface(), selection)
.map_err(InterpretedExecutionRefusal::Selection)?;
let parity = trust.parity();
let pair = parity.reading().pair();
let input = parity.reading().input();
let witness = parity.reading().witness();
let witness_claim = witness.binding().row().claim();
if witness_claim != point.owner_claim() {
return Err(InterpretedExecutionRefusal::WitnessForAnotherClaim {
expected: point.owner_claim(),
found: witness_claim,
});
}
let execution = execution_key(witness.binding(), invocation);
if trust.projection().standing().execution() != &execution {
return Err(InterpretedExecutionRefusal::InvocationForAnotherExecution);
}
let trial = trial_identity(witness.binding().row());
let measurement = invocation.clock().begin();
let observed = pair
.evaluation()
.evaluate(
input,
EvaluationDirective::active(selection, point, alternative),
)
.map_err(InterpretedExecutionRefusal::EvaluationCall)?;
let (meaning, firings) = observed.into_parts();
let Some(activation) = ActivationEvidence::observed(selection, trial, firings) else {
return Err(InterpretedExecutionRefusal::DudPlant(Box::new(
DudPlant::unfired(selection, trial),
)));
};
let conclusion = witness.conclude(&meaning);
let report = record_one(
witness.binding(),
invocation,
HostTrialRecord::recorded(
trial,
RunAttempt::Executed(conclusion.clone()),
measurement.finish(),
),
)
.map_err(InterpretedExecutionRefusal::Report)?;
let target = MutationTarget::pressed(
MutationIdentity::Interpreted {
point: point.identity(),
alternative: alternative.identity(),
},
FamilyAttribution::Declared(alternative.family()),
MutationSite::Declared(point.activation_site()),
MappingPosture::Mapped(point.owner_claim()),
);
let mutation = MutationReport::interpreted(target, activation, &report);
Ok(InterpretedMutationEvidence::admitted(
trust.duplicate(),
meaning,
report,
mutation,
))
}