// Exact, callback-free admission for a public `Interpreter::call_value` root
// that enters the numeric self/mutual recursion slice. The plan contains call
// syntax only; closure, binding, object, realm, and source provenance are
// sealed by the next layer before managed execution begins.
///|
#warnings("-unused_constructor-unused_field")
priv enum DirectNumericRecursionCycle {
DirectNumericSelf
DirectNumericMutualPeer(String)
}
///|
#warnings("-unused_field")
priv struct DirectNumericRecursionCallPlan {
entry : NumericRecursionFunctionSyntax
cycle : DirectNumericRecursionCycle
initial_argument : Double
root_call_loc : @token.Loc
}
///|
fn DirectNumericRecursionCallPlan::DirectNumericRecursionCallPlan(
entry~ : NumericRecursionFunctionSyntax,
cycle~ : DirectNumericRecursionCycle,
initial_argument~ : Double,
root_call_loc~ : @token.Loc,
) -> DirectNumericRecursionCallPlan {
{ entry, cycle, initial_argument, root_call_loc }
}
///|
fn classify_direct_numeric_recursion_user_func(
data : FuncData,
) -> (NumericRecursionFunctionSyntax, DirectNumericRecursionCycle)? {
guard data.name is Some(name) &&
!data.strict &&
!data.has_name_binding &&
!data.is_method else {
return None
}
guard classify_numeric_recursion_function_syntax(name, data.params, data.body)
is Some(entry) &&
entry.return_recipe is NumericRecursionDirectReturn &&
entry.retained_parameter is None &&
numeric_recursion_identifier_is_safe(entry.recursive_callee) &&
entry.recursive_callee != entry.parameter else {
return None
}
let cycle = if entry.recursive_callee == name {
DirectNumericSelf
} else {
DirectNumericMutualPeer(entry.recursive_callee)
}
Some((entry, cycle))
}
///|
#warnings("-unused_value")
fn classify_direct_numeric_recursion_call(
callee : Value,
this_value : Value,
args : Array[Value],
root_call_loc : @token.Loc,
) -> DirectNumericRecursionCallPlan? {
guard this_value is Undefined &&
args.length() == 1 &&
args[0] is Number(initial_argument) &&
initial_argument == NUMERIC_RECURSION_INITIAL_ARGUMENT else {
return None
}
guard callee is Object(object_data) &&
object_data.class_name == "Function" &&
object_data.callable is Some(UserFunc(data)) else {
return None
}
match classify_direct_numeric_recursion_user_func(data) {
Some((entry, cycle)) =>
Some(
DirectNumericRecursionCallPlan(
entry~,
cycle~,
initial_argument~,
root_call_loc~,
),
)
None => None
}
}