Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f32cb06
Introduce Pulse.VC, a module to uniformly handle VCs
mtzguido Feb 14, 2025
f7199dd
New guarded matching logic, matching keys, no backtracking on SMT ever
mtzguido Feb 15, 2025
7dc386c
Allow admitting SMT queries.
mtzguido Feb 14, 2025
ca06dd1
Update pulse library
mtzguido Feb 17, 2025
a4a31be
Update tests
mtzguido Feb 15, 2025
adc7417
Update examples
mtzguido Feb 15, 2025
c32c78f
Update expected output
mtzguido Feb 18, 2025
ff7c90d
AVLTree: remove leftover admits
mtzguido Feb 18, 2025
9e9db1f
AVLTree: remove no-ops
mtzguido Feb 18, 2025
f06ceaf
all: remove leftover debugging options
mtzguido Feb 18, 2025
531b3a6
Array.Core: fix mkey to match fsti
mtzguido Feb 18, 2025
d633d09
ArrayPtr: remove specialized fold/unfold, no longer needed
mtzguido Feb 18, 2025
b7f925e
LinkedList: remove stray admit
mtzguido Feb 18, 2025
d799d56
Quicksort.Task: remove now-needless rewrite
mtzguido Feb 18, 2025
c408993
Matcher: allow delta when matching arguments in full matcher
mtzguido Feb 18, 2025
c90af6f
Quicksort.Task: simplify now that matcher will unfold args
mtzguido Feb 18, 2025
5e6e2cf
Add repros for #347
mtzguido Feb 18, 2025
5ede645
Removing debug options in test/examples
mtzguido Feb 18, 2025
786d361
lib: remove leftover admits
mtzguido Feb 18, 2025
74c9f81
remove more now-superfluous rewrites
mtzguido Feb 18, 2025
5329695
pulse.opam: can now set ADMIT=1 in build
mtzguido Feb 18, 2025
918d2a3
remove debug output
mtzguido Feb 19, 2025
a819dad
Trade: mark components as mkeys, allows deep matching
mtzguido Feb 19, 2025
8fc6740
lib: No need for GTot on prop/Type0
mtzguido Feb 21, 2025
12d5e6e
Matcher: allow unification for slprops too
mtzguido Feb 21, 2025
7233c9f
Add test for krml admit
mtzguido Feb 21, 2025
8d0019c
Update expected putput (not great)
mtzguido Feb 21, 2025
060bad3
pulse2rust/DICE/DPE: make tests slightly more incremental
mtzguido Feb 21, 2025
3f61797
Simplify: hd (h :: t) ~> h, tl (h :: t) ~> t
mtzguido Feb 22, 2025
b9a4874
Defend against empty issues from typing reflection
mtzguido Feb 24, 2025
6273aae
Update some tests
mtzguido Feb 24, 2025
07aa99e
simplify append_split
tahina-pro Feb 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ _cache
FStar
_pak
pulse.tar.gz

# make touchfiles
.*.touch
55 changes: 28 additions & 27 deletions lib/common/Pulse.Lib.Core.fsti
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,27 @@ module T = FStar.Tactics.V2
open Pulse.Lib.Dv {}
open FStar.ExtractAs

