// Exact, callback-free admission for the two structural lifecycle roots owned
// by #630. The plan contains no AST arrays: mutable syntax remains at the
// imperative shell boundary and is reclassified before managed execution.
///|
priv enum ControlLifecyclePlan {
ControlLabelledBreak(String)
ControlBoundedContinue
}
///|
#warnings("-unused_field")
priv struct ControlLifecyclePreflight {
plan : ControlLifecyclePlan
}
///|
fn ControlLifecyclePreflight::ControlLifecyclePreflight(
plan~ : ControlLifecyclePlan,
) -> ControlLifecyclePreflight {
{ plan, }
}
///|
#warnings("-unused_field")
priv struct TrustedControlLifecycleProgram {
plan : ControlLifecyclePlan
root_env : Environment
}
///|
#warnings("-unused_value")
fn TrustedControlLifecycleProgram::TrustedControlLifecycleProgram(
plan~ : ControlLifecyclePlan,
root_env~ : Environment,
) -> TrustedControlLifecycleProgram {
{ plan, root_env }
}
///|
#warnings("-unused_constructor")
priv enum ControlLifecyclePhase {
ControlAwaitRoot
ControlAwaitProtected
ControlAwaitAbrupt
ControlAwaitFinalizer
ControlAwaitLoopAdvance
ControlAwaitTerminal
ControlFinished
}
///|
#warnings("-unused_constructor")
priv enum ControlLifecycleRole {
ControlRootRole
ControlProtectedRole
ControlAbruptRole
ControlFinalizerRole
ControlLoopAdvanceRole
ControlTerminalRole
}
///|
fn exact_control_number_statement(stmt : @ast.Stmt, expected : Double) -> Bool {
match stmt {
@ast.ExprStmt(@ast.NumberLit(value, lex_form, _), _) =>
value == expected && lex_form == @token.LexForm::LexNormal
_ => false
}
}
///|
fn control_lifecycle_try_matches(
plan : ControlLifecyclePlan,
stmt : @ast.Stmt,
) -> Bool {
guard stmt is @ast.TryCatchStmt(try_body, None, None, Some(finalizer_body), _) &&
try_body.length() == 1 &&
finalizer_body.length() == 1 else {
return false
}
match plan {
ControlLabelledBreak(label) =>
try_body[0] is @ast.BreakStmt(Some(actual), _) &&
actual == label &&
exact_control_number_statement(finalizer_body[0], 1.0)
ControlBoundedContinue =>
try_body[0] is @ast.ContinueStmt(None, _) &&
exact_control_number_statement(finalizer_body[0], 2.0)
}
}
///|
fn control_lifecycle_root_matches(
plan : ControlLifecyclePlan,
stmt : @ast.Stmt,
) -> Bool {
match (plan, stmt) {
(ControlLabelledBreak(expected), @ast.LabeledStmt(actual, body, _)) =>
actual == expected && control_lifecycle_try_matches(plan, body)
(ControlBoundedContinue, @ast.DoWhileStmt(body, @ast.BoolLit(false, _), _)) =>
control_lifecycle_try_matches(plan, body)
_ => false
}
}
///|
#warnings("-unused_value")
fn control_lifecycle_abrupt_matches(
plan : ControlLifecyclePlan,
stmt : @ast.Stmt,
) -> Bool {
match (plan, stmt) {
(ControlLabelledBreak(expected), @ast.BreakStmt(Some(actual), _)) =>
actual == expected
(ControlBoundedContinue, @ast.ContinueStmt(None, _)) => true
_ => false
}
}
///|
#warnings("-unused_value")
fn control_lifecycle_finalizer_matches(
plan : ControlLifecyclePlan,
stmt : @ast.Stmt,
) -> Bool {
match plan {
ControlLabelledBreak(_) => exact_control_number_statement(stmt, 1.0)
ControlBoundedContinue => exact_control_number_statement(stmt, 2.0)
}
}
///|
fn control_lifecycle_terminal_matches(
plan : ControlLifecyclePlan,
stmt : @ast.Stmt,
) -> Bool {
match plan {
ControlLabelledBreak(_) => exact_control_number_statement(stmt, 9.0)
ControlBoundedContinue => exact_control_number_statement(stmt, 8.0)
}
}
///|
fn control_lifecycle_plans_match(
expected : ControlLifecyclePlan,
actual : ControlLifecyclePlan,
) -> Bool {
match (expected, actual) {
(ControlLabelledBreak(expected), ControlLabelledBreak(actual)) =>
expected == actual
(ControlBoundedContinue, ControlBoundedContinue) => true
_ => false
}
}
///|
fn classify_control_lifecycle_program(
stmts : Array[@ast.Stmt],
) -> ControlLifecyclePlan? {
guard stmts.length() == 2 else { return None }
match stmts[0] {
@ast.LabeledStmt(label, _, _) => {
let plan = ControlLabelledBreak(label)
guard control_lifecycle_root_matches(plan, stmts[0]) &&
control_lifecycle_terminal_matches(plan, stmts[1]) else {
return None
}
Some(plan)
}
@ast.DoWhileStmt(_, _, _) => {
let plan = ControlBoundedContinue
guard control_lifecycle_root_matches(plan, stmts[0]) &&
control_lifecycle_terminal_matches(plan, stmts[1]) else {
return None
}
Some(plan)
}
_ => None
}
}
///|
#warnings("-unused_value")
fn preflight_control_lifecycle_program(
stmts : Array[@ast.Stmt],
) -> ControlLifecyclePreflight? {
classify_control_lifecycle_program(stmts).map(plan => {
ControlLifecyclePreflight(plan~)
})
}
///|
#warnings("-unused_value")
fn seal_control_lifecycle_program(
preflight : ControlLifecyclePreflight,
stmts : Array[@ast.Stmt],
root_env : Environment,
) -> TrustedControlLifecycleProgram raise InvalidActivationDispatchShell {
guard classify_control_lifecycle_program(stmts) is Some(actual) &&
control_lifecycle_plans_match(preflight.plan, actual) else {
invalid_activation_dispatch_shell(
"control lifecycle program no longer matches exact admission",
)
}
TrustedControlLifecycleProgram(plan=preflight.plan, root_env~)
}
///|
#warnings("-unused_value")
fn advance_control_lifecycle_phase(
plan : ControlLifecyclePlan,
phase : ControlLifecyclePhase,
role : ControlLifecycleRole,
) -> ControlLifecyclePhase? {
match (plan, phase, role) {
(_, ControlAwaitRoot, ControlRootRole) => Some(ControlAwaitProtected)
(_, ControlAwaitProtected, ControlProtectedRole) => Some(ControlAwaitAbrupt)
(_, ControlAwaitAbrupt, ControlAbruptRole) => Some(ControlAwaitFinalizer)
(ControlLabelledBreak(_), ControlAwaitFinalizer, ControlFinalizerRole) =>
Some(ControlAwaitTerminal)
(ControlBoundedContinue, ControlAwaitFinalizer, ControlFinalizerRole) =>
Some(ControlAwaitLoopAdvance)
(ControlBoundedContinue, ControlAwaitLoopAdvance, ControlLoopAdvanceRole) =>
Some(ControlAwaitTerminal)
(_, ControlAwaitTerminal, ControlTerminalRole) => Some(ControlFinished)
_ => None
}
}