Class ObligationCensus

java.lang.Object
org.ek9lang.compiler.phase5.ObligationCensus
All Implemented Interfaces:
Consumer<org.antlr.v4.runtime.tree.ParseTree>

final class ObligationCensus extends Object implements Consumer<org.antlr.v4.runtime.tree.ParseTree>
Layer 1 of the Symbolic/Contract Scanner — the every-build obligation census (docs/tooling/EK9_SYMBOLIC_SCANNER_IMPLEMENTATION_SPEC.md §2). It rides the existing phase-5 walk beside ValueTrackingAnalyzer, enumerating the contract/partiality obligations in each callable body and marking those an existing analysis already discharges, then squirrelling the tally (OBLIGATIONS_TOTAL/DISCHARGED/UNDISCHARGED) on the construct symbol — the same static, every-build role InputVarietyDenominatorRecorder plays for input variety, and the same squirrel lifecycle as COMPLEXITY/INPUT_VARIETY_*.

Why inline, not a post-hoc exit walk. Discharge for a guarded division (if y &lt;&gt; 0 then x / y) or a provably-true require depends on the narrowed value state at the obligation's own program point — state ValueTrackingAnalyzer holds only during the walk and merges away by construct exit. So detection happens inline at the obligation node (checkArithmetic(EK9Parser.ExpressionContext) from exitExpression, checkRequire(EK9Parser.RequireStatementContext) from enterRequireStatement), reading the live narrowed state exactly as the sibling flow checkers (FlowConditionOrError, RedundantIsSetCheckOrError) do (§2.5). Only the squirrel — the pop of the finished tally — happens at construct exit, wired into the same exit .andThen chain as InputVarietyDenominatorRecorder.

A per-callable scope stack isolates nested callables (a dynamic function's obligations never fold into the enclosing method). Advisory only — the census emits no error; undischarged obligations are the Layer-2 solver's candidates, surfaced by the ungated Contract roundel.

  • Constructor Details

  • Method Details

    • enterConstruct

      void enterConstruct()
      Open a fresh obligation scope on entry of a callable (function / method / operator / service operation / dynamic function). Paired with accept(ParseTree) on the callable's exit.
    • accept

      public void accept(org.antlr.v4.runtime.tree.ParseTree node)
      Close the current callable's obligation scope and squirrel its tally on the construct symbol. Wired as a Consumer<ParseTree> into the exit .andThen chain, so it runs after the body walk has filled the tally (and after valueTracker.exitCallableScope() — the tally is already complete, no live value state is read here).
      Specified by:
      accept in interface Consumer<org.antlr.v4.runtime.tree.ParseTree>
    • checkArithmetic

      void checkArithmetic(EK9Parser.ExpressionContext ctx)
      Count a division / modulo / remainder as a DIV_BY_ZERO obligation, discharged when the divisor is provably non-zero from the narrowed flow state. Called from exitExpression so the ValueTrackingAnalyzer narrowing is settled (inside if y <> 0 the divisor is narrowed to exclude zero).
    • checkRequire

      void checkRequire(EK9Parser.RequireStatementContext ctx)
      Count a require as a REQUIRE obligation, discharged when its expression is provably true from the narrowed flow state at the require's program point. Called from enterRequireStatement; the state read is what is known before the require, which is exactly the question "does this precondition already hold here?".
    • checkContainerUnwrap

      void checkContainerUnwrap(EK9Parser.ObjectAccessExpressionContext ctx)
      Count each container unwrap (Optional.get / Result.ok/error / Iterator.next) in an object-access chain as a CONTAINER_UNWRAP obligation, GUARD-discharged when the access is safe. Delegates the chain walk + guard decision to ContainerUnwrapObligations, which reuses the same predicates as the E08030 checker.
    • checkConstrainedConstruction

      void checkConstrainedConstruction(EK9Parser.CallContext ctx)
      Count a constrained-type construction (Age(expr) for Age constrain as ...) as a CONSTRAINED_CONSTRUCTION obligation — a construction-time Panic risk. Discharged only when the argument is a literal the compile-time evaluator proves inside the interval; a computed argument stays undischarged (the Layer-2 candidate). Reuses ConstrainedConstructionResolver — the same site definition the E07xxx checker uses.