Repository navigation
Expand file tree
/
Copy pathCanonNatExample.v
More file actions
190 lines (142 loc) · 4.26 KB
/
Copy pathCanonNatExample.v
File metadata and controls
190 lines (142 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
Require Import ImpExtern.
Import ListNotations.
Local Open Scope list_scope.
Import Notations.
Local Open Scope impure.
Import HConsing.
Module TestNat.
(* Example of using a hash-Cons function *)
Section Building. (* Here, we only build hashed values *)
(* This hash-Cons function is shared between several function handling hashed values *)
Variable hC: hashinfo (hashV nat) -> ?? hashV nat.
Hypothesis hC_correct: forall n, WHEN hC n ~> n' THEN data (hdata n)=data n'.
(* First, we wrap constructors for hashed values !*)
Definition hO: unit -> ?? hashV nat :=
fun _ =>
hC {| hdata := liftHV 0; hcodes := [] |}.
Local Hint Resolve hC_correct.
Lemma hO_correct:
WHEN hO tt ~> n THEN (data n)=O.
Proof.
wlp_simplify.
Qed.
Global Opaque hO.
Hint Resolve hO_correct: wlp.
Definition hS: hashV nat -> ?? hashV nat :=
fun x =>
hC {| hdata :=liftHV (S (data x)); hcodes := [hid x] |}.
Lemma hS_correct n:
WHEN hS n ~> n' THEN (data n')=(S (data n)).
Proof.
wlp_simplify.
Qed.
Global Opaque hS.
Hint Resolve hS_correct: wlp.
(* Second, we use these hashed constructors ! *)
Fixpoint builder (x:nat): ?? hashV nat :=
match x with
| O => hO tt
| S n =>
DO n' <~ builder n;;
(* print "*";; *)
hS n'
end.
Lemma builder_correct:
forall x, WHEN builder x ~> x' THEN x=(data x').
Proof.
induction x; simpl; wlp_simplify.
Qed.
Global Opaque builder.
End Building.
(* Now, we build the hash-Cons value from a "hasheq".
Informal specification:
[hash_eq] must be consistent with the "hashed" constructors defined above.
We expect that hashinfo values in the code of these "hashed" constructors verify:
(hasheq (data (hdata x)) (data (hdata y)) ~> true) <-> (hcodes x)=(hcodes y)
*)
Definition hasheq (x y: nat): ?? bool :=
match x, y with
| S x', S y' => phys_eq x' y'
| O, O => RET true
| _, _ => RET false
end.
Lemma hasheq_correct: forall x y, WHEN hasheq x y ~> b THEN b=true -> x=y.
Proof.
destruct x, y; wlp_simplify; try discriminate.
Qed.
Global Opaque hasheq.
Hint Resolve hasheq_correct builder_correct: wlp.
Local Open Scope string_scope.
Definition pretty_hashinfo {A} (k: pstring -> ?? A) (x: hashinfo (hashV nat)) : ?? A :=
match data (hdata x), hcodes x with
| 0, _ => k "O"
| S n, [nid] =>
DO s <~ string_of_hashcode nid ;;
k ("S " +; (CamlStr s))
| _, _ => FAILWITH "unexpected hcodes"
end.
Definition unknownHash_msg: pstring := "unknown hashed value".
Fixpoint print_head (head: list pstring): ?? unit :=
match head with
| s::head' => println ("- " +; s);; print_head head'
| _ => RET tt
end.
Definition example (x y: nat) (fail: bool): ?? unit :=
println "START example";;
DO ko <~ hasheq x y ;;
assert_b (negb ko) "not supposed to be hash_eq, but only =";;
DO hco <~ hConsV hasheq;;
println "builder1";;
DO x' <~ builder (hC hco) x;;
next_log hco "ending builder1";;
println "builder2";;
DO y' <~ builder (hC hco) y;;
next_log hco "ending builder2";;
println "eq_test";;
DO ok <~ phys_eq x' y' ;;
assert_b ok "inputs are supposed to be =" ;;
let k := S (max x y) in
println "builder3";;
let hC_known := hC_known hco (pretty_hashinfo (fun v => RET (unknownHash_msg +; " in " +; v))) in
builder (if fail then hC_known else (hC hco)) k;;
next_log hco "ending builder3";;
println "SUCCESS of example";;
println "PRINT the table:" ;;
DO exp <~ export hco tt ;;
iterall exp (fun o hid d =>
print_head o;;
DO s <~ string_of_hashcode hid ;;
print ((CamlStr s) +; ": ");;
pretty_hashinfo println d)
.
Definition example_correct x y fail:
WHEN example x y fail ~> _ THEN x=y.
Proof.
wlp_simplify.
Qed.
Definition test_example x y fail: ?? unit :=
println "";;
TRY
example x y fail
WITH_FAIL s, e =>
println ("FAILURE of example: " +; s).
Local Open Scope nat.
Fixpoint dup (x:nat): nat :=
match x with
| O => O
| S n => S (dup n)
end.
Definition test: ?? unit :=
let n:=100 in
test_example n n false;;
test_example (S (S n)) n false;;
test_example n (dup n) true;;
test_example n (dup n) false.
End TestNat.
(*************************)
(* Extraction directives *)
Require Import ExtrOcamlString.
Require Import ExtrOcamlBasic.
Import ImpConfig.
Extraction Blacklist List String.
Separate Extraction BinInt ImpPrelude TestNat.