Hoare Logic for Core #
The structural Hoare rules of Imperative.Logic.Hoare, instantiated for Core directly
over its own language of statement lists, EventLang.coreBlock: there is a single
judgement, Triple, conditioned on Core.Logic.BlockInitEnvWF.
Contents #
Triple, and the rules false_pre, consequence, of_storeWF_pre,
of_forall_entryFactory, cmd, set, init, init_nondet, havoc, assume,
assume_eval, assert, assert_eval, seq, exit_cons, block, skip, ite
and while_rule.
Why the rules are here and not in a HoareProps module #
As in Strata.DL.Imperative.Logic.HoareTemplate: the rules below are the logic rather than
properties of it, so they stay with the judgements they introduce. What does live
separately is the contract integration: ContractToHoareTriple defines the
contract reading, ContractToHoareTripleProps discharges it, and HoareCall
provides the rule for procedure calls.
The denotational domain of Core real is Strata.Util.Real, inherited from
Lambda.SortDenote, so these Hoare judgements state correctness over the real
numbers.
The Core triple #
Core Hoare triple with an explicit event-condition interpretation.
Equations
- Core.Logic.Hoare.TripleWith π conditionInterp params Pre ss Post = Strata.Logic.Hoare.TripleWith (Core.Logic.EventLang.coreBlock π) conditionInterp params Pre ss Post
Instances For
Core Hoare triple over statement lists, with conditions read by evaluation in
runtime factories over factory (DenoteBasedInterp factory). A runtime factory
carries a model of factory, so the triple covers every model through the entry
environments it quantifies over. The default is Core.Factory; program-level
clients can supply the factory visible at a particular declaration.
Equations
- Core.Logic.Hoare.Triple π params Pre ss Post factory = Core.Logic.Hoare.TripleWith π (Core.Logic.DenoteBasedInterp factory) params Pre ss Post
Instances For
Parametric rules #
False precondition proves anything.
Consequence (weakening): strengthen the precondition, weaken the postcondition.
A triple whose precondition also requires a well-formed entry store holds without that requirement: the gate of every admitted entry gives it.
A triple holds when it holds, for every runtime factory E, from the entries whose
runtime factory is E.
Rules for a single command #
A generic single Core command. h receives the full InitEnvWF params (.cmd c) ρ₀,
including the WellFormedSemanticEval bundle that EvalCommandE needs.
Assignment. The value written is quantified inside hpost, next to the evaluation
that produced it: which value e takes depends on the environment, so fixing one
outside would demand that Pre determine it.
Declaration. InitState differs from UpdateState only in requiring the slot to
have been undefined beforehand, which the postcondition never inspects.
Declaration without an initial value. The variable is bound to an arbitrary value of its declared type, which is all the postcondition may rely on.
Havoc. The variable takes an arbitrary value of the type of the value it held, which is all the postcondition may rely on.
Assumption. The store is unchanged, and the postcondition is owed only where the assumed condition holds in some world: an assumption that cannot hold makes the rest of the run unreachable.
Assumption, where the precondition fixes the runtime factory to be over factory:
the assumed condition then holds exactly when it evaluates to true.
Assertion. The store is unchanged, and the asserted condition must hold in every world at every environment the precondition admits.
Assertion, where the precondition fixes the runtime factory to be over factory:
the asserted condition then holds exactly when it evaluates to true.
Structural rules #
Sequencing: glue two triples along the concatenation of their statement lists.
No statement step mutates the factory across the prefix's run, which is what lets
the well-formedness condition be re-established on the suffix; see
Imperative.Logic.Hoare.seq_append for why hnoesc is needed.
An exit ends the statement list where it stands, leaving the
environment untouched, so the precondition survives to the exiting configuration.
The statements after it never run. An enclosing block catches the exit.
Wrap a statement list in a labelled block. Post must not mention the names the
body scopes (PostWF); no statement step mutates the factory across the body, so
leaving the block restores nothing.
Empty block is skip. No lowering condition: the generic rule instantiates
skip_block at the trivial block condition.
If-then-else rule.
While rule. hcov says the body's exits are all caught inside the body,
and hInv_proj that the invariant survives the body block's store
projection.