// Closed composition admission for the exact numeric-plus-Array.map root. The
// catalog is deliberately private: only the sealed numeric and Array.map
// UserFunc adapters can be selected, and no arbitrary callback or closure
// enters the production driver through this seam.

///|
priv enum DispatchManagedUserFuncAdapterToken {
  DispatchNumericUserFuncAdapterToken(Value)
  DispatchArrayMapUserFuncAdapterToken(Value)
}

///|
priv struct DispatchManagedUserFuncCatalog {
  numeric : TrustedNumericRecursionRegistry
  array_map : TrustedArrayMapRecursionRegistry
}

///|
fn DispatchManagedUserFuncCatalog::DispatchManagedUserFuncCatalog(
  numeric~ : TrustedNumericRecursionRegistry,
  array_map~ : TrustedArrayMapRecursionRegistry,
) -> DispatchManagedUserFuncCatalog {
  { numeric, array_map }
}

///|
fn numeric_map_composition_call_plan(
  preflight : NumericMapCompositionPreflight,
  catalog : DispatchManagedUserFuncCatalog,
) -> DispatchBinaryRightCallResume? {
  let left_request = DispatchCallRequest(
    callee=catalog.numeric.entry.callee,
    this_value=Undefined,
    args=[Number(NUMERIC_RECURSION_INITIAL_ARGUMENT)],
    loc=preflight.left_call_loc,
  )
  let right_request = DispatchCallRequest(
    callee=catalog.array_map.step_function,
    this_value=Undefined,
    args=[Number(preflight.array_map.plan.initial_count)],
    loc=preflight.right_call_loc,
  )
  let left_adapter = match
    catalog.select(left_request.callee, None, left_request.this_value) {
    Some(token) => token
    None => return None
  }
  guard left_adapter is DispatchNumericUserFuncAdapterToken(_) else {
    return None
  }
  let right_adapter = match
    catalog.select(right_request.callee, None, right_request.this_value) {
    Some(token) => token
    None => return None
  }
  guard right_adapter is DispatchArrayMapUserFuncAdapterToken(_) else {
    return None
  }
  Some(
    DispatchBinaryRightCallResume(
      left_request~,
      right_request~,
      left_value=None,
      op=@ast.Add,
      loc=preflight.binary_loc,
      left_adapter~,
      right_adapter~,
    ),
  )
}

///|
priv struct NumericMapCompositionPreflight {
  numeric : NumericRecursionPreflight
  array_map : ArrayMapRecursionPreflight
  left_call_loc : @token.Loc
  right_call_loc : @token.Loc
  binary_loc : @token.Loc
}

///|
priv struct NumericMapCompositionSource {
  numeric_stmts : Array[@ast.Stmt]
  array_map_stmts : Array[@ast.Stmt]
  left_call_loc : @token.Loc
  right_call_loc : @token.Loc
  binary_loc : @token.Loc
}

///|
fn dispatch_managed_user_func_adapter_token_matches(
  token : DispatchManagedUserFuncAdapterToken,
  callee : Value,
) -> Bool {
  match token {
    DispatchNumericUserFuncAdapterToken(expected)
    | DispatchArrayMapUserFuncAdapterToken(expected) =>
      array_map_value_identity_matches(expected, callee)
  }
}

///|
fn dispatch_numeric_catalog_callee_matches(
  registry : TrustedNumericRecursionRegistry,
  callee : Value,
) -> Bool {
  let entry_matches = match callee {
    Object(actual) =>
      numeric_recursion_trusted_callee_has_identity(registry.entry, actual)
    _ => false
  }
  if entry_matches {
    return true
  }
  match registry.peer {
    Some(peer) =>
      match callee {
        Object(actual) =>
          numeric_recursion_trusted_callee_has_identity(peer, actual)
        _ => false
      }
    None => false
  }
}

///|
fn dispatch_array_map_catalog_callee_matches(
  registry : TrustedArrayMapRecursionRegistry,
  callee : Value,
  map_state : MapState?,
  receiver : Value,
) -> Bool {
  if array_map_value_identity_matches(registry.step_function, callee) {
    return true
  }
  match registry.forward_function {
    Some(forward) if array_map_value_identity_matches(forward, callee) =>
      return true
    _ => ()
  }
  match map_state {
    Some(state) if array_map_value_identity_matches(state.callback, callee) =>
      true
    Some(_) if registry.plan.callback_family is ArrayMapMemberCallback =>
      array_map_member_receiver_matches(
        receiver,
        callee,
        registry.plan.member_property_name,
      )
    _ => false
  }
}

