Skip to content
Snippets Groups Projects
Commit fcc95c24 authored by Ralf Jung's avatar Ralf Jung
Browse files

Merge branch 'ralf/gen-exercises' into 'master'

Auto-generate exercise files

Closes #4

See merge request !4
parents ae3bead2 a6c95521
Branches
No related tags found
1 merge request!4Auto-generate exercise files
Pipeline #33203 failed
......@@ -26,7 +26,11 @@ _*_.tex
*.glob
*.v.d
*.vio
Makefile.coq*
*.vos
*.vok
Makefile.coq
Makefile.coq.conf
.Makefile.coq.d
*.crashcoqide
.coqdeps.d
build-dep
......
......@@ -5,6 +5,7 @@ stages:
variables:
CPU_CORES: "10"
MAKE_TARGET: "ci"
.template: &template
stage: build
......@@ -40,7 +41,7 @@ build-coq.8.10.1:
build-iris.dev:
<<: *template
variables:
OPAM_PINS: "coq version 8.11.dev coq-stdpp.dev git git+https://gitlab.mpi-sws.org/iris/stdpp.git#$STDPP_REV coq-iris.dev git git+https://gitlab.mpi-sws.org/iris/iris.git#$IRIS_REV"
OPAM_PINS: "coq version 8.12.dev coq-stdpp.dev git git+https://gitlab.mpi-sws.org/iris/stdpp.git#$STDPP_REV coq-iris.dev git git+https://gitlab.mpi-sws.org/iris/iris.git#$IRIS_REV"
except:
only:
- triggers
......
# Generate an exercise for each solution.
SOLUTIONS := $(wildcard solutions/*.v)
EXERCISES := $(addprefix exercises/,$(notdir $(SOLUTIONS)))
exercises: $(EXERCISES)
.PHONY: exercises
$(EXERCISES): exercises/%.v: solutions/%.v gen-exercises.awk
$(HIDE)echo "Generating exercise file $@ from $<"
$(HIDE)gawk -f gen-exercises.awk < $< > $@
# CI make target
ci: all
+@make -B exercises # force make (in case exercise files have been edited directly)
if [ -n "$$(git status --porcelain)" ]; then echo 'ERROR: Exercise files are not up-to-date with solutions.'; exit 1; fi
......@@ -58,3 +58,35 @@ If you would like to know more about Iris, we recommend to take a look at:
Ralf Jung, Robbert Krebbers, Jacques-Henri Jourdan, Aleš Bizjak, Lars
Birkedal, Derek Dreyer.
A detailed description of the Iris logic and its model
## Generating the exercises
If you want to contribute to the tutorial, note that the files in `exercises/`
are generated from the corresponding files in `solutions/`. Run `make exercises`
to re-generate those files. This requires `gawk` to be installed (which should
usually be available on Linux but might have to be installed separately on
macOS).
The syntax for the solution files is as follows:
```
(* BEGIN SOLUTION *)
solution here.
(* END SOLUTION *)
```
is replaced by
```
(* exercise *)
Admitted.
```
and the more powerful
```
(* BEGIN SOLUTION *)
solution here.
(* END SOLUTION BEGIN TEMPLATE
exercise template here.
END TEMPLATE *)
```
is replaced by
```
exercise template here.
```
......@@ -117,7 +117,7 @@ Lemma rotate_r_spec_again x y z v1 v2 v3 :
rotate_r #x #y #z
{{{ RET #(); x v3 y v1 z v2 }}}.
Proof.
iIntros (Φ) "(Hx & Hy & Hz) Post". wp_lam.
iIntros (Φ) "(Hx & Hy & Hz) Post". wp_lam. do 2 wp_let.
(* We can shorten the above a bit: Instead of using the [iApply] tactic, we
can use [wp_apply] which automatically uses [wp_bind] first. Also, it strips
the later [▷] by calling [iNext] afterwards. *)
......
......@@ -101,7 +101,8 @@ Section proof.
destruct b.
- wp_cmpxchg_fail. iMod ("Hclose" with "[Hl]") as "_".
{ iNext. iExists true. iFrame. }
iModIntro. wp_proj. (* exercise *)
iModIntro. wp_proj.
(* exercise *)
Admitted.
(** *Exercise*: prove the spec of [acquire]. Since [acquire] is a recursive
......
......@@ -36,8 +36,7 @@ Section proof1.
iIntros (Φ) "_ Post".
unfold parallel_add. wp_alloc r as "Hr". wp_let.
wp_apply (newlock_spec (parallel_add_inv_1 r) with "[Hr]").
{ (* exercise *)
admit. }
{ (* exercise *) admit. }
iIntros (l) "#Hl". wp_let.
wp_apply (wp_par (λ _, True%I) (λ _, True%I)).
- wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n) "[Hr %]".
......@@ -105,8 +104,7 @@ Section proof2.
iMod (ghost_var_alloc 0) as (γ1) "[Hγ1● Hγ1◯]".
iMod (ghost_var_alloc 0) as (γ2) "[Hγ2● Hγ2◯]".
wp_apply (newlock_spec (parallel_add_inv_2 r γ1 γ2) with "[Hr Hγ1● Hγ2●]").
{ (* exercise *)
admit. }
{ (* exercise *) admit. }
iIntros (l) "#Hl". wp_let.
wp_apply (wp_par (λ _, own γ1 (E 2%Z)) (λ _, own γ2 (E 2%Z))
with "[Hγ1◯] [Hγ2◯]").
......@@ -140,8 +138,7 @@ Section proof3.
iMod (own_alloc (F 0 F 0)) as (γ) "[Hγ● [Hγ1◯ Hγ2◯]]".
{ by apply auth_both_valid. }
wp_apply (newlock_spec (parallel_add_inv_3 r γ) with "[Hr Hγ●]").
{ (* exercise *)
admit. }
{ (* exercise *) admit. }
iIntros (l) "#Hl". wp_let.
wp_apply (wp_par (λ _, own γ (F{1/2} 2)) (λ _, own γ (F{1/2} 2))
with "[Hγ1◯] [Hγ2◯]").
......
......@@ -62,7 +62,7 @@ Section proof.
True%I. (* exercise: replace [True] with something meaningful. *)
Lemma parallel_add_mul_spec :
{{{ True }}} parallel_add_mul {{{ z, RET #z; z = 2 z = 4 }}}.
{{{ True }}} parallel_add_mul {{{ z, RET #z; z = 2%Z z = 4%Z }}}.
Proof.
(* exercise *)
Admitted.
......
BEGIN {
in_solution = 0;
}
{ # on every line of the input
if (match($0, /^( *)\(\* *BEGIN SOLUTION *\*\)$/, groups)) {
in_solution = 1
} else if (match($0, /^( *)\(\* *END SOLUTION *\*\)$/, groups)) {
print groups[1] " (* exercise *)"
print groups[1] "Admitted."
in_solution = 0
} else if (match($0, /^( *)\(\* *END SOLUTION BEGIN TEMPLATE *$/, groups)) {
in_solution = 0
} else if (match($0, /^( *)END TEMPLATE *\*\)$/, groups)) {
# Nothing to do, just do not print this line.
} else if (in_solution == 0) {
gsub("From solutions Require", "From exercises Require")
print
}
}
......@@ -137,9 +137,11 @@ Lemma rotate_l_spec x y z v1 v2 v3 :
rotate_l #x #y #z
{{{ RET #(); x v2 y v3 z v1 }}}.
Proof.
(* BEGIN SOLUTION *)
iIntros (Φ) "(Hx & Hy & Hz) Post". unfold rotate_l. wp_lam. do 2 wp_let.
wp_apply (swap_spec with "[$Hx $Hy]"); iIntros "[Hx Hy]"; wp_seq.
wp_apply (swap_spec with "[$Hy $Hz]"); iIntros "[Hy Hz]".
iApply ("Post" with "[$]").
Qed.
(* END SOLUTION *)
End proof.
......@@ -117,6 +117,7 @@ Lemma inc_list_spec_induction n l v :
inc_list #n v
{{{ RET #(); is_list (map (Z.add n) l) v }}}.
Proof.
(* BEGIN SOLUTION *)
iIntros (Φ) "Hl Post".
iInduction l as [|x l] "IH" forall (v Φ); simpl.
- iDestruct "Hl" as %->.
......@@ -133,6 +134,7 @@ Proof.
iExists p. iSplitR; [done|].
iExists v. iSplitR "Hl"; [iApply "Hp"|iApply "Hl"].
Qed.
(* END SOLUTION *)
(** *Exercise*: Now do the proof again using Löb induction. *)
Lemma inc_list_spec_löb n l v :
......@@ -140,6 +142,7 @@ Lemma inc_list_spec_löb n l v :
inc_list #n v
{{{ RET #(); is_list (map (Z.add n) l) v }}}.
Proof.
(* BEGIN SOLUTION *)
iIntros (Φ) "Hl Post".
iLöb as "IH" forall (l v Φ). destruct l as [|x l]; simpl; wp_rec; wp_let.
- iDestruct "Hl" as %->. wp_match. by iApply "Post".
......@@ -148,6 +151,7 @@ Proof.
wp_apply ("IH" with "Hl"). iIntros "Hl".
iApply "Post". eauto with iFrame.
Qed.
(* END SOLUTION *)
(** *Exercise*: Do the proof of [sum_inc_list] by making use of the lemmas of
[sum_list] and [inc_list] we just proved. Make use of [wp_apply]. *)
......@@ -156,10 +160,12 @@ Lemma sum_inc_list_spec n l v :
sum_inc_list #n v
{{{ RET #(sum_list_coq (map (Z.add n) l)); is_list (map (Z.add n) l) v }}}.
Proof.
(* BEGIN SOLUTION *)
iIntros (Φ) "Hl Post". wp_lam. wp_let.
wp_apply (inc_list_spec_induction with "Hl"); iIntros "Hl /="; wp_seq.
wp_apply (sum_list_spec_induction with "Hl"); auto.
Qed.
(* END SOLUTION *)
(** *Optional exercise*: Prove the following spec of [map_list] which makes use
of a nested Texan triple, This spec is rather weak, as it requires [f] to be
......@@ -168,6 +174,7 @@ Lemma map_list_spec_induction (f : val) (f_coq : Z → Z) l v :
( n, {{{ True }}} f #n {{{ RET #(f_coq n); True }}}) -∗
{{{ is_list l v }}} map_list f v {{{ RET #(); is_list (map f_coq l) v }}}.
Proof.
(* BEGIN SOLUTION *)
iIntros "#Hf" (Φ) "!# Hl Post".
iLöb as "IH" forall (l v Φ). destruct l as [|x l]; simpl; wp_rec; wp_let.
- iDestruct "Hl" as %->. wp_match. by iApply "Post".
......@@ -178,4 +185,5 @@ Proof.
wp_apply ("IH" with "Hl"). iIntros "Hl".
iApply "Post". eauto with iFrame.
Qed.
(* END SOLUTION *)
End proof.
......@@ -101,12 +101,15 @@ Section proof.
destruct b.
- wp_cmpxchg_fail. iMod ("Hclose" with "[Hl]") as "_".
{ iNext. iExists true. iFrame. }
iModIntro. wp_proj. iApply ("HΦ" $! false). done.
iModIntro. wp_proj.
(* BEGIN SOLUTION *)
iApply ("HΦ" $! false). done.
- (* Exercise *) wp_cmpxchg_suc.
iMod ("Hclose" with "[Hl]") as "_".
{ iNext. iExists true. iFrame. }
iModIntro. wp_proj. by iApply ("HΦ" $! true with "HR").
Qed.
(* END SOLUTION *)
(** *Exercise*: prove the spec of [acquire]. Since [acquire] is a recursive
function, you should use the tactic [iLöb] for Löb induction. Use the tactic
......@@ -114,11 +117,13 @@ Section proof.
Lemma acquire_spec lk R :
{{{ is_lock lk R }}} acquire lk {{{ RET #(); R }}}.
Proof.
(* BEGIN SOLUTION *)
iIntros (Φ) "#Hl HΦ". iLöb as "IH". wp_rec.
wp_apply (try_acquire_spec with "Hl"). iIntros ([]).
- iIntros "HR". wp_if. by iApply "HΦ".
- iIntros "_". wp_if. iApply ("IH" with "HΦ").
Qed.
(* END SOLUTION *)
(** *Exercise*: prove the spec of [release]. At a certain point in this proof,
you need to open the invariant. For this you can use:
......@@ -130,9 +135,11 @@ Section proof.
Lemma release_spec lk R :
{{{ is_lock lk R R }}} release lk {{{ RET #(); True }}}.
Proof.
(* BEGIN SOLUTION *)
iIntros (Φ) "(Hlock & HR) HΦ".
iDestruct "Hlock" as (l ->) "#Hinv /=".
wp_lam. iInv lockN as (b) "[Hl _]" "Hclose".
wp_store. iApply "HΦ". iApply "Hclose". iNext. iExists false. iFrame.
Qed.
(* END SOLUTION *)
End proof.
......@@ -36,23 +36,33 @@ Section proof1.
iIntros (Φ) "_ Post".
unfold parallel_add. wp_alloc r as "Hr". wp_let.
wp_apply (newlock_spec (parallel_add_inv_1 r) with "[Hr]").
{ (* exercise *) iExists 0. iFrame. }
(* BEGIN SOLUTION *)
{ iExists 0. iFrame. }
(* END SOLUTION BEGIN TEMPLATE
{ (* exercise *) admit. }
END TEMPLATE *)
iIntros (l) "#Hl". wp_let.
wp_apply (wp_par (λ _, True%I) (λ _, True%I)).
- wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n) "[Hr %]".
wp_seq. wp_load. wp_op. wp_store.
wp_apply (release_spec with "[Hr $Hl]"); [|done].
iExists _. iFrame "Hr". iPureIntro. by apply Zeven_plus_Zeven.
- (* exercise *)
wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n) "[Hr %]".
(* BEGIN SOLUTION *)
- wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n) "[Hr %]".
wp_seq. wp_load. wp_op. wp_store.
wp_apply (release_spec with "[Hr $Hl]"); [|done].
iExists _. iFrame "Hr". iPureIntro. by apply Zeven_plus_Zeven.
- (* exercise *)
iIntros (v1 v2) "_ !>". wp_seq.
- iIntros (v1 v2) "_ !>". wp_seq.
wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n) "[Hr %]".
wp_seq. wp_load. by iApply "Post".
Qed.
(* END SOLUTION BEGIN TEMPLATE
- (* exercise *)
admit.
- (* exercise *)
admit.
Admitted.
END TEMPLATE *)
End proof1.
(** 2nd proof : we prove that the program returns 4 exactly.
......@@ -62,7 +72,7 @@ Whereas we previously abstracted over an arbitrary "ghost state" [Σ] in the
proofs, we now need to make sure that we can use integer ghost variables. For
this, we add the type class constraint:
inG Σ (authR (optionUR (exclR ZO)))
inG Σ (excl_authR ZO)
*)
......@@ -109,7 +119,11 @@ Section proof2.
iMod (ghost_var_alloc 0) as (γ1) "[Hγ1● Hγ1◯]".
iMod (ghost_var_alloc 0) as (γ2) "[Hγ2● Hγ2◯]".
wp_apply (newlock_spec (parallel_add_inv_2 r γ1 γ2) with "[Hr Hγ1● Hγ2●]").
{ (* exercise *) iExists 0, 0. iFrame. }
(* BEGIN SOLUTION *)
{ iExists 0, 0. iFrame. }
(* END SOLUTION BEGIN TEMPLATE
{ (* exercise *) admit. }
END TEMPLATE *)
iIntros (l) "#Hl". wp_let.
wp_apply (wp_par (λ _, own γ1 (E 2%Z)) (λ _, own γ2 (E 2%Z))
with "[Hγ1◯] [Hγ2◯]").
......@@ -119,21 +133,27 @@ Section proof2.
iMod (ghost_var_update γ1 2 with "Hγ1● Hγ1◯") as "[Hγ1● Hγ1◯]".
wp_apply (release_spec with "[- $Hl Hγ1◯]"); [|by auto].
iExists _, _. iFrame "Hγ1● Hγ2●". rewrite (_ : 2 + n2 = 0 + n2 + 2)%Z; [done|ring].
- (* exercise *)
wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n1 n2) "(Hr & Hγ1● & Hγ2●)".
(* BEGIN SOLUTION *)
- wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n1 n2) "(Hr & Hγ1● & Hγ2●)".
wp_seq. wp_load. wp_op. wp_store.
iDestruct (ghost_var_agree with "Hγ2● Hγ2◯") as %->.
iMod (ghost_var_update γ2 2 with "Hγ2● Hγ2◯") as "[Hγ2● Hγ2◯]".
wp_apply (release_spec with "[- $Hl Hγ2◯]"); [|by auto].
iExists _, _. iFrame "Hγ1● Hγ2●". by rewrite -Z.add_assoc.
- (* exercise *)
iIntros (??) "[Hγ1◯ Hγ2◯] !>". wp_seq.
- iIntros (??) "[Hγ1◯ Hγ2◯] !>". wp_seq.
wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n1 n2) "(Hr & Hγ1● & Hγ2●)".
wp_seq. wp_load.
iDestruct (ghost_var_agree with "Hγ1● Hγ1◯") as %->.
iDestruct (ghost_var_agree with "Hγ2● Hγ2◯") as %->.
by iApply "Post".
Qed.
(* END SOLUTION BEGIN TEMPLATE
- (* exercise *)
admit.
- (* exercise *)
admit.
Admitted.
END TEMPLATE *)
End proof2.
(** 3rd proof : we prove that the program returns 4 exactly, but using a
......@@ -153,7 +173,11 @@ Section proof3.
iMod (own_alloc (F 0 F 0)) as (γ) "[Hγ● [Hγ1◯ Hγ2◯]]".
{ by apply auth_both_valid. }
wp_apply (newlock_spec (parallel_add_inv_3 r γ) with "[Hr Hγ●]").
{ (* exercise *) iExists 0. iFrame. }
(* BEGIN SOLUTION *)
{ iExists 0. iFrame. }
(* END SOLUTION BEGIN TEMPLATE
{ (* exercise *) admit. }
END TEMPLATE *)
iIntros (l) "#Hl". wp_let.
wp_apply (wp_par (λ _, own γ (F{1/2} 2)) (λ _, own γ (F{1/2} 2))
with "[Hγ1◯] [Hγ2◯]").
......@@ -164,19 +188,25 @@ Section proof3.
by apply frac_auth_update, (op_local_update_discrete n 0 2). }
wp_apply (release_spec with "[$Hl Hr Hγ●]"); [|by auto].
iExists _. iFrame. by rewrite Nat2Z.inj_add.
- (* exercise *)
wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n) "[Hr Hγ●]".
(* BEGIN SOLUTION *)
- wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n) "[Hr Hγ●]".
wp_seq. wp_load. wp_op. wp_store.
iMod (own_update_2 _ _ _ (F (n+2) F{1/2}2) with "Hγ● Hγ2◯") as "[Hγ● Hγ2◯]".
{ rewrite (comm plus).
by apply frac_auth_update, (op_local_update_discrete n 0 2). }
wp_apply (release_spec with "[- $Hl Hγ2◯]"); [|by auto].
iExists _. iFrame. by rewrite Nat2Z.inj_add.
- (* exercise *)
iIntros (??) "[Hγ1◯ Hγ2◯] !>". wp_seq.
- iIntros (??) "[Hγ1◯ Hγ2◯] !>". wp_seq.
wp_apply (acquire_spec with "Hl"). iDestruct 1 as (n) "(Hr & Hγ●)".
wp_seq. wp_load. iCombine "Hγ1◯ Hγ2◯" as "Hγ◯".
iDestruct (own_valid_2 with "Hγ● Hγ◯") as %->%frac_auth_agreeL.
by iApply "Post".
Qed.
(* END SOLUTION BEGIN TEMPLATE
- (* exercise *)
admit.
- (* exercise *)
admit.
Admitted.
END TEMPLATE *)
End proof3.
......@@ -59,6 +59,7 @@ Section proof.
and the rules for those as given above. You are allowed to use any number of
Boolean ghost variables. *)
Definition parallel_add_mul_inv (r : loc) (γ1 γ2 : gname) : iProp Σ :=
(* BEGIN SOLUTION *)
( (b1 b2 : bool) (z : Z),
own γ1 (E b1) own γ2 (E b2) r #z
match b1, b2 with
......@@ -66,10 +67,14 @@ Section proof.
| true, false => z = 2
| false, _ => z = 0
end)%I.
(* END SOLUTION BEGIN TEMPLATE
True%I. (* exercise: replace [True] with something meaningful. *)
END TEMPLATE *)
Lemma parallel_add_mul_spec :
{{{ True }}} parallel_add_mul {{{ z, RET #z; z = 2%Z z = 4%Z }}}.
Proof.
(* BEGIN SOLUTION *)
iIntros (Φ) "_ Post".
unfold parallel_add_mul. wp_alloc r as "Hr". wp_let.
iMod (ghost_var_alloc false) as (γ1) "[Hγ1● Hγ1◯]".
......@@ -102,4 +107,5 @@ Section proof.
iDestruct (ghost_var_agree with "Hγ2● Hγ2◯") as %->.
auto.
Qed.
(* END SOLUTION *)
End proof.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment