From iris.base_logic Require Import iprop.
From iris.proofmode Require Import proofmode.
From iris.heap_lang Require Import lang proofmode notation par.
Set Default Goal Selector "!".

Section hw5.

Context `{!heapGS Σ}.

(* 2 points *)
Lemma sep_assoc_1 (P Q R : iProp Σ) : P ∗ (Q ∗ R) ⊢ (P ∗ Q) ∗ R.
Proof.
  (* exercise *)
Admitted.

(* 2 points *)
Lemma sep_ex_distr {A} (P : iProp Σ) (Φ : A → iProp Σ) :
  (P ∗ ∃ x, Φ x) ⊣⊢ ∃ x, P ∗ Φ x.
Proof.
  (* exercise *)
Admitted.

(* 3 points *)
Lemma iApply_exercise : forall (P Q R S : iProp Σ),
  (P ∗ Q) ∗ R ∗ (P -∗ (Q ∗ R) -∗ S) ⊢ S.
Proof.
  (* exercise *)
Admitted.

Definition arith2 : expr :=
  let: "x" := #1 + #2 * #3 in
  let: "y" := #4 * #5 in
  "y" - "x".

(* 2 points *)
Lemma arith2_spec : ⊢ WP arith2 {{ v, ⌜v = #13⌝ }}.
Proof.
  (* exercise *)
Admitted.

Definition double : val :=
  λ: "x",
  let: "v" := !"x" in
  "x" <- #2 * "v".

(* 3 points *)
Lemma double_spec (l : loc) (v : Z) :
  {{{ l ↦ #v }}}
    double #l
  {{{ RET #(); l ↦ #(2 * v) }}}.
Proof.
  (* exercise *)
Admitted.

(* 3 points *)
(* Consider the following program: *)
Definition is_gt_5 : val :=
  λ: "x",
  let: "v" := !"x" in
  if: #5 < "v" then #1 else #0.

(* Write a specification for [is_gt_5], in the form of a lemma stating
   a pre- and postcondition for it. You don't have to prove the lemma,
   but you should try to get it to typecheck. *)
(** Lemma is_gt_5_spec : ...
  Admitted. *)

(* grad exercise *)
(** Write and prove a specification for the following program: *)
Definition alloc_sum : val :=
  λ: "x" "y",
  let: "r" := ref (!"x" + !"y") in
  "r".

End hw5.