///|
// Selection is a pure exhaustive choice over the sealed adapter catalog. A
// collision is rejected as None rather than silently preferring one family.
fn DispatchManagedUserFuncCatalog::select(
  self : DispatchManagedUserFuncCatalog,
  callee : Value,
  map_state : MapState?,
  receiver : Value,
) -> DispatchManagedUserFuncAdapterToken? {
  let numeric = dispatch_numeric_catalog_callee_matches(self.numeric, callee)
  let array_map = dispatch_array_map_catalog_callee_matches(
    self.array_map,
    callee,
    map_state,
    receiver,
  )
  match (numeric, array_map) {
    (true, false) => Some(DispatchNumericUserFuncAdapterToken(callee))
    (false, true) => Some(DispatchArrayMapUserFuncAdapterToken(callee))
    (false, false) | (true, true) => None
  }
}

///|
fn composition_call_expression(
  expr : @ast.Expr,
  expected_name : String,
) -> (@token.Loc, @token.Loc)? {
  match expr {
    @ast.Call(
      @ast.Ident(actual_name, _),
      [@ast.NumberLit(value, lex_form, argument_loc)],
      call_loc
    ) if actual_name == expected_name &&
      lex_form == @token.LexForm::LexNormal &&
      exact_numeric_recursion_number(
        @ast.NumberLit(value, lex_form, argument_loc),
        NUMERIC_RECURSION_INITIAL_ARGUMENT,
      ) => Some((call_loc, argument_loc))
    _ => None
  }
}

///|
fn classify_numeric_map_composition_source(
  stmts : Array[@ast.Stmt],
) -> NumericMapCompositionSource? {
  guard stmts.length() == 4 else { return None }
  let (left_expr, right_expr, binary_loc, stmt_loc) = match stmts[3] {
    @ast.ExprStmt(@ast.Binary(@ast.Add, left, right, binary_loc), stmt_loc) =>
      (left, right, binary_loc, stmt_loc)
    _ => return None
  }
  guard composition_call_expression(left_expr, "step") is Some((left_loc, _)) else {
    return None
  }
  guard composition_call_expression(right_expr, "u") is Some((right_loc, _)) else {
    return None
  }
  let numeric_stmts = [stmts[0], @ast.ExprStmt(left_expr, stmt_loc)]
  let array_map_stmts = [
    stmts[1],
    stmts[2],
    @ast.ExprStmt(right_expr, stmt_loc),
  ]
  guard classify_numeric_recursion_program(numeric_stmts) is Some(numeric) else {
    return None
  }
  guard numeric_recursion_plan_is_dispatchable(numeric) else { return None }
  guard classify_array_map_recursion_program(array_map_stmts) is Some(array_map) else {
    return None
  }
  guard array_map_plan_is_dispatchable(array_map) else { return None }
  Some({
    numeric_stmts,
    array_map_stmts,
    left_call_loc: left_loc,
    right_call_loc: right_loc,
    binary_loc,
  })
}

///|
fn Interpreter::preflight_dispatchable_numeric_map_composition_program(
  self : Interpreter,
  stmts : Array[@ast.Stmt],
) -> NumericMapCompositionPreflight? {
  let source = match classify_numeric_map_composition_source(stmts) {
    Some(source) => source
    None => return None
  }
  let numeric_plan = match
    classify_numeric_recursion_program(source.numeric_stmts) {
    Some(plan) => plan
    None => return None
  }
  let array_map_plan = match
    classify_array_map_recursion_program(source.array_map_stmts) {
    Some(plan) => plan
    None => return None
  }
  let numeric = match self.preflight_numeric_recursion_program(numeric_plan) {
    Some(preflight) => preflight
    None => return None
  }
  let array_map = match
    self.preflight_array_map_recursion_program(array_map_plan) {
    Some(preflight) => preflight
    None => return None
  }
  Some({
    numeric,
    array_map,
    left_call_loc: source.left_call_loc,
    right_call_loc: source.right_call_loc,
    binary_loc: source.binary_loc,
  })
}

