A program logic for higher-order procedural variables and non-local jumps
Relying on the formulae-as-types paradigm for classical logic, we define a program logic for an imperative language with higher-order procedural variables and non-local jumps. Then, we show how to derive a sound program logic for this programming language. As a by-product, we obtain a non-dependent type system which is more permissive than what is usually found in statically typed imperative languages. As a generic example, we encode imperative versions of delimited continuations operators shift and reset.
💡 Research Summary
The paper presents a formal program logic for an imperative language that simultaneously supports higher‑order procedural variables and non‑local jumps. The authors build the logic on the formulae‑as‑types interpretation of classical logic, where logical formulas serve directly as program types and proof steps correspond to verification steps. This approach allows them to treat pre‑conditions and post‑conditions as logical assertions attached to each command, and to derive Hoare‑style triples from logical inference rules.
The language under study extends a basic imperative core (assignments, conditionals, loops) with first‑class procedures and a jump construct. Procedures can be stored in variables, passed as arguments, and returned as results, thus requiring a higher‑order treatment of contracts. A procedure type is expressed as a pair of contracts {P} proc {Q} where P and Q are pure logical formulas describing the required state before the call and the guaranteed state after the call. When a procedure is passed as an argument, its contract is instantiated at the call site, yielding a higher‑order contract system that remains non‑dependent: the contracts themselves do not depend on runtime values, only on the logical description of the state.
Non‑local jumps are modeled by labeled control points. For each label L the authors associate a “jump invariant” I_L. The rule for a goto L command requires that the current state entails I_L; after the jump the state is assumed to satisfy I_L. This invariant mechanism guarantees that even though control flow can abruptly leave the current stack frame, the overall logical consistency of the program is preserved. The jump rule is integrated with the usual sequential and procedural rules, yielding a unified proof system that can reason about arbitrary interleavings of procedure calls and jumps.
A key contribution is the derivation of a non‑dependent type system from the logic. Types are simply contracts of the form proc(P,Q). Because the system does not rely on dependent types, type checking remains relatively simple, yet it is more permissive than conventional static type systems for imperative languages: programs that would be rejected because of higher‑order procedure manipulation or jumps are accepted as long as the associated contracts can be proved.
To demonstrate the expressive power of the framework, the authors encode delimited continuations—specifically the shift and reset operators—entirely within the imperative language. reset creates a fresh label and records the current continuation as the invariant of that label. shift captures the current continuation by storing a procedure that, when invoked, performs a goto to the saved label. This encoding shows that the logic can faithfully model sophisticated control‑flow abstractions without extending the core language with native continuation constructs.
The soundness of the logic and type system is proved by structural induction on the operational semantics. Each inference rule is shown to preserve the truth of the associated logical assertions, and the jump invariant rule is proved to be compatible with the reduction semantics of jumps. Consequently, any derivable Hoare triple is guaranteed to hold for all reachable program states.
In conclusion, the paper offers a novel synthesis of classical logic, program verification, and advanced imperative features. By treating contracts as non‑dependent types derived from logical formulas, it provides a sound and relatively lightweight framework for reasoning about programs that use higher‑order procedures and non‑local jumps. The work opens avenues for integrating such logics into real‑world compilers, extending them to concurrent settings, and exploring automated verification tools based on the presented proof system.
Comments & Academic Discussion
Loading comments...
Leave a Comment