rocq/theories/CountLogic.v
rocq/programs/count.c through the program logic of Logic.v: a helper with its own specification, called in a loop, with memory read after each call.
next_l is strchr for l. Its triple (next_l_spec) is proved once, from wp_strchr, and count_l uses it at both of its calls through wp_call_bind: once on the whole string, then in the loop on the suffix just past each hit, which the string lends (string_suffix) and takes back after the call. The loop is a Löb induction at the point after its head's phis (count_loop): it owns the string, and the pointer it holds is null or a hit before the NUL (found_from). Each iteration reads the byte the pointer lands on through the string's capability (wp_check_read, wp_raw_load_byte), so the read comes after a call and depends on the callee's postcondition: a hit is before the NUL, because l is not 0.
count_logic_safe is the labelled machine's safety from any memory holding the string; interp_count_logic_safe instantiates it on Hi.v's fixture, whose literal "hello" has two ls.
Integer arithmetic on an unknown stays folded when a premise is computed (Symbolic.v).
The module
The checked module nanofil makes of count.c (count_term).
The fixture decodes to count_module.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The module's i-th function, or an empty one.
next_l: strchr for l.
count_l: the loop.
The module's symbols.
Laying out the module gives count_globals.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
Block l of f, or an empty one.
next_l's one block: strchr, then return its result.
count_l's entry: the first call of next_l.
The loop's head: is the pointer null?
The loop's body: read the byte, count it, call next_l past it.
The exit: return the count.
next_l has its block.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
count_l has its entry.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
count_l has the loop's head.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
count_l has the loop's body.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
count_l has the exit.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
A function called with the pointer p, at its entry.
count_l's contracts: strchr's alone, over no world.
What the loop holds
The pointer q, for the string p with contents bytes, is null or points into it before its NUL, with its capability.
Prove an address premise: drop the wraps of raw_address and of a flight's sum where arithmetic shows them the identity, then arithmetic.
Prove a premise that names words: by computation, with the environment's facts.
What strchr finds of a nonzero byte is null or before the NUL.
Explore proof 3 tactics
Initial goal
intros i & x & Hx & _ & _ & → | _ & → ; right | left ; reflexivity
exists i
split ; exact lookup_lt_Some_ _ _ Hx | reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
What strchr finds in the suffix just past the j-th byte of the string, before its NUL, is null or before the string's NUL.
Explore proof 7 tactics
Initial goal
intros Hj i & x & Hx & _ & _ & → | _ & → ; right | left ; reflexivity
rewrite lookup_drop in Hx
exists Sj + i%nat
split ; exact lookup_lt_Some_ _ _ Hx |
cbn [ ptr_addr ptr_cap ]
f_equal
lia
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
The linked genv: the module, its symbols, R's free.
next_l is a function of the module.
Explore proof 2 tactics
Initial goal
vm_compute
reflexivity
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The Iris instance of count.c: strchr's contract, no world.
The expressions of count.c's language.
next_l's triple: owning the string at p, it returns what strchr finds of l, and hands the string back.
Explore proof 11 tactics
Initial goal
iIntros Hs HΦ
iApply wp_enter ; exact find_n_start | reflexivity |
iNext
cbn [ b_insts b_jump n_start ]
iApply wp_strchr with Hs ; reflexivity | reflexivity | reflexivity | reflexivity | reflexivity | vm_compute ; intuition congruence | vm_compute ; intuition congruence |
iNext
iIntros q Hq Hs
iApply wp_ret ; reflexivity | reflexivity |
iNext
iApply HΦ with [%] Hs
exact Hq
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The loop, from the point after its head's phis: with pr.2 a pointer null or before the NUL of the string at p, which it owns, and pr.1 an int, the run is safe and returns an int. By Löb induction; each iteration reads the byte at the pointer and calls next_l on the suffix past it.
Proof 76 steps Qed
Null: the loop ends and returns the count.
A hit at j: read its byte, count it, and call next_l past it.
count_l, owning the string at p, is safe and returns an int: it calls next_l on the whole string and enters the loop.
Explore proof 21 tactics
Initial goal
iIntros Hs
iApply wp_enter ; exact find_c_start | reflexivity |
iNext
cbn [ b_insts b_jump c_start ]
iApply wp_call_bind ; reflexivity | exact find_next_l | reflexivity |
iNext
iApply next_l_spec with Hs
iNext
iIntros q Hq Hs
iExists _
2 openiSplit ; iPureIntro ; reflexivity |
iNext
cbn [ fr_fn fr_env fr_locals fr_doomed fr_at ]
iApply wp_goto
iNext
iApply wp_enter ; exact find_c_L6 | reflexivity |
iNext
iApply count_loopp b reg bytes with [%] Hs
3 openshelved goal
split ; reflexivity |
2 opensplit ; reflexivity |
exact found_firstp bytes 108 q Hq
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
count_l is safe: from a ready runtime, live objects apart, and a string at p, with any fuel, no labelled run stops with a failure_ending, and a run that returns returns an int. By heap_labelled_safe from count_spec, the ghost heap starting with the string's pieces.
Explore proof 12 tactics
Initial goal
intros Hr Hd Hok Ha
apply heap_labelled_safeΣ count_registry no_world count_ge entrycount_fn p m s tt list_to_mapstring_psp b reg bytes
5 openfocused goal
focused goal
focused goal
focused goal
–exact Hr
4 opendeferred goal
deferred goal
deferred goal
deferred goal
–exact Hd
3 opendeferred goal
deferred goal
deferred goal
–intros l v Hl
3 opendeferred goal
deferred goal
exact all_agree_elem_ _ _ _ Ha elem_of_list_to_map_2_ _ _ Hl
2 opendeferred goal
deferred goal
–exact I
deferred goal
–intros HinvG HheapG
rewrite big_sepM_list_to_map ; | exact string_ps_nodupp b reg bytes
iIntros Hs
iApply count_specp b reg bytes with [$Hs]
done
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.
Source script
The interpreter's runtime
count.c over the interpreter's runtime.
count_l is safe under the interpreter's runtime, called with Hi.v's literal "hello" in Hi.v's fixture memory.
Explore proof 9 tactics
Initial goal
intros fuel
destruct HiChecks.entry_pre as _ & _ & Hv
apply InterpCountLogic.count_logic_safehiΣ _ _ _ _ 65552 lit_reg hello_bytes
4 openfocused goal
focused goal
focused goal
–exact hi_memory_ready
3 opendeferred goal
deferred goal
deferred goal
–exact hi_memory_disjoint
2 opendeferred goal
deferred goal
–exact lit_ok
deferred goal
–apply all_agree_intro
intros l v Hl
exact InterpHiLogic.lit_valid_agrees_ Hv l v Hl
No remaining goals.
Qed
✓ Proof checked and closed by Rocq.