///|
fn Interpreter::seal_numeric_map_composition_catalog(
  self : Interpreter,
  preflight : NumericMapCompositionPreflight,
  stmts : Array[@ast.Stmt],
) -> DispatchManagedUserFuncCatalog raise InvalidActivationDispatchShell {
  let source = match classify_numeric_map_composition_source(stmts) {
    Some(source) => source
    None =>
      invalid_activation_dispatch_shell(
        "numeric/map composition no longer satisfies exact admission",
      )
  }
  guard source.left_call_loc == preflight.left_call_loc &&
    source.right_call_loc == preflight.right_call_loc &&
    source.binary_loc == preflight.binary_loc else {
    invalid_activation_dispatch_shell(
      "numeric/map composition source locations changed after preflight",
    )
  }
  let numeric = self.seal_numeric_recursion_registry(
    preflight.numeric,
    source.numeric_stmts,
  )
  let array_map = self.seal_array_map_recursion_registry(
    preflight.array_map,
    source.array_map_stmts,
  )
  DispatchManagedUserFuncCatalog(numeric~, array_map~)
}

///|
// Postfix keeps arbitrary left-associated depth in owned data instead of
// adding a continuation variant for each call count.
priv enum DispatchExpressionPlanStep {
  DispatchExpressionCall(DispatchExpressionCallStep)
  DispatchExpressionNumericAdd(@token.Loc)
}

///|
priv struct DispatchExpressionCallStep {
  request : DispatchCallRequest
  adapter : DispatchManagedUserFuncAdapterToken
  name : String
}

///|
fn DispatchExpressionCallStep::DispatchExpressionCallStep(
  request~ : DispatchCallRequest,
  adapter~ : DispatchManagedUserFuncAdapterToken,
  name~ : String,
) -> DispatchExpressionCallStep {
  {
    request: DispatchCallRequest(
      callee=request.callee,
      this_value=request.this_value,
      args=request.args,
      loc=request.loc,
    ),
    adapter,
    name,
  }
}

///|
priv struct DispatchExpressionPlan {
  steps : Array[DispatchExpressionPlanStep]
}

///|
fn DispatchExpressionPlan::DispatchExpressionPlan(
  steps~ : Array[DispatchExpressionPlanStep],
) -> DispatchExpressionPlan {
  { steps: steps.map(snapshot_dispatch_expression_plan_step) }
}

///|
priv struct DispatchExpressionPlanResume {
  plan : DispatchExpressionPlan
  next_index : Int
  values : Array[Value]
}

///|
fn DispatchExpressionPlanResume::DispatchExpressionPlanResume(
  plan~ : DispatchExpressionPlan,
  next_index~ : Int,
  values~ : Array[Value],
) -> DispatchExpressionPlanResume {
  {
    plan: snapshot_dispatch_expression_plan(plan),
    next_index,
    values: values.copy(),
  }
}

///|
priv struct DispatchExpressionCallSource {
  name : String
  argument : Double
  call_loc : @token.Loc
  argument_loc : @token.Loc
}

///|
priv enum DispatchExpressionSourceStep {
  DispatchExpressionCallSourceStep(DispatchExpressionCallSource)
  DispatchExpressionAddSourceStep(@token.Loc)
}

///|
priv struct NumericMapExpressionSource {
  numeric_stmts : Array[@ast.Stmt]
  array_map_stmts : Array[@ast.Stmt]
  steps : Array[DispatchExpressionSourceStep]
}

///|
priv struct NumericMapExpressionPreflight {
  numeric : NumericRecursionPreflight
  array_map : ArrayMapRecursionPreflight
  source : NumericMapExpressionSource
}

///|
fn snapshot_dispatch_expression_call_step(
  step : DispatchExpressionCallStep,
) -> DispatchExpressionCallStep {
  DispatchExpressionCallStep(
    request=step.request,
    adapter=step.adapter,
    name=step.name,
  )
}

///|
fn snapshot_dispatch_expression_plan_step(
  step : DispatchExpressionPlanStep,
) -> DispatchExpressionPlanStep {
  match step {
    DispatchExpressionCall(call) =>
      DispatchExpressionCall(snapshot_dispatch_expression_call_step(call))
    DispatchExpressionNumericAdd(loc) => DispatchExpressionNumericAdd(loc)
  }
}

///|
fn snapshot_dispatch_expression_plan(
  plan : DispatchExpressionPlan,
) -> DispatchExpressionPlan {
  DispatchExpressionPlan(steps=plan.steps)
}

///|
fn snapshot_dispatch_expression_plan_resume(
  plan_resume : DispatchExpressionPlanResume,
) -> DispatchExpressionPlanResume {
  DispatchExpressionPlanResume(
    plan=plan_resume.plan,
    next_index=plan_resume.next_index,
    values=plan_resume.values,
  )
}