(* This attribute can be used on the indexes of a slprop
to instruct the checker to call the SMT solver to relate
occurrences of that index.

For example, if you have

val pts_to (x:ref a) ([@@@equate_by_smt] v:a) : slprop

Then `pts_to x (a + b)` and `pts_to x (b + a)` will be
matched by the prover by emitting an SMT query (a + b) == (b + a). Of course,
`pts_to x a` and `pts_to x a` will be matched purely by unification without
emitted a trivial SMT query (a == a).

By default, if none of the indexes of a slprop are marked with "equate_by_smt",
the _last_ argument of a slprop is considered to be equated by SMT. This makes
it convenient to write slprops like the one below, without paying special
heed to this attribute.

val pts_to (x:ref a) (v:a) : slprop
(* Arguments of slprops can be marked as a matching key to
1- Make sure we do no try to use the SMT to match resources with
different matching keys (in other words, we only use the unifier to
match the matching keys).
2- Indicate that we only expect a single instance of the resource for
a given set of matching keys, so we allow the use of SMT for the rest
of the arguments.

val pts_to ([@@@mkey] x : ref a) (v : a) : slprop

Then `pts_to x (a + b)` and `pts_to x (b + a)` will be matched by the
prover by emitting an SMT query `pts_to x (a + b) == pts_to x (b +
a)`. (Note we ask for this possibly weaker fact instead of `(a + b)
== (b + a)`; this can be useful when the definition of the resource
is not injective.)

Of course, `pts_to x a` and `pts_to x a` will be matched purely by
unification without even emitting a trivial SMT query (a == a).
*)
val equate_by_smt : unit (* now meaningless. *)
val equate_strict : unit (* only use fastunif *)
val equate_syntactic : unit (* only use term_eq *)
val mkey : unit
val no_mkeys : unit

(** This attribute allows to do ambiguous proving when calling a function. *)
val allow_ambiguous : unit
Expand Down Expand Up @@ -177,7 +175,10 @@ let (/!) (is1 is2 : inames) : Type0 =
GhostSet.disjoint is1 is2

val inv (i:iname) (p:slprop) : slprop

[@@no_mkeys]
val inames_live (inames:inames) : slprop

let mem_iname (e:inames) (i:iname) : erased bool = elift2 (fun e i -> GhostSet.mem i e) e i
let mem_inv (e:inames) (i:iname) : GTot bool = mem_iname e i

Expand Down Expand Up @@ -525,7 +526,7 @@ val later_equiv (p q: slprop) : squash (later (equiv p q) == equiv (later p) (la
[@@erasable]
val slprop_ref : Type0

val slprop_ref_pts_to (x: slprop_ref) (y: slprop) : slprop
val slprop_ref_pts_to ([@@@mkey]x: slprop_ref) (y: slprop) : slprop

val slprop_ref_alloc (y: slprop)
: stt_ghost slprop_ref emp_inames emp fun x -> slprop_ref_pts_to x y
Expand Down Expand Up @@ -688,7 +689,7 @@ let pcm_ref
val pcm_pts_to
(#a:Type u#1)
(#p:pcm a)
([@@@equate_strict] r:pcm_ref p)
([@@@mkey] r:pcm_ref p)
(v:a)
: slprop

Expand Down Expand Up @@ -793,7 +794,7 @@ instance val non_informative_ghost_pcm_ref
val ghost_pcm_pts_to
(#a:Type u#1)
(#p:pcm a)
([@@@equate_strict] r:ghost_pcm_ref p)
([@@@mkey] r:ghost_pcm_ref p)
(v:a)
: slprop

Expand Down Expand Up @@ -867,7 +868,7 @@ val ghost_gather
val big_pcm_pts_to
(#a:Type u#2)
(#p:pcm a)
([@@@equate_strict] r:pcm_ref p)
([@@@mkey] r:pcm_ref p)
(v:a)
: slprop

Expand Down Expand Up @@ -946,7 +947,7 @@ val big_gather
val big_ghost_pcm_pts_to
(#a:Type u#2)
(#p:pcm a)
([@@@equate_strict] r:ghost_pcm_ref p)
([@@@mkey] r:ghost_pcm_ref p)
(v:a)
: slprop

Expand Down
6 changes: 3 additions & 3 deletions lib/core/Pulse.Lib.Core.fst
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ open PulseCore.FractionalPermission
open PulseCore.Observability
friend PulseCore.InstantiatedSemantics
module Sep = PulseCore.IndirectionTheorySep
let equate_by_smt = ()
let equate_strict = ()
let equate_syntactic = ()

let mkey = ()
let no_mkeys = ()

let allow_ambiguous = ()

Expand Down
16 changes: 8 additions & 8 deletions lib/pulse/c/Pulse.C.Types.Array.fsti
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,12 @@ inline_for_extraction [@@noextract_to "krml"]
let array_ref (#t: Type) (td: typedef t) = (a: array_ptr td { g_array_ptr_is_null a == false })

(*
val array_ref_base_size_type (#t: Type) (#td: typedef t) (a: array_ref td) : GTot Type0
val array_ref_base_size_type (#t: Type) (#td: typedef t) (a: array_ref td) : Type0
*)
val array_ref_base_size (#t: Type) (#td: typedef t) (a: array_ptr td) : Ghost SZ.t
(requires True)
(ensures (fun y -> SZ.v y == 0 <==> a == null_array_ptr td))
val has_array_ref_base (#t: Type) (#td: typedef t) (a: array_ref td) (#ty: Type) (r: ref (base_array0 ty td (array_ref_base_size a))) : GTot prop
val has_array_ref_base (#t: Type) (#td: typedef t) (a: array_ref td) (#ty: Type) (r: ref (base_array0 ty td (array_ref_base_size a))) : prop
val has_array_ref_base_inj (#t: Type) (#td: typedef t) (a: array_ref td) (#ty: Type) (r1 r2: ref (base_array0 ty td (array_ref_base_size a))) : Lemma
(requires (has_array_ref_base a r1 /\ has_array_ref_base a r2))
(ensures (r1 == r2))
Expand Down Expand Up @@ -323,7 +323,7 @@ let has_array_of_base
(#td: typedef t)
(r: ref (base_array0 tn td n))
(a: array td)
: GTot prop
: prop
= let (| al, len |) = a in
array_ref_base_size al == n /\
has_array_ref_base al #tn r /\
Expand Down Expand Up @@ -390,7 +390,7 @@ let array_ref_of_base_post
(r: ref (base_array0 tn td n))
(a: array_ref td)
(ar: array td)
: GTot prop
: prop
=
array_ptr_of ar == a /\
array_ref_base_size a == Ghost.reveal n /\
Expand Down Expand Up @@ -521,7 +521,7 @@ ensures
}


let full_seq (#t: Type) (td: typedef t) (v: Seq.seq t) : GTot prop =
let full_seq (#t: Type) (td: typedef t) (v: Seq.seq t) : prop =
forall (i: nat { i < Seq.length v }) . {:pattern (Seq.index v i)} full td (Seq.index v i)

let full_seq_seq_of_base_array
Expand Down Expand Up @@ -907,7 +907,7 @@ let array_ref_split_post
(a: array td)
(i: SZ.t)
(sl sr: Ghost.erased (Seq.seq t))
: GTot prop
: prop
= SZ.v i <= array_length a /\ Seq.length s == array_length a /\
Ghost.reveal sl == Seq.slice s 0 (SZ.v i) /\
Ghost.reveal sr == Seq.slice s (SZ.v i) (Seq.length s)
Expand Down Expand Up @@ -983,7 +983,7 @@ val array_join
))
(fun _ -> array_pts_to a (sl `Seq.append` sr))

let fractionable_seq (#t: Type) (td: typedef t) (s: Seq.seq t) : GTot prop =
let fractionable_seq (#t: Type) (td: typedef t) (s: Seq.seq t) : prop =
forall (i: nat). i < Seq.length s ==> fractionable td (Seq.index s i)

let mk_fraction_seq (#t: Type) (td: typedef t) (s: Seq.seq t) (p: perm) : Ghost (Seq.seq t)
Expand Down Expand Up @@ -1055,7 +1055,7 @@ let array_blit_post
(idx_dst: SZ.t)
(len: SZ.t)
(s1' : Ghost.erased (Seq.seq t))
: GTot prop
: prop
=
SZ.v idx_src + SZ.v len <= array_length src /\
SZ.v idx_dst + SZ.v len <= array_length dst /\
Expand Down
8 changes: 4 additions & 4 deletions lib/pulse/c/Pulse.C.Types.Base.fsti
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ val typedef (t: Type0) : Type0
inline_for_extraction [@@noextract_to "krml"]
let typeof (#t: Type0) (td: typedef t) : Tot Type0 = t

val fractionable (#t: Type0) (td: typedef t) (x: t) : GTot prop
val fractionable (#t: Type0) (td: typedef t) (x: t) : prop

val mk_fraction (#t: Type0) (td: typedef t) (x: t) (p: perm) : Ghost t
(requires (fractionable td x))
Expand All @@ -48,7 +48,7 @@ val mk_fraction_compose (#t: Type0) (td: typedef t) (x: t) (p1 p2: perm) : Lemma
(requires (fractionable td x /\ p1 <=. 1.0R /\ p2 <=. 1.0R))
(ensures (mk_fraction td (mk_fraction td x p1) p2 == mk_fraction td x (p1 `prod_perm` p2)))

val full (#t: Type0) (td: typedef t) (v: t) : GTot prop
val full (#t: Type0) (td: typedef t) (v: t) : prop

val uninitialized (#t: Type0) (td: typedef t) : Ghost t
(requires True)
Expand Down Expand Up @@ -115,10 +115,10 @@ let null (#t: Type) (td: typedef t) : Tot (ptr td) = null_gen t
inline_for_extraction [@@noextract_to "krml"]
let ref (#t: Type) (td: typedef t) : Tot Type0 = (p: ptr td { ~ (p == null td) })

val pts_to (#t: Type) (#[@@@equate_by_smt]td: typedef t) (r: ref td) ([@@@equate_by_smt] v: Ghost.erased t) : slprop
val pts_to (#t: Type) (#td: typedef t) ([@@@mkey]r: ref td) (v: Ghost.erased t) : slprop

let pts_to_or_null
(#t: Type) (#[@@@equate_by_smt]td: typedef t) (p: ptr td) ([@@@equate_by_smt] v: Ghost.erased t) : slprop
(#t: Type) (#td: typedef t) ([@@@mkey]p: ptr td) (v: Ghost.erased t) : slprop
= if FStar.StrongExcludedMiddle.strong_excluded_middle (p == null _)
then emp
else pts_to p v
Expand Down
Loading
Loading