Documentation

Std.WP.Gadget.ForIn

forIn loop-invariant gadgets #

forInPureWithInvariant and forInPureWithInvariant' annotate a forIn/forIn' loop with its invariant so that vcgen reads the invariant from the program. Their @[spec] specifications restate Spec.forIn_list/Spec.forIn'_list for every container with a PureForIn instance.

forInLoopWithInvariant, forInLoopWithVariant and forInLoopWithInvariantAndVariant do the same for a repeat loop, one per set of annotations the loop states. Each restates Spec.forIn_loop, leaving what the loop does not state to vcgen to infer.

Gadgets #

@[inline]
def Std.WP.Gadget.forInPureWithInvariant {α : Type u₁} {β : Type (max u₁ u₂)} {m : Type (max u₁ u₂) → Type v} {Pred : Type (max u₁ u₂)} {ρ : Type w} [ForIn m ρ α] (xs : ρ) (init : β) (f : αβm (ForInStep β)) (inv : Invariant α β Pred) :
m β

A forIn loop annotated with its loop invariant, which vcgen reads from the inv argument. It is definitionally forIn xs init f, so the annotation is erased at runtime. The invariant ranges over the elements consumed so far, the elements remaining, and the loop state.

Equations
Instances For
    @[inline]
    def Std.WP.Gadget.forInPureWithInvariant' {α : Type u₁} {β : Type (max u₁ u₂)} {m : Type (max u₁ u₂) → Type v} {Pred : Type (max u₁ u₂)} {ρ : Type w} {d : Membership α ρ} [ForIn' m ρ α d] (xs : ρ) (init : β) (f : (a : α) → a xsβm (ForInStep β)) (inv : Invariant α β Pred) :
    m β

    A membership-aware forIn' loop annotated with its loop invariant, which vcgen reads from the inv argument. It is definitionally forIn' xs init f, so the annotation is erased at runtime. The invariant ranges over the elements consumed so far, the elements remaining, and the loop state.

    Equations
    Instances For

      Specifications #

      theorem Std.WP.Spec.forInPure {α : Type u₁} {β : Type (max u₁ u₂)} {m : Type (max u₁ u₂) → Type v} {Pred EPred : Type (max u₁ u₂)} [Monad m] [Assertion Pred] [Assertion EPred] [WPMonad m Pred EPred] {ρ : Type w} [ForIn m ρ α] [ForIn Id ρ α] [Internal.PureForIn m ρ α] {xs : ρ} {init : β} {f : αβm (ForInStep β)} (inv : Invariant α β Pred) {epost : EPred} (step : ∀ (pref : List α) (cur : α) (suff : List α), ForIn.toList xs = pref ++ cur :: suff∀ (b : β), binderNameHint pref inv (binderNameHint suff (inv pref) (binderNameHint cur f (binderNameHint b (inv pref (cur :: suff)) (inv pref (cur :: suff) b)))) f cur b fun (r : ForInStep β) => match r with | ForInStep.yield b' => inv (pref ++ [cur]) suff b' | ForInStep.done b' => inv (ForIn.toList xs) [] b'; epost ) :
      inv [] (ForIn.toList xs) init Gadget.forInPureWithInvariant xs init f inv fun (b : β) => binderNameHint b (inv (ForIn.toList xs) []) (inv (ForIn.toList xs) [] b); epost
      theorem Std.WP.Spec.forInPure' {α : Type u₁} {β : Type (max u₁ u₂)} {m : Type (max u₁ u₂) → Type v} {Pred EPred : Type (max u₁ u₂)} [Monad m] [Assertion Pred] [Assertion EPred] [WPMonad m Pred EPred] {ρ : Type w} {d : Membership α ρ} [ForIn' m ρ α d] [ForIn Id ρ α] [Internal.LawfulMemForInId ρ α] [Internal.PureForIn' m ρ α] {xs : ρ} {init : β} {f : (a : α) → a xsβm (ForInStep β)} (inv : Invariant α β Pred) {epost : EPred} (step : ∀ (pref : List α) (cur : α) (suff : List α) (h : ForIn.toList xs = pref ++ cur :: suff) (b : β), binderNameHint pref inv (binderNameHint suff (inv pref) (binderNameHint cur f (binderNameHint b (inv pref (cur :: suff)) (inv pref (cur :: suff) b)))) f cur b fun (r : ForInStep β) => match r with | ForInStep.yield b' => inv (pref ++ [cur]) suff b' | ForInStep.done b' => inv (ForIn.toList xs) [] b'; epost ) :
      inv [] (ForIn.toList xs) init Gadget.forInPureWithInvariant' xs init f inv fun (b : β) => binderNameHint b (inv (ForIn.toList xs) []) (inv (ForIn.toList xs) [] b); epost
      @[inline]
      def Std.WP.Gadget.forInLoopWithInvariant {β : Type u} {m : Type u → Type v} {Pred : Type uₚ} [Monad m] (l : Lean.Loop) (init : β) (f : Unitβm (ForInStep β)) (inv : WhileInvariant β Pred) :
      m β

      A repeat loop annotated with the loop invariant that vcgen reads from the inv argument. It is definitionally forIn l init f, so the annotation is erased at runtime. The invariant takes the loop's exit flag, false while the loop iterates and true once it is done.

      Equations
      Instances For
        @[inline]
        def Std.WP.Gadget.forInLoopWithVariant {β : Type u} {m : Type u → Type v} {Fun : Type} [Monad m] (l : Lean.Loop) (init : β) (f : Unitβm (ForInStep β)) (var : βFun) :
        m β

        A repeat loop annotated with the termination measure that vcgen reads from the var argument. It is definitionally forIn l init f, so the annotation is erased at runtime. The measure is the function a Variant is built from, so that the assertion language it evaluates in is the one the specification is applied at.

        Equations
        Instances For
          @[inline]
          def Std.WP.Gadget.forInLoopWithInvariantAndVariant {β : Type u} {m : Type u → Type v} {Pred : Type uₚ} {Fun : Type} [Monad m] (l : Lean.Loop) (init : β) (f : Unitβm (ForInStep β)) (inv : WhileInvariant β Pred) (var : βFun) :
          m β

          A repeat loop annotated with the loop invariant and the termination measure that vcgen reads from the inv and var arguments. It is definitionally forIn l init f, so the annotations are erased at runtime. The invariant takes the loop's exit flag, false while the loop iterates and true once it is done. The measure is the function a Variant is built from, so that the assertion language it evaluates in is the one the specification is applied at.

          Equations
          Instances For
            theorem Std.WP.Spec.forInLoop_invariant_variant {β : Type u} {m : Type u → Type v} {Pred : Type uₚ} {EPred : Type uₑ} [Monad m] [Lean.Order.MonadTail m] [Assertion Pred] [Assertion EPred] [WPMonad m Pred EPred] {Fun : Type} {γ : Type uγ'} {l : Lean.Loop} {init : β} {f : Unitβm (ForInStep β)} [Assertion.NondetFun Pred Fun γ] [WellFoundedRelation γ] [∀ (P : Pred), Lean.Order.PreservesSup (Lean.Order.meet P)] (measure : βFun) (inv : BoolβPred) (einv : EPred) (step : ∀ (b : β) (mb : γ), binderNameHint b (inv false) (Lean.Order.meet ((Variant.ofMeasure measure).EvalsTo b mb) (inv false b)) f () b fun (r : ForInStep β) => match r with | ForInStep.yield b' => Lean.Order.meet ((Variant.ofMeasure measure).EvalsBelow b' mb) (inv false b') | ForInStep.done b' => inv true b'; einv ) :
            inv false init Gadget.forInLoopWithInvariantAndVariant l init f (WhileInvariant.mk inv) measure fun (b : β) => binderNameHint b (inv true) (inv true b); einv
            theorem Std.WP.Spec.forInLoop_invariant {β : Type u} {m : Type u → Type v} {Pred : Type uₚ} {EPred : Type uₑ} [Monad m] [Lean.Order.MonadTail m] [Assertion Pred] [Assertion EPred] [WPMonad m Pred EPred] {l : Lean.Loop} {init : β} {f : Unitβm (ForInStep β)} [∀ (P : Pred), Lean.Order.PreservesSup (Lean.Order.meet P)] (measure : Variant β Pred) (inv : BoolβPred) (einv : EPred) (step : ∀ (b : β) (mb : measure.γ), binderNameHint b (inv false) (Lean.Order.meet (measure.EvalsTo b mb) (inv false b)) f () b fun (r : ForInStep β) => match r with | ForInStep.yield b' => Lean.Order.meet (measure.EvalsBelow b' mb) (inv false b') | ForInStep.done b' => inv true b'; einv ) :
            inv false init Gadget.forInLoopWithInvariant l init f (WhileInvariant.mk inv) fun (b : β) => binderNameHint b (inv true) (inv true b); einv
            theorem Std.WP.Spec.forInLoop_variant {β : Type u} {m : Type u → Type v} {Pred : Type uₚ} {EPred : Type uₑ} [Monad m] [Lean.Order.MonadTail m] [Assertion Pred] [Assertion EPred] [WPMonad m Pred EPred] {Fun : Type} {γ : Type uγ'} {l : Lean.Loop} {init : β} {f : Unitβm (ForInStep β)} [Assertion.NondetFun Pred Fun γ] [WellFoundedRelation γ] [∀ (P : Pred), Lean.Order.PreservesSup (Lean.Order.meet P)] (measure : βFun) (inv : WhileInvariant β Pred) (einv : EPred) (step : ∀ (b : β) (mb : γ), binderNameHint b (inv false) (Lean.Order.meet ((Variant.ofMeasure measure).EvalsTo b mb) (inv false b)) f () b fun (r : ForInStep β) => match r with | ForInStep.yield b' => Lean.Order.meet ((Variant.ofMeasure measure).EvalsBelow b' mb) (inv false b') | ForInStep.done b' => inv true b'; einv ) :
            inv false init Gadget.forInLoopWithVariant l init f measure fun (b : β) => binderNameHint b (inv true) (inv true b); einv