///|
fn dispatch_expression_plan_root_call_locs(
  plan : DispatchExpressionPlan,
) -> Array[@token.Loc] {
  let locations : Array[@token.Loc] = []
  for step in plan.steps {
    match step {
      DispatchExpressionCall(call) =>
        match call.adapter {
          DispatchArrayMapUserFuncAdapterToken(_) =>
            locations.push(call.request.loc)
          DispatchNumericUserFuncAdapterToken(_) => ()
        }
      DispatchExpressionNumericAdd(_) => ()
    }
  }
  locations
}

///|
fn expression_call_source(expr : @ast.Expr) -> DispatchExpressionCallSource? {
  match expr {
    @ast.Call(
      @ast.Ident(name, _),
      [@ast.NumberLit(argument, lex_form, argument_loc)],
      call_loc
    ) if (name == "step" || name == "u") &&
      lex_form == @token.LexForm::LexNormal &&
      argument == NUMERIC_RECURSION_INITIAL_ARGUMENT =>
      Some({ name, argument, call_loc, argument_loc })
    _ => None
  }
}

///|
priv enum DispatchExpressionVisit {
  DispatchExpressionVisitExpr(@ast.Expr)
  DispatchExpressionVisitAdd(@token.Loc)
}

///|
// Walk the exact left-associated shape with an explicit worklist. A binary
// right child must be a call leaf; right-nested trees remain legacy.
fn classify_expression_source_steps(
  expr : @ast.Expr,
) -> Array[DispatchExpressionSourceStep]? {
  let work : Array[DispatchExpressionVisit] = [
    DispatchExpressionVisitExpr(expr),
  ]
  let steps : Array[DispatchExpressionSourceStep] = []
  while work.pop() is Some(item) {
    match item {
      DispatchExpressionVisitExpr(@ast.Binary(@ast.Add, left, right, loc)) => {
        guard expression_call_source(right) is Some(_) else { return None }
        work.push(DispatchExpressionVisitAdd(loc))
        work.push(DispatchExpressionVisitExpr(right))
        work.push(DispatchExpressionVisitExpr(left))
      }
      DispatchExpressionVisitExpr(expr) =>
        match expression_call_source(expr) {
          Some(source) => steps.push(DispatchExpressionCallSourceStep(source))
          None => return None
        }
      DispatchExpressionVisitAdd(loc) =>
        steps.push(DispatchExpressionAddSourceStep(loc))
    }
  }
  Some(steps)
}

///|
fn expression_source_step_is_call_named(
  steps : Array[DispatchExpressionSourceStep],
  index : Int,
  name : String,
) -> Bool {
  match steps[index] {
    DispatchExpressionCallSourceStep({ name: actual, .. }) => actual == name
    _ => false
  }
}

///|
fn expression_source_step_is_add(
  steps : Array[DispatchExpressionSourceStep],
  index : Int,
) -> Bool {
  match steps[index] {
    DispatchExpressionAddSourceStep(_) => true
    _ => false
  }
}

///|
// The common postfix plan is deliberately closed to the three-call,
// four-call, and five-call sources already proven at the public boundary. A
// longer or reordered call sequence remains on the legacy evaluator.
fn expression_source_shape_is_admissible(
  steps : Array[DispatchExpressionSourceStep],
) -> Bool {
  match steps.length() {
    5 =>
      expression_source_step_is_call_named(steps, 0, "step") &&
      expression_source_step_is_call_named(steps, 1, "u") &&
      expression_source_step_is_add(steps, 2) &&
      expression_source_step_is_call_named(steps, 3, "step") &&
      expression_source_step_is_add(steps, 4)
    7 =>
      expression_source_step_is_call_named(steps, 0, "step") &&
      expression_source_step_is_call_named(steps, 1, "u") &&
      expression_source_step_is_add(steps, 2) &&
      expression_source_step_is_call_named(steps, 3, "step") &&
      expression_source_step_is_add(steps, 4) &&
      expression_source_step_is_call_named(steps, 5, "u") &&
      expression_source_step_is_add(steps, 6)
    9 =>
      expression_source_step_is_call_named(steps, 0, "step") &&
      expression_source_step_is_call_named(steps, 1, "u") &&
      expression_source_step_is_add(steps, 2) &&
      expression_source_step_is_call_named(steps, 3, "step") &&
      expression_source_step_is_add(steps, 4) &&
      expression_source_step_is_call_named(steps, 5, "u") &&
      expression_source_step_is_add(steps, 6) &&
      expression_source_step_is_call_named(steps, 7, "step") &&
      expression_source_step_is_add(steps, 8)
    _ => false
  }
}

