iris


https://plv.mpi-sws.org/coqdoc/iris/index.html https://plv.mpi-sws.org/semantics-course/

Iris

NONEV and SOMEV

  • Both are val values.
  • val counterparts of SOME and NONE
Notation NONEV := (InjLV #())
Notation SOMEV x := (InjRV x)

InjLV itself is a constructor of val type:

Inductive expr : Set :=
    Val : val → expr
  | Var : string → expr
  | Rec : binder → binder → expr → expr
  | App : expr → expr → expr
  | UnOp : un_op → expr → expr
  | BinOp : bin_op → expr → expr → expr
  | If : expr → expr → expr → expr
  | Pair : expr → expr → expr
  | Fst : expr → expr
  | Snd : expr → expr
  | InjL : expr → expr
  | InjR : expr → expr
  | Case : expr → expr → expr → expr
  | AllocN : expr → expr → expr
  | Free : expr → expr
  | Load : expr → expr
  | Store : expr → expr → expr
  | CmpXchg : expr → expr → expr → expr
  | Xchg : expr → expr → expr
  | FAA : expr → expr → expr
  | Fork : expr → expr
  | NewProph : expr
  | Resolve : expr → expr → expr → expr
  with val : Set :=
    LitV : base_lit → val
  | RecV : binder → binder → expr → val
  | PairV : val → val → val
  | InjLV : val → val
  | InjRV : val → val.

Concurrency

  • Fork e: create a new thread to run e
    • e is run only for its side effects. Its return value cannot be used
    • Fork is the only primitive for concurrency in HeapLang
  • spawn: takes a thunk that will be executed in a new thread
    • A handle to the return value of this execution is returned
    • This handle can be awaited upon with spawn.join
  • par: Run two threads in parallel
    • Needs From iris.heap_lang Require Import lib.par
    • Defined in terms of spawn ??
    • e1 ||| e2 is notation for par e1 e2
    • Result will be a pair, consisting of return values from running e1 and e2

Iris Proof Mode (IPM)

https://gitlab.mpi-sws.org/iris/iris/blob/master/docs/proof_mode.md

  • Involves an extra context named spatial context
    • This is in addition to the 'normal' context, called non-spatial context in iris.
  • iris tactics tailored to work also with spatial context start with i
    • Eg: iIntros "H" instead of intros H
    • Eg: iApply "H" instead of apply H
  • Start IPM: iStartProof
    • Many iris tactics will automatically start IPM though.
  • https://github.com/izgzhen/iris-coq/blob/master/ProofMode.md

Arrays:

Rules

P1 ⊢ Q1      P2 ⊢ Q2
----------------------
  P1 ∗ P2 ⊢ Q1 ∗ Q2

  {P} e {w. Q}
---------------- Frame rule
{P*R} e {w. Q*R}


------------------ Val
{True} v {w. w==v}


---------------------- Alloc
{True} ref(v) {l. l↦v}


------------------------ Load
{l↦v} !l {w. w==v * l↦v}


--------------- Store
{l↦v} l←w {l↦w}

Relevance of frame rule:

  • It says that if a computation proceeded without involvement of a resource, it will still go correctly with its involvement.
  • Helps us to compose disjoint computations together.

HeapLang

HeapLang: an ML-like language that comes with iris.

  • Values are prefixed by #
    • Eg: #4, #true
  • Natively supported by HeapLang
    • Integers
    • Booleans
    • Tuples: Fst, Snd
    • Option: SOME, NONE
  • Is untyped ??
    • Eg: if: #true then #() else #false is vaild
  • Variables are strings

Types

  • val
    • Scope: %V
  • expr
    • Scope: %E
  • loc

Functions

Non-recursive:

(* add5 := λx. x+5 *)
λ: "x", "x" + #5 

(* compose := λx. x+5 *)
λ: "f" "g", (λ: "x", "g" ("f" "x"))

Recursive (from here):

Example recursion : expr :=
  let: "fac" :=
    rec: "f" "n" := if: "n" = #0 then #1 else "n" * "f" ("n" - #1)
  in
  ("fac" #4, "fac" #5).

References

  • 'Handles' for dynamically allocated values.
  • A ref use does this:
    1. A location in heap is found for the value
    2. Value is stored in this location
    3. This location is returned
  • Dereference value at a location l: !l
  • Update value at location l with another value v: l <- v
let "v" := ref (#0) in
"v"

Evaluate an expr

  • Use eval with a fuel parameter
  • Eg: eval 10 expvar where 10 is the fuel
  • inl _ if result could be obtained. Otherwise inr _

let expressions

Not native, but available by means of notations that desugars to lambda abstractions.

Example:

let: "a" := #4 in
let: "b" := #2 in
"a" + "b".

Tactics

WP

WP e {{ v, Φ v }} is the weakest precondition such that

  • all executions of the expression e would produce a value v such that Φ v is true
  • φ is a proposition
  • The {{ v, Φ v }} is the post condition

Example from here:

Section Proof.         
  Context `{heapGS Σ}.

Section list.                                     
  Context `{heapGS Σ}.                            

  Example arith : expr := #1 + #2 + #3 + #4 + #5. 

  Lemma arith_spec : ⊢ WP arith {{ v, ⌜v = #15⌝ }}. 
  Proof.                                            
    unfold arith.                                   
    by wp_pures.                                    
  Qed.                                              
End Proof.

{{{ P }}} e {{{ RET v, Q }}}

desugars to

∀ Φ, P -∗ (Q -∗ Φ v) -∗ WP e {{ v, Φ v }}

This is logically equivalent to

P -∗ WP e {{ x, x = v ∗ Q }}

WP tactics

https://gitlab.mpi-sws.org/iris/iris/-/blob/master/docs/heap_lang.md#tactics

These tactics work when goal is like WP e @ E {{ Q }} ??

  • wplam: removes λ:
    • Does application. ie, beta-reduction
  • wprec: similar to wplam, but for recursive function
  • wplet: zeta-reduction (ie, substitutes let var with its definition)
  • wpload: substitute !x with v if there is a x ↦ v in assumption
  • wpstore: move a p <- v to context as p ↦ v
  • wpseq: reduce a sequential composition
  • wpalloc
  • wppair
  • wpfork
  • wpapply
  • wpsmartapply
  • wpbind
  • wppures
  • wpcmpxchgsuc, wpcmpxchgfail
  • wpfaa
  • wpproj
  • wpinj
  • wpmatch, wpcase
  • wpunop, wpbinop, wpop: reduce unary, binary or other arithmetic operation
  • wppure: kind of like 'auto' for wp tactics
  • wppures: do wppure as many times as possible
  1. wplam

    "Hx" : x ↦ v1
    "Hy" : y ↦ v2
    "Post" : ▷ (x ↦ v2 ∗ y ↦ v1 -∗ Φ #())
    --------------------------------------∗
    WP (λ: "x" "y", let: "tmp" := ! "x" in "x" <- "y";; "y" <- "tmp")%V #x #y
    {{ v, Φ v }}
    

    becomes

    "Hx" : x ↦ v1
    "Hy" : y ↦ v2
    "Post" : x ↦ v2 ∗ y ↦ v1 -∗ Φ #()
    --------------------------------------∗
    WP let: "y" := #y in let: "tmp" := ! #x in #x <- "y";; "y" <- "tmp"
    {{ v, Φ v }}
    
  2. wpstore

    --------------------------------------□
    "Hp" : p ↦ (#x, v)
    "Hl" : is_list l v
    "Post" : (∃ p0 : loc, ⌜InjRV #p = InjRV #p0⌝ ∗
                ∃ v' : val, p0 ↦ (#(n + x), v') ∗ is_list (map (Z.add n) l) v') -∗
             Φ #()
    --------------------------------------∗
    WP #p <- (#x + #n, v);; inc_list #n v {{ v, Φ v }}
    

    becomes

    --------------------------------------□
    "Hp" : p ↦ (#(x + n), v)
    "Hl" : is_list l v
    "Post" : (∃ p0 : loc, ⌜InjRV #p = InjRV #p0⌝ ∗
                ∃ v' : val, p0 ↦ (#(n + x), v') ∗ is_list (map (Z.add n) l) v') -∗
             Φ #()
    --------------------------------------∗
    WP inc_list #n v {{ v, Φ v }}
    

Interpreter (experimental)

  • A heaplang interpreter is available as part of the iris_unstable package.
    • This package contains iris stuff that is not considered ready for release.
  • This interpreter is only development version and is not part of standard release.
  • Use via exec function with a fuel parameter:
    • Eg: Compute (exec 10 exprn)

Misc

Doubts

  • Meaning of %->
  • Meaning of |={⊤}=>

Seperation Logic

Dbt