Fil-C on Nix

Filnix wiki

the formal campaign

rocq/theories/Buffer.v

A program with a heap object, proved never to panic: rocq/programs/buffer.c, which allocates a buffer of four longs (__builtin_alloca, which Fil-C places in the collected heap), fills it, then sums p[i % 4] for i from 0 while i < n, for every int n (BufferCode.v, checked current by rocq/programs.sh). BufferLogic.v proves the same theorem through the Iris program logic.

The proof is Cycle.v's: an assertion at each of the function's 32 points (buffer_assert), and one step from any configuration where it holds is safe and reaches a point where its assertion holds (buffer_safe). What is new is the object. The run chooses its base, so the assertions speak of any base b that the allocation could return (fresh): from the allocation on, the temporary v4 holds a pointer to b with b's own capability, and b's region is a live heap object of 32 bytes. The access checks then pass because each address is b plus 0 to 24.

A safepoint leaves the object as it is: the collector changes no region (Runtime.v's collector_live), and Fil-C's runtime frees nothing by itself. Only code a program brings in, a signal handler it installs or a thread it starts, could free the buffer under it, and buffer calls no external at all. So the theorem holds for every runtime with no premise.

Decisions

DecisionWhy
no premise about safepointsthe theorem once took safepoint_keeps_live, when Runtime.v's safepoint stood for signal handlers too; a handler or a thread is the program's code, and Fil-C's collector frees nothing, so the safepoint axiom is now the collector's alone (collector_live)
the assertions say nothing of the buffer's bytesthe program reads them only as longs it adds; any value is safe, so neither the fill nor a safepoint's bytes matter
an allocation's base is any fresh onePanics.v's never_panics_by_invariant gives every base the runtime may return; the proof uses only that it is positive and that the object ends at or below 2^64
From Stdlib Require Import String ZArith List Bool Lia
From Nanofil Require Import Term Syntax Values Memory Runtime Ops Semantics Run Machine Transport Panics Symbolic BufferCode
Import ListNotations
Open Scope Z_scope
Arguments Z.add : simpl nomatch
Arguments Z.sub : simpl nomatch
Arguments Z.mul : simpl nomatch
Arguments Z.opp : simpl nomatch

Integer arithmetic on an unknown stays folded when a step is computed (Symbolic.v).

The program

The checked module, decoded from the fixture buffer_term (buffer_decodes).

51Definition buffer_module: module ≔
Somemd
⇒
md
None
⇒
[ ]

The fixture decodes to buffer_module.

55Lemma buffer_decodes
Explore proof 2 tactics

Initial goal

vm_compute

⊢
SomeIFuncfn_name ≔ TAtom"buffer"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassL; fn_params ≔ W, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v4" P Alloc16 Const32; b_jump ≔ JGotoToTAtom"L6"; b_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.1" W TAtom"start", Const0; TAtom"L7", TmpTAtom"v18"; b_insts ≔ LetTAtom"v11" W CmpSlt W TmpTAtom"pr.1"; Const4; b_jump ≔ JBranchTmpTAtom"v11" ToTAtom"L7" ToTAtom"L24"; b_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v14" L ExtSw TmpTAtom"pr.1"; LetTAtom"v15" L Shl TmpTAtom"v14"; Const3; FlightTAtom"v16" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v15" LowerOfTmpTAtom"v4"; LetTAtom"v18" W Add TmpTAtom"pr.1"; Const1; LetTAtom"v19" L ExtSw TmpTAtom"v18"; LetTAtom"chk0" A Check0 8 Write 1 TmpTAtom"v16"; RawStoreWl 0 TmpTAtom"v19" TmpTAtom"chk0"; b_jump ≔ JGotoPollTAtom"L6"; b_label ≔ TAtom"L24"; b_phis ≔ PhiTAtom"pr.3" W TAtom"L25", TmpTAtom"v41"; TAtom"L6", Const0; PhiTAtom"pr.2" L TAtom"L25", TmpTAtom"v39"; TAtom"L6", Const0; b_insts ≔ LetTAtom"v30" W CmpSlt W TmpTAtom"pr.3"; TmpTAtom"v0"; b_jump ≔ JBranchTmpTAtom"v30" ToTAtom"L25" ToTAtom"L27"; b_label ≔ TAtom"L25"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v34" W Rem TmpTAtom"pr.3"; Const4; LetTAtom"v35" L ExtSw TmpTAtom"v34"; LetTAtom"v36" L Shl TmpTAtom"v35"; Const3; FlightTAtom"v37" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v36" LowerOfTmpTAtom"v4"; LetTAtom"chk1" A Check0 8 Read 1 TmpTAtom"v37"; LetTAtom"v38" L RawLoadLdL 0 TmpTAtom"chk1"; LetTAtom"v39" L Add TmpTAtom"pr.2"; TmpTAtom"v38"; LetTAtom"v41" W Add TmpTAtom"pr.3"; Const1; b_jump ≔ JGotoPollTAtom"L24"; b_label ≔ TAtom"L27"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.2" = SomeIFuncfn_name ≔ TAtom"buffer"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassL; fn_params ≔ W, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v4" P Alloc16 Const32; b_jump ≔ JGotoToTAtom"L6"; b_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.1" W TAtom"start", Const0; TAtom"L7", TmpTAtom"v18"; b_insts ≔ LetTAtom"v11" W CmpSlt W TmpTAtom"pr.1"; Const4; b_jump ≔ JBranchTmpTAtom"v11" ToTAtom"L7" ToTAtom"L24"; b_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v14" L ExtSw TmpTAtom"pr.1"; LetTAtom"v15" L Shl TmpTAtom"v14"; Const3; FlightTAtom"v16" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v15" LowerOfTmpTAtom"v4"; LetTAtom"v18" W Add TmpTAtom"pr.1"; Const1; LetTAtom"v19" L ExtSw TmpTAtom"v18"; LetTAtom"chk0" A Check0 8 Write 1 TmpTAtom"v16"; RawStoreWl 0 TmpTAtom"v19" TmpTAtom"chk0"; b_jump ≔ JGotoPollTAtom"L6"; b_label ≔ TAtom"L24"; b_phis ≔ PhiTAtom"pr.3" W TAtom"L25", TmpTAtom"v41"; TAtom"L6", Const0; PhiTAtom"pr.2" L TAtom"L25", TmpTAtom"v39"; TAtom"L6", Const0; b_insts ≔ LetTAtom"v30" W CmpSlt W TmpTAtom"pr.3"; TmpTAtom"v0"; b_jump ≔ JBranchTmpTAtom"v30" ToTAtom"L25" ToTAtom"L27"; b_label ≔ TAtom"L25"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v34" W Rem TmpTAtom"pr.3"; Const4; LetTAtom"v35" L ExtSw TmpTAtom"v34"; LetTAtom"v36" L Shl TmpTAtom"v35"; Const3; FlightTAtom"v37" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v36" LowerOfTmpTAtom"v4"; LetTAtom"chk1" A Check0 8 Read 1 TmpTAtom"v37"; LetTAtom"v38" L RawLoadLdL 0 TmpTAtom"chk1"; LetTAtom"v39" L Add TmpTAtom"pr.2"; TmpTAtom"v38"; LetTAtom"v41" W Add TmpTAtom"pr.3"; Const1; b_jump ≔ JGotoPollTAtom"L24"; b_label ≔ TAtom"L27"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.2"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
vm_compute
reflexivity

The function buffer, the module's only item.

59Definition buffer_fn: func ≔
match buffer_module with
IFuncf :: _
⇒
f
_
⇒
mkFuncTAtom"buffer" TAtom"export" RClassL [ ] [ ]

The module's one global, the function buffer.

66Definition buffer_globals: listname × ptr ≔
TAtom"buffer", mkPtr65536 FnTAtom"buffer"

The module's initial memory, which holds no object.

70Definition buffer_mem: mem ≔
Some_, m
⇒
m
None
⇒

Laying out the module succeeds, with buffer_globals and buffer_mem.

Explore proof 3 tactics

Initial goal

assert H : option_mapfst initial_memorybuffer_module = Somebuffer_globals by vm_compute ; reflexivity

unfold buffer_mem

destruct initial_memorybuffer_module as g m | ; inversion H ; reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
assert H : option_mapfst initial_memorybuffer_module = Somebuffer_globals by vm_compute ; reflexivity
unfold buffer_mem
destruct initial_memorybuffer_module as g m | ; inversion H ; reflexivity

The genv of the module with any free; the program calls none.

83Definition buffer_gefree : word → mem → optionresunit × mem : genv ≔

buffer is a function of the core subset in the module.

87Lemma buffer_find
∀ free
Explore proof 3 tactics

Initial goal

⊢
∀free : word → mem → optionresunit × mem, find_fnbuffer_gefree TAtom"buffer" = SomeDefinedbuffer_fn

intros free

free :
word → mem → optionresunit × mem

vm_compute

free :
word → mem → optionresunit × mem
⊢
SomeDefinedfn_name ≔ TAtom"buffer"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassL; fn_params ≔ W, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v4" P Alloc16 Const32; b_jump ≔ JGotoToTAtom"L6"; b_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.1" W TAtom"start", Const0; TAtom"L7", TmpTAtom"v18"; b_insts ≔ LetTAtom"v11" W CmpSlt W TmpTAtom"pr.1"; Const4; b_jump ≔ JBranchTmpTAtom"v11" ToTAtom"L7" ToTAtom"L24"; b_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v14" L ExtSw TmpTAtom"pr.1"; LetTAtom"v15" L Shl TmpTAtom"v14"; Const3; FlightTAtom"v16" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v15" LowerOfTmpTAtom"v4"; LetTAtom"v18" W Add TmpTAtom"pr.1"; Const1; LetTAtom"v19" L ExtSw TmpTAtom"v18"; LetTAtom"chk0" A Check0 8 Write 1 TmpTAtom"v16"; RawStoreWl 0 TmpTAtom"v19" TmpTAtom"chk0"; b_jump ≔ JGotoPollTAtom"L6"; b_label ≔ TAtom"L24"; b_phis ≔ PhiTAtom"pr.3" W TAtom"L25", TmpTAtom"v41"; TAtom"L6", Const0; PhiTAtom"pr.2" L TAtom"L25", TmpTAtom"v39"; TAtom"L6", Const0; b_insts ≔ LetTAtom"v30" W CmpSlt W TmpTAtom"pr.3"; TmpTAtom"v0"; b_jump ≔ JBranchTmpTAtom"v30" ToTAtom"L25" ToTAtom"L27"; b_label ≔ TAtom"L25"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v34" W Rem TmpTAtom"pr.3"; Const4; LetTAtom"v35" L ExtSw TmpTAtom"v34"; LetTAtom"v36" L Shl TmpTAtom"v35"; Const3; FlightTAtom"v37" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v36" LowerOfTmpTAtom"v4"; LetTAtom"chk1" A Check0 8 Read 1 TmpTAtom"v37"; LetTAtom"v38" L RawLoadLdL 0 TmpTAtom"chk1"; LetTAtom"v39" L Add TmpTAtom"pr.2"; TmpTAtom"v38"; LetTAtom"v41" W Add TmpTAtom"pr.3"; Const1; b_jump ≔ JGotoPollTAtom"L24"; b_label ≔ TAtom"L27"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.2" = SomeDefinedfn_name ≔ TAtom"buffer"; fn_linkage ≔ TAtom"export"; fn_ret ≔ RClassL; fn_params ≔ W, TAtom"v0"; fn_blocks ≔ b_label ≔ TAtom"start"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v4" P Alloc16 Const32; b_jump ≔ JGotoToTAtom"L6"; b_label ≔ TAtom"L6"; b_phis ≔ PhiTAtom"pr.1" W TAtom"start", Const0; TAtom"L7", TmpTAtom"v18"; b_insts ≔ LetTAtom"v11" W CmpSlt W TmpTAtom"pr.1"; Const4; b_jump ≔ JBranchTmpTAtom"v11" ToTAtom"L7" ToTAtom"L24"; b_label ≔ TAtom"L7"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v14" L ExtSw TmpTAtom"pr.1"; LetTAtom"v15" L Shl TmpTAtom"v14"; Const3; FlightTAtom"v16" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v15" LowerOfTmpTAtom"v4"; LetTAtom"v18" W Add TmpTAtom"pr.1"; Const1; LetTAtom"v19" L ExtSw TmpTAtom"v18"; LetTAtom"chk0" A Check0 8 Write 1 TmpTAtom"v16"; RawStoreWl 0 TmpTAtom"v19" TmpTAtom"chk0"; b_jump ≔ JGotoPollTAtom"L6"; b_label ≔ TAtom"L24"; b_phis ≔ PhiTAtom"pr.3" W TAtom"L25", TmpTAtom"v41"; TAtom"L6", Const0; PhiTAtom"pr.2" L TAtom"L25", TmpTAtom"v39"; TAtom"L6", Const0; b_insts ≔ LetTAtom"v30" W CmpSlt W TmpTAtom"pr.3"; TmpTAtom"v0"; b_jump ≔ JBranchTmpTAtom"v30" ToTAtom"L25" ToTAtom"L27"; b_label ≔ TAtom"L25"; b_phis ≔ [ ]; b_insts ≔ LetTAtom"v34" W Rem TmpTAtom"pr.3"; Const4; LetTAtom"v35" L ExtSw TmpTAtom"v34"; LetTAtom"v36" L Shl TmpTAtom"v35"; Const3; FlightTAtom"v37" Add FAddressTmpTAtom"v4"; FValueTmpTAtom"v36" LowerOfTmpTAtom"v4"; LetTAtom"chk1" A Check0 8 Read 1 TmpTAtom"v37"; LetTAtom"v38" L RawLoadLdL 0 TmpTAtom"chk1"; LetTAtom"v39" L Add TmpTAtom"pr.2"; TmpTAtom"v38"; LetTAtom"v41" W Add TmpTAtom"pr.3"; Const1; b_jump ≔ JGotoPollTAtom"L24"; b_label ≔ TAtom"L27"; b_phis ≔ [ ]; b_insts ≔ [ ]; b_jump ≔ JRetTmpTAtom"pr.2"

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros free
vm_compute
reflexivity

Any arguments whose first word is the integer n start buffer at its entry block with n as its parameter v0.

93Lemma buffer_call_frame
∀ n rest
call_framebuffer_fn WIntn :: rest = SomemkFramebuffer_fn TAtom"v0", WIntn [ ] None EnterTAtom"start" None
Explore proof 1 tactics

Initial goal

⊢
∀n : Z rest : listword, call_framebuffer_fn WIntn :: rest = Somefr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None

reflexivity

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
reflexivity

The points

Block l of buffer after its first j instructions.

101Definition buffer_atl : string j : nat : point ≔
Someb
⇒
None
⇒

Every point of buffer, numbered: the entry block start, before and after its allocation (0 to 2); the fill loop's head L6 (3 to 6) and body L7 (7 to 15); the sum loop's head L24 (16 to 19) and body L25 (20 to 29); and the exit L27 (30, 31).

111Definition buffer_points: listpoint ≔
EnterTAtom"start" None; buffer_at"start" 0; buffer_at"start" 1; EnterTAtom"L6" SomeTAtom"start"; EnterTAtom"L6" SomeTAtom"L7"; buffer_at"L6" 0; buffer_at"L6" 1; EnterTAtom"L7" SomeTAtom"L6" ++ mapbuffer_at"L7" seq0 8 ++ EnterTAtom"L24" SomeTAtom"L6"; EnterTAtom"L24" SomeTAtom"L25"; buffer_at"L24" 0; buffer_at"L24" 1; EnterTAtom"L25" SomeTAtom"L24" ++ mapbuffer_at"L25" seq0 9 ++ EnterTAtom"L27" SomeTAtom"L24"; buffer_at"L27" 0

The assertions

The buffer at the base b, in the environment e and the memory m: v4 holds a pointer to b with b's capability, b is positive, the object ends at or below 2^64, and its region is a live heap object of 32 bytes.

127Definition holds_buffere : env m : mem b : Z : Prop ≔
lookupTAtom"v4" e = SomeWPtrmkPtrb Objb ∧ 0 < b ∧ b + 32 ≤ 2 ^ 64 ∧ object_regionb m_regionsm = SomemkRegionb b + 32 Heap Live

The temporary x holds a pointer into the buffer at b with 8 bytes after it.

133Definition into_bufe : env x : string b : Z : Prop ≔
∃a, lookupTAtomx e = SomeWPtrmkPtra Objb ∧ b ≤ a ≤ b + 24

What holds after the first j instructions of the fill loop's body, which stores i + 1 at pi: the index pr.1 below 4, then v14 and v15, the offset, the pointer v16, the next index v18 and its long v19, and the checked proof chk0.

140Definition fill_assertj : nat b : Z e : env : Prop ≔
int_ate TAtom"pr.1" λi ⇒ 0 ≤ i < 4
∧
1 ≤? j%nat
→
int_ate TAtom"v14" λi ⇒ 0 ≤ i < 4
else
True
∧
2 ≤? j%nat
→
int_ate TAtom"v15" λo ⇒ 0 ≤ o ≤ 24
else
True
∧
3 ≤? j%nat
→
into_bufe "v16" b
else
True
∧
4 ≤? j%nat
→
int_ate TAtom"v18" λi ⇒ 0 ≤ i ≤ 4
else
True
∧
5 ≤? j%nat
→
else
True
∧
6 ≤? j%nat
→
into_bufe "chk0" b
else
True

What holds after the first j instructions of the sum loop's body, as Cycle.v's body_assert with the buffer for the array.

151Definition sum_assertj : nat b : Z e : env : Prop ≔
∧
int_ate TAtom"pr.3" λi ⇒ 0 ≤ i ∧ i + 1 < 2 ^ 31
∧
1 ≤? j%nat
→
int_ate TAtom"v34" λr ⇒ 0 ≤ r < 4
else
True
∧
2 ≤? j%nat
→
int_ate TAtom"v35" λr ⇒ 0 ≤ r < 4
else
True
∧
3 ≤? j%nat
→
int_ate TAtom"v36" λo ⇒ 0 ≤ o ≤ 24
else
True
∧
4 ≤? j%nat
→
into_bufe "v37" b
else
True
∧
5 ≤? j%nat
→
into_bufe "chk1" b
else
True
∧
6 ≤? j%nat
→
else
True
∧
7 ≤? j%nat
→
else
True
∧
8 ≤? j%nat
→
int_ate TAtom"v41" λi ⇒ 0 ≤ i < 2 ^ 31
else
True

What holds at point k of buffer_points besides the buffer: at each loop's head and branch, its index and the comparison's answer; in each body, fill_assert or sum_assert; at the exit, the sum.

166Definition point_assertk : nat b : Z e : env : Prop ≔
match k with
4%nat
⇒
int_ate TAtom"v18" λi ⇒ 0 ≤ i ≤ 4
5%nat
⇒
int_ate TAtom"pr.1" λi ⇒ 0 ≤ i ≤ 4
6%nat
⇒
∃i, lookupTAtom"pr.1" e = SomeWInti ∧ 0 ≤ i ≤ 4 ∧ lookupTAtom"v11" e = SomeWInt0 ∨ lookupTAtom"v11" e = SomeWInt1 ∧ i < 4
7%nat
⇒
int_ate TAtom"pr.1" λi ⇒ 0 ≤ i < 4
17%nat
⇒
int_ate TAtom"v41" λi ⇒ 0 ≤ i < 2 ^ 31 ∧ int_ate TAtom"v39" any
18%nat
⇒
int_ate TAtom"pr.2" any ∧ int_ate TAtom"pr.3" λi ⇒ 0 ≤ i < 2 ^ 31
19%nat
⇒
int_ate TAtom"pr.2" any ∧ ∃i, lookupTAtom"pr.3" e = SomeWInti ∧ 0 ≤ i < 2 ^ 31 ∧ lookupTAtom"v30" e = SomeWInt0 ∨ lookupTAtom"v30" e = SomeWInt1 ∧ i + 1 < 2 ^ 31
20%nat
⇒
30%nat | 31%nat
⇒
_
⇒
8 ≤? k%nat && k ≤? 15%nat
→
fill_assertk − 8 b e
21 ≤? k%nat && k ≤? 29%nat
→
sum_assertk − 21 b e
else
True

What holds at point k in the memory m: nothing before the allocation; from it on, the buffer at some base b and the point's own assertion.

190Definition buffer_assertk : nat e : env m : mem : Prop ≔
match k with
0%nat | 1%nat
⇒
True
_
⇒
∃b, holds_buffere m b ∧ point_assertk b e

A configuration of buffer where the assertions hold: at point k, with no caller, the input v0 an integer, and the assertion of k.

198Definition buffer_invc : config : Prop ≔
∃k pt e, c = mkConfigmkFramebuffer_fn e [ ] None pt [ ] c_memc c_fuelc ∧ nth_errorbuffer_points k = Somept ∧ int_ate TAtom"v0" any ∧ buffer_assertk e c_memc

Each step

Unfold the assertion at a known point.

207Ltac assertion  ≔
cbn [ buffer_assert point_assert Nat.leb andb Nat.sub ] ; try unfold fill_assert ; try unfold sum_assert ; cbn [ Nat.leb ]

Unfold the assertion at a known point in the hypothesis H.

212Ltac assertion_in H ≔
cbn [ buffer_assert point_assert Nat.leb andb Nat.sub ] in H ; try unfold fill_assert in H ; try unfold sum_assert in H ; cbn [ Nat.leb ] in H

The point of the next configuration is point n of buffer_points or a later one: find it by computing each in turn.

218Ltac find_point pt n ≔
lazymatch n with32%nat⇒fail_⇒first assert Hpt : nth_errorbuffer_points n = Somept by vm_compute ; reflexivity ; exists n, pt | find_point pt Snend

The next configuration is in buffer_inv: at its point, with the facts shown.

228Ltac next_inv  ≔
cbv beta ; unfold buffer_inv;match goal with|- ∃k pt e, mkConfigmkFrame_ _ _ _ ?pt′ _ _ _ = _ ∧ _⇒find_point pt′ 0%natend;eexists;split;|subst ; reflexivity|;split;|assumption|;split;|show_facts|assertion ; unfold holds_buffer , into_buf ; show_facts

The allocation's result is safe: its extent is nonnegative, and every fresh base gives a configuration where the assertions hold.

239Ltac fresh_inv  ≔
change heap_req16 32 with mkReq16 32 Heap in * ; split ; cbv ; discriminate | ; intros ? Hfresh ; unfold fresh in Hfresh ; cbn [ c_mem req_extent req_align ] in Hfresh ; facts ; next_inv

One point of buffer_safe: the point from Hk, an index into the points pts, the assertion Ha taken apart, the step taken by its rule (take_step), and its result shown safe.

247Ltac point_safe pts Hk Ha ≔
cbv in Hk ; injection Hk as ← ; clear pts ; assertion_in Ha ; unfold int_at , holds_buffer , into_buf in * ; facts ; take_step ; cbn [ safe_step ] ; solve intro ; assumption | next_inv | fresh_inv

One step from a configuration where the assertions hold is safe_step for them.

255Lemma buffer_safe
Proof 18 steps Qed
intros free c k & pt & e & Ec & Hk & Hin & Ha
rewrite Ec
clear Ec
set m := c_memc in *
set fuel := c_fuelc in *
clearbody m fuel
set pts := buffer_points in Hk
vm_compute in pts
remember buffer_fn as f eqn: Hf
block_fact f buffer_fn Hf TAtom"start" b0 Hb0
block_fact f buffer_fn Hf TAtom"L6" b6 Hb6
block_fact f buffer_fn Hf TAtom"L7" b7 Hb7
block_fact f buffer_fn Hf TAtom"L24" b24 Hb24
block_fact f buffer_fn Hf TAtom"L25" b25 Hb25
block_fact f buffer_fn Hf TAtom"L27" b27 Hb27
assert Hret : fn_retf = RClassL by rewrite Hf ; reflexivity
do 32 destruct k as | k ; point_safe pts Hk Ha |
destruct k ; discriminate Hk

A call with an integer first argument starts where the assertions hold, with any fuel.

276Lemma buffer_start
∀ n fuel
Explore proof 5 tactics

Initial goal

⊢
∀n fuel : Z, buffer_invc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel

intros n fuel

n, fuel :
Z
⊢
buffer_invc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel

exists O, EnterTAtom"start" None, TAtom"v0", WIntn

n, fuel :
Z
⊢
c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ c_memc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel; c_fuel ≔ c_fuelc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel ∧ nth_errorbuffer_points 0 = SomeEnterTAtom"start" None ∧ int_atTAtom"v0", WIntn TAtom"v0" any ∧ buffer_assert0 TAtom"v0", WIntn c_memc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel

split ; reflexivity |

n, fuel :
Z
⊢
nth_errorbuffer_points 0 = SomeEnterTAtom"start" None ∧ int_atTAtom"v0", WIntn TAtom"v0" any ∧ buffer_assert0 TAtom"v0", WIntn c_memc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel

split ; vm_compute ; reflexivity |

n, fuel :
Z
⊢
int_atTAtom"v0", WIntn TAtom"v0" any ∧ buffer_assert0 TAtom"v0", WIntn c_memc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel

split ; exists n ; split ; reflexivity | exact I | exact I

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros n fuel
exists O, EnterTAtom"start" None, TAtom"v0", WIntn
split ; reflexivity |
split ; vm_compute ; reflexivity |
split ; exists n ; split ; reflexivity | exact I | exact I

Over any runtime

buffer never panics under the runtime R.

288Module BufferSafe R : Runtime
289Module P ≔ Panics R

What R does at a safepoint keeps the assertions: it changes only the memory, and no region (R.collector_live), so the buffer's region stays.

294Lemma buffer_safepoint
∀ c s s′ m′
R.safepoints c_memc s′ m′
Explore proof 16 tactics

Initial goal

⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

intros c s s′ m′ k & pt & e & Ec & Hk & Hin & Ha Hsp

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points k = Somept
Hin :
Hsp :
R.safepoints c_memc s′ m′

exists k, pt, e

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points k = Somept
Hin :
Hsp :
R.safepoints c_memc s′ m′
⊢
P.RM.with_memc m′ = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memP.RM.with_memc m′; c_fuel ≔ c_fuelP.RM.with_memc m′ ∧ nth_errorbuffer_points k = Somept ∧ int_ate TAtom"v0" any ∧ buffer_assertk e c_memP.RM.with_memc m′

rewrite Ec at 1

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points k = Somept
Hin :
Hsp :
R.safepoints c_memc s′ m′
⊢
P.RM.with_memc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc m′ = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memP.RM.with_memc m′; c_fuel ≔ c_fuelP.RM.with_memc m′ ∧ nth_errorbuffer_points k = Somept ∧ int_ate TAtom"v0" any ∧ buffer_assertk e c_memP.RM.with_memc m′

unfold P.RM.with_mem ; cbn [ c_frame c_callers c_mem c_fuel ]

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points k = Somept
Hin :
Hsp :
R.safepoints c_memc s′ m′
⊢
c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ m′; c_fuel ≔ c_fuelc = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ m′; c_fuel ≔ c_fuelc ∧ nth_errorbuffer_points k = Somept ∧ int_ate TAtom"v0" any ∧ buffer_assertk e m′

split ; reflexivity |

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points k = Somept
Hin :
Hsp :
R.safepoints c_memc s′ m′
⊢
nth_errorbuffer_points k = Somept ∧ int_ate TAtom"v0" any ∧ buffer_assertk e m′

split ; exact Hk |

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points k = Somept
Hin :
Hsp :
R.safepoints c_memc s′ m′
⊢
int_ate TAtom"v0" any ∧ buffer_assertk e m′

split ; exact Hin |

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points k = Somept
Hin :
Hsp :
R.safepoints c_memc s′ m′
⊢

destruct k as | | k ; exact I | exact I |

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points SSk = Somept
Hin :
Hsp :
R.safepoints c_memc s′ m′
⊢
buffer_assertSSk e m′

destruct Ha as b & Hv & Hpos & Hle & Hr & Hp

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points SSk = Somept
Hin :
b :
Z
Hv :
lookupTAtom"v4" e = SomeWPtrptr_addr ≔ b; ptr_cap ≔ Objb
Hpos :
0 < b
Hle :
b + 32 ≤ 2 ^ 64
Hr :
object_regionb m_regionsc_memc = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live
Hp :
Hsp :
R.safepoints c_memc s′ m′
⊢
buffer_assertSSk e m′

exists b

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points SSk = Somept
Hin :
b :
Z
Hv :
lookupTAtom"v4" e = SomeWPtrptr_addr ≔ b; ptr_cap ≔ Objb
Hpos :
0 < b
Hle :
b + 32 ≤ 2 ^ 64
Hr :
object_regionb m_regionsc_memc = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live
Hp :
Hsp :
R.safepoints c_memc s′ m′
⊢
holds_buffere m′ b ∧ point_assertSSk b e

split ; | exact Hp

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points SSk = Somept
Hin :
b :
Z
Hv :
lookupTAtom"v4" e = SomeWPtrptr_addr ≔ b; ptr_cap ≔ Objb
Hpos :
0 < b
Hle :
b + 32 ≤ 2 ^ 64
Hr :
object_regionb m_regionsc_memc = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live
Hp :
Hsp :
R.safepoints c_memc s′ m′
⊢
holds_buffere m′ b

split ; exact Hv |

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points SSk = Somept
Hin :
b :
Z
Hv :
lookupTAtom"v4" e = SomeWPtrptr_addr ≔ b; ptr_cap ≔ Objb
Hpos :
0 < b
Hle :
b + 32 ≤ 2 ^ 64
Hr :
object_regionb m_regionsc_memc = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live
Hp :
Hsp :
R.safepoints c_memc s′ m′
⊢
0 < b ∧ b + 32 ≤ 2 ^ 64 ∧ object_regionb m_regionsm′ = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live

split ; exact Hpos |

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points SSk = Somept
Hin :
b :
Z
Hv :
lookupTAtom"v4" e = SomeWPtrptr_addr ≔ b; ptr_cap ≔ Objb
Hpos :
0 < b
Hle :
b + 32 ≤ 2 ^ 64
Hr :
object_regionb m_regionsc_memc = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live
Hp :
Hsp :
R.safepoints c_memc s′ m′
⊢
b + 32 ≤ 2 ^ 64 ∧ object_regionb m_regionsm′ = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live

split ; exact Hle |

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points SSk = Somept
Hin :
b :
Z
Hv :
lookupTAtom"v4" e = SomeWPtrptr_addr ≔ b; ptr_cap ≔ Objb
Hpos :
0 < b
Hle :
b + 32 ≤ 2 ^ 64
Hr :
object_regionb m_regionsc_memc = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live
Hp :
Hsp :
R.safepoints c_memc s′ m′
⊢
object_regionb m_regionsm′ = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live

rewrite R.collector_live_ _ _ _ Hsp

s, s′ :
R.state
m′ :
k :
nat
pt :
e :
Ec :
c = c_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ e; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ pt; c_callers ≔ [ ]; c_mem ≔ c_memc; c_fuel ≔ c_fuelc
Hk :
nth_errorbuffer_points SSk = Somept
Hin :
b :
Z
Hv :
lookupTAtom"v4" e = SomeWPtrptr_addr ≔ b; ptr_cap ≔ Objb
Hpos :
0 < b
Hle :
b + 32 ≤ 2 ^ 64
Hr :
object_regionb m_regionsc_memc = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live
Hp :
Hsp :
R.safepoints c_memc s′ m′
⊢
object_regionb m_regionsc_memc = Somer_base ≔ b; r_end ≔ b + 32; r_kind ≔ Heap; r_life ≔ Live

exact Hr

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
intros c s s′ m′ k & pt & e & Ec & Hk & Hin & Ha Hsp
exists k, pt, e
rewrite Ec at 1
split ; reflexivity |
split ; exact Hk |
split ; exact Hin |
destruct k as | | k ; exact I | exact I |
destruct Ha as b & Hv & Hpos & Hle & Hr & Hp
exists b
split ; | exact Hp
split ; exact Hv |
split ; exact Hpos |
split ; exact Hle |
rewrite R.collector_live_ _ _ _ Hsp
exact Hr

buffer never panics: for every input whose first word is an integer, with any fuel, no state of its run fails, whatever base its buffer gets.

309Theorem buffer_never_panics
P.never_panicsbuffer_module TAtom"buffer" λxs ⇒ ∃n rest, xs = WIntn :: rest
Explore proof 12 tactics

Initial goal

⊢
P.never_panicsbuffer_module TAtom"buffer" λxs : listword ⇒ ∃n : Z rest : listword, xs = WIntn :: rest

apply P.never_panics_by_invariant_ _ _ buffer_globals buffer_mem buffer_fn buffer_inv

5 open

focused goal
focused goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀fuel : Z, buffer_invc_frame ≔ fr; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel
focused goal
focused goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

–exact buffer_initial

4 open

deferred goal
deferred goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀fuel : Z, buffer_invc_frame ≔ fr; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel
deferred goal
deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

–apply buffer_find

3 open

deferred goal
⊢
∀xs : listword, ∃n : Z rest : listword, xs = WIntn :: rest → ∃fr : frame, call_framebuffer_fn xs = Somefr ∧ ∀fuel : Z, buffer_invc_frame ≔ fr; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel
deferred goal
deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

–intros xs n & rest & →

3 open

n :
Z
rest :
listword
⊢
∃fr : frame, call_framebuffer_fn WIntn :: rest = Somefr ∧ ∀fuel : Z, buffer_invc_frame ≔ fr; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel
deferred goal
deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

eexists

4 open

n :
Z
rest :
listword
⊢
call_framebuffer_fn WIntn :: rest = Some?fr ∧ ∀fuel : Z, buffer_invc_frame ≔ ?fr; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel
deferred goal
deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′
shelved goal
n :
Z
rest :
listword

split ; apply buffer_call_frame |

3 open

n :
Z
rest :
listword
⊢
∀fuel : Z, buffer_invc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel
deferred goal
deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

intros fuel

3 open

n :
Z
rest :
listword
fuel :
Z
⊢
buffer_invc_frame ≔ fr_fn ≔ buffer_fn; fr_env ≔ TAtom"v0", WIntn; fr_locals ≔ [ ]; fr_doomed ≔ None; fr_at ≔ EnterTAtom"start" None; c_callers ≔ [ ]; c_mem ≔ buffer_mem; c_fuel ≔ fuel
deferred goal
deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

apply buffer_start

2 open

deferred goal
deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

–intros c s Hc _

2 open

deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

apply buffer_safe , Hc

deferred goal
⊢
∀c : config s s′ : R.state m′ : mem, buffer_invc → R.readys c_memc → P.RM.safepoint_dueP.program_genvbuffer_module buffer_globals c = true → R.safepoints c_memc s′ m′ → buffer_invP.RM.with_memc m′

–intros c s s′ m′ Hc _ _ Hsp

s, s′ :
R.state
m′ :
Hsp :
R.safepoints c_memc s′ m′

eapply buffer_safepoint ; eassumption

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script
–apply buffer_find
–intros xs n & rest & →
eexists
split ; apply buffer_call_frame |
intros fuel
–intros c s Hc _
apply buffer_safe , Hc
–intros c s s′ m′ Hc _ _ Hsp
eapply buffer_safepoint ; eassumption

The theorem for the interpreter's runtime.

323Module InterpBuffer ≔ BufferSafe InterpRuntime

buffer never panics under the interpreter's runtime, an instance of buffer_never_panics.

327Theorem interp_buffer_never_panics
InterpBuffer.P.never_panicsbuffer_module TAtom"buffer" λxs ⇒ ∃n rest, xs = WIntn :: rest
Explore proof 1 tactics

Initial goal

⊢
InterpBuffer.P.never_panicsbuffer_module TAtom"buffer" λxs : listword ⇒ ∃n : Z rest : listword, xs = WIntn :: rest

apply InterpBuffer.buffer_never_panics

No remaining goals.

Qed

✓ Proof checked and closed by Rocq.

Source script