///|
fn numeric_map_expression_source(
  stmts : Array[@ast.Stmt],
) -> NumericMapExpressionSource? {
  guard stmts.length() == 4 else { return None }
  let (expr, stmt_loc) = match stmts[3] {
    @ast.ExprStmt(expr, stmt_loc) => (expr, stmt_loc)
    _ => return None
  }
  let steps = match classify_expression_source_steps(expr) {
    Some(steps) => steps
    None => return None
  }
  guard expression_source_shape_is_admissible(steps) else { return None }
  let mut first_step_expr : @ast.Expr? = None
  let mut first_u_expr : @ast.Expr? = None
  for step in steps {
    match step {
      DispatchExpressionCallSourceStep(source) => {
        if source.name == "step" && first_step_expr is None {
          first_step_expr = Some(
            @ast.Call(
              @ast.Ident(source.name, @token.Loc::default()),
              [
                @ast.NumberLit(
                  source.argument,
                  @token.LexForm::LexNormal,
                  source.argument_loc,
                ),
              ],
              source.call_loc,
            ),
          )
        }
        if source.name == "u" && first_u_expr is None {
          first_u_expr = Some(
            @ast.Call(
              @ast.Ident(source.name, @token.Loc::default()),
              [
                @ast.NumberLit(
                  source.argument,
                  @token.LexForm::LexNormal,
                  source.argument_loc,
                ),
              ],
              source.call_loc,
            ),
          )
        }
      }
      DispatchExpressionAddSourceStep(loc) => ignore(loc)
    }
  }
  guard first_step_expr is Some(step_expr) && first_u_expr is Some(u_expr) else {
    return None
  }
  let numeric_stmts = [stmts[0], @ast.ExprStmt(step_expr, stmt_loc)]
  let array_map_stmts = [stmts[1], stmts[2], @ast.ExprStmt(u_expr, stmt_loc)]
  Some({ numeric_stmts, array_map_stmts, steps })
}

///|
fn Interpreter::preflight_dispatchable_numeric_map_expression_program(
  self : Interpreter,
  stmts : Array[@ast.Stmt],
) -> NumericMapExpressionPreflight? {
  let source = match numeric_map_expression_source(stmts) {
    Some(source) => source
    None => return None
  }
  let numeric_plan = match
    classify_numeric_recursion_program(source.numeric_stmts) {
    Some(plan) if numeric_recursion_plan_is_dispatchable(plan) => plan
    _ => return None
  }
  let array_map_plan = match
    classify_array_map_recursion_program(source.array_map_stmts) {
    Some(plan) if array_map_plan_is_dispatchable(plan) => plan
    _ => return None
  }
  let numeric = match self.preflight_numeric_recursion_program(numeric_plan) {
    Some(preflight) => preflight
    None => return None
  }
  let array_map = match
    self.preflight_array_map_recursion_program(array_map_plan) {
    Some(preflight) => preflight
    None => return None
  }
  Some({ numeric, array_map, source })
}

///|
fn source_steps_match(
  expected : Array[DispatchExpressionSourceStep],
  actual : Array[DispatchExpressionSourceStep],
) -> Bool {
  guard expected.length() == actual.length() else { return false }
  for i in 0..
        expected_call.name == actual_call.name &&
        expected_call.argument == actual_call.argument &&
        expected_call.call_loc == actual_call.call_loc &&
        expected_call.argument_loc == actual_call.argument_loc
      (
        DispatchExpressionAddSourceStep(expected_loc),
        DispatchExpressionAddSourceStep(actual_loc),
      ) => expected_loc == actual_loc
      _ => false
    }
    guard matches else { return false }
  }
  true
}

///|
fn dispatch_numeric_map_expression_adapter_matches_name(
  adapter : DispatchManagedUserFuncAdapterToken,
  name : String,
) -> Bool {
  match (adapter, name) {
    (DispatchNumericUserFuncAdapterToken(_), "step") => true
    (DispatchArrayMapUserFuncAdapterToken(_), "u") => true
    _ => false
  }
}

