///|
/// Only simple numeric/vector values enter this private producer scope.
fn dae_numeric_result_value(value : @lib.ValType) -> Bool {
match value {
@lib.NumTypeValType(_) | @lib.VecTypeValType => true
_ => false
}
}
///|
/// The final candidate must independently remove one numeric result only.
fn dae_numeric_result_signature_change(
old : @lib.FuncType,
next : @lib.FuncType,
) -> Bool {
let @lib.FuncType(old_params, old_results) = old
let @lib.FuncType(next_params, next_results) = next
old_params == next_params &&
old_params.all(dae_numeric_result_value) &&
old_results.length() == 1 &&
dae_numeric_result_value(old_results[0]) &&
next_results.is_empty()
}
///| Plan checks admit only the audited result constructor. They do not replace
///|
/// the independent module, context, body and dependency checks at the gate.
fn dae_numeric_result_validation_plan(plan : DaeRewritePlan) -> Bool {
let @lib.TypeSec(old_types) = plan.type_section_rewrite.expected
let @lib.TypeSec(next_types) = plan.type_section_rewrite.replacement
physical_equal(old_types, next_types) &&
plan.parameter_actions.all(fn(action) { action == DaeKeepParameter }) &&
plan.result_actions.length() == 1 &&
plan.result_actions[0] == DaeRemoveResult &&
dae_numeric_result_signature_change(
plan.old_signature,
plan.replacement_signature,
)
}
///| Preserve a source only before the audited numeric result COW constructor.
///|
/// Unsupported signatures still end the scope before any producer runs.
fn dae_numeric_result_validation_before_producer(
chain : DaeScalarValidationChain?,
graph : DaeCurrentBoundaryGraph,
target_def : Int32,
) -> Unit {
let allowed = match chain {
Some(chain) if chain.no_callback is Some(_) &&
chain.numeric_result_source &&
target_def >= 0 &&
target_def < graph.snapshot.defined => {
let target_abs = graph.snapshot.imported + target_def
if target_abs < 0 || target_abs >= graph.snapshot.function_types.length() {
false
} else {
let calls = graph.snapshot.call_facts
let direct = dae_call_boundary_count_at(calls.direct_calls, target_abs)
let all_dropped = direct > 0 &&
dae_call_boundary_count_at(calls.dropped_calls, target_abs) == direct
match graph.snapshot.function_types[target_abs] {
Some(@lib.FuncType(params, results)) =>
all_dropped &&
params.all(dae_numeric_result_value) &&
results.length() == 1 &&
dae_numeric_result_value(results[0])
None => false
}
}
}
_ => false
}
if !allowed {
dae_scalar_validation_barrier_opt(chain)
}
}
///|
/// Validate the final reconstructed commit, never a producer touch mask.
fn dae_numeric_result_validation_check_candidate(
chain : DaeScalarValidationChain,
source : @lib.Module,
candidate : @lib.Module,
plan : DaeRewritePlan,
work~ : DaeScalarValidationWork? = None,
) -> Result[Unit, @validate.ValidationError] {
if dae_numeric_result_validation_plan(plan) {
return dae_scalar_validation_check_candidate(
chain,
source,
candidate,
work~,
allow_numeric_result_removal=true,
)
}
// Appended/replaced types, references and all other plans use the full gate.
// Do not carry that unsupported producer's checked source to a later offer.
dae_scalar_validation_barrier(chain)
let result = dae_scalar_validation_check_candidate(
chain,
source,
candidate,
work~,
)
dae_scalar_validation_barrier(chain)
result
}