///|
fn Interpreter::seal_numeric_map_expression_catalog(
  self : Interpreter,
  preflight : NumericMapExpressionPreflight,
  stmts : Array[@ast.Stmt],
) -> (DispatchManagedUserFuncCatalog, DispatchExpressionPlan) raise InvalidActivationDispatchShell {
  let source = match numeric_map_expression_source(stmts) {
    Some(source) => source
    None =>
      invalid_activation_dispatch_shell(
        "numeric/map expression no longer satisfies exact admission",
      )
  }
  guard source_steps_match(preflight.source.steps, source.steps) else {
    invalid_activation_dispatch_shell(
      "numeric/map expression tree or source locations changed after preflight",
    )
  }
  let numeric = self.seal_numeric_recursion_registry(
    preflight.numeric,
    source.numeric_stmts,
  )
  let array_map = self.seal_array_map_recursion_registry(
    preflight.array_map,
    source.array_map_stmts,
  )
  let catalog = DispatchManagedUserFuncCatalog(numeric~, array_map~)
  let plan_steps : Array[DispatchExpressionPlanStep] = []
  for source_step in source.steps {
    match source_step {
      DispatchExpressionCallSourceStep(call) => {
        let callee = if call.name == "step" {
          catalog.numeric.entry.callee
        } else {
          catalog.array_map.step_function
        }
        let adapter = match catalog.select(callee, None, Undefined) {
          Some(adapter) => adapter
          None =>
            invalid_activation_dispatch_shell(
              "numeric/map expression adapter selection was not unique",
            )
        }
        guard dispatch_numeric_map_expression_adapter_matches_name(
          adapter,
          call.name,
        ) else {
          invalid_activation_dispatch_shell(
            "numeric/map expression adapter family drifted",
          )
        }
        plan_steps.push(
          DispatchExpressionCall(
            DispatchExpressionCallStep(
              request=DispatchCallRequest(
                callee~,
                this_value=Undefined,
                args=[Number(call.argument)],
                loc=call.call_loc,
              ),
              adapter~,
              name=call.name,
            ),
          ),
        )
      }
      DispatchExpressionAddSourceStep(loc) =>
        plan_steps.push(DispatchExpressionNumericAdd(loc))
    }
  }
  (catalog, DispatchExpressionPlan(steps=plan_steps))
}

///|
fn resume_dispatch_expression_plan(
  state : ActivationDispatchState,
  plan_resume : DispatchExpressionPlanResume,
  value : Value,
) -> DispatchCompletionResume raise InvalidDispatchTransition {
  guard state.phase is DispatchReady else {
    invalid_dispatch_transition("expression plan resume requires Ready")
  }
  guard plan_resume.next_index >= 0 &&
    plan_resume.next_index <= plan_resume.plan.steps.length() else {
    invalid_dispatch_transition("expression plan cursor is outside its steps")
  }
  let values = plan_resume.values.copy()
  values.push(value)
  let mut index = plan_resume.next_index
  while index < plan_resume.plan.steps.length() {
    match plan_resume.plan.steps[index] {
      DispatchExpressionCall(call) => {
        guard dispatch_managed_user_func_adapter_token_matches(
            call.adapter,
            call.request.callee,
          ) &&
          dispatch_numeric_map_expression_adapter_matches_name(
            call.adapter,
            call.name,
          ) else {
          invalid_dispatch_transition("expression plan call adapter drifted")
        }
        let next = DispatchExpressionPlanResume(
          plan=plan_resume.plan,
          next_index=index + 1,
          values~,
        )
        return dispatch_resume_decision(
          suspend_dispatch_work(
            state,
            DispatchSuspendCall(
              call.request,
              DispatchContinueExpressionPlan(next),
            ),
          ),
        )
      }
      DispatchExpressionNumericAdd(loc) => {
        guard values.length() >= 2 else {
          invalid_dispatch_transition(
            "expression plan binary node lacks two operands",
          )
        }
        let right = match values.pop() {
          Some(right) => right
          None =>
            invalid_dispatch_transition("expression plan right operand missing")
        }
        let left = match values.pop() {
          Some(left) => left
          None =>
            invalid_dispatch_transition("expression plan left operand missing")
        }
        let next = DispatchExpressionPlanResume(
          plan=plan_resume.plan,
          next_index=index + 1,
          values~,
        )
        return dispatch_resume_decision(
          suspend_dispatch_work(
            state,
            DispatchSuspendContinueProduction(
              DispatchContinueExpressionPlan(next),
              DispatchNumericApplyBinaryRight(
                DispatchBinaryResume(op=@ast.Add, left~, loc~),
                right,
              ),
            ),
          ),
        )
      }
    }
    index += 1
  }
  guard values.length() == 1 else {
    invalid_dispatch_transition("expression plan did not produce one value")
  }
  DispatchResumeCompletion(DispatchNormal(values[0]))
}