-
Notifications
You must be signed in to change notification settings - Fork 78
/
Copy pathquantifiers.rs
100 lines (88 loc) · 2.86 KB
/
quantifiers.rs
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
#[allow(unused_imports)]
use builtin::*;
use builtin_macros::*;
fn main() {}
verus! {
spec fn f1(i: int, j: int) -> bool {
i <= j
}
spec fn f2(i: int, j: int) -> bool {
i >= j
}
spec fn g1(i: int) -> int {
i + 1
}
spec fn g2(i: int) -> int {
i + 2
}
spec fn g3(i: int) -> int {
i + 3
}
// Automatically chosen triggers
fn test_auto() {
// :pattern ((f1. i@ j@))
assert(forall|i: int, j: int| i == j ==> f1(i, j));
// :pattern ((f1. i@ j@))
assert(forall|i: int, j: int| i == j ==> f1(i, j) && f1(i, j));
// :pattern ((f1. j@ i@))
// :pattern ((f1. i@ j@))
assert(forall|i: int, j: int| i == j ==> f1(i, j) || f1(j, i));
// :pattern ((f1. i@ j@))
// note: f1(i, j) is preferred over splitting i, j among g1(i), g2(j)
assert(forall|i: int, j: int| f1(i, j) ==> g1(i) <= g2(j));
// :pattern ((g1. i@))
// note: g1(i) is preferred over the more deeply nested g3(i)
assert(forall|i: int| #![auto] g1(i) >= i || g2(g3(i)) >= i);
// :pattern ((f1. i@ j@))
// note: f1(i, j) is preferred over the larger f2(j, g1(i))
assert(forall|i: int, j: int| #![auto] i == j ==> f1(i, j) || f2(j, g1(i)));
// :pattern ((f1. j@ (g1. i@)))
// note: f1(i, j) is excluded due to a potential matching loop
assert(forall|i: int, j: int| i == j ==> f1(i, j) || f1(j, g1(i)));
// matching loop, no trigger
// assert(forall|i: int, j: int| i == j ==> f1(i, j) || f1(j, i + 1));
// :pattern ((f2. j@ i@))
// :pattern ((f1. i@ j@))
assert(forall|i: int, j: int| f2(j, i) ==> f1(i, j));
// :pattern ((g1. j@) (g1. i@))
assert(forall|i: int, j: int| g1(i) >= i && g1(j) >= j);
// :pattern ((g1. i@) (g2. j@))
assert(g1(3) == g2(2));
assert(exists|i: int, j: int| g1(i) == g2(j));
}
// Manually chosen triggers
fn test_manual() {
//
// For single triggers, use #[trigger]
//
// :pattern ((f1. i@ j@))
assert(forall|i: int, j: int| f2(j, i) ==> #[trigger] f1(i, j));
// :pattern ((g1. i@) (g2. j@))
assert(forall|i: int, j: int| f1(i, j) ==> f1(#[trigger] g1(i), #[trigger] g2(j)));
//
// For multiple triggers, use
// with_triggers!([...trigger 1 terms...], ..., [...trigger n terms...] => body)
//
// :pattern ((g1. i@) (g2. j@))
// :pattern ((f1. i@ j@))
assert(forall|i: int, j: int|
#![trigger g1(i), g2(j)]
#![trigger f1(i, j)]
f1(i, j) ==> f1(g1(i), g2(j)));
// :pattern ((g1. i@) (g2. j@))
// :pattern ((f1. i@ j@) (g1. i@))
assert(forall|i: int, j: int|
#![trigger g1(i), g2(j)]
#![trigger f1(i, j), g1(i)]
f1(i, j) ==> f1(g1(i), g2(j)));
}
spec fn tr(i: int) -> bool {
true
}
fn test_nat() {
assert(forall|i: nat| i >= 0 && tr(i as int));
assert(tr(300));
assert(exists|i: nat| i >= 0 && tr(i as int));
assert(exists|i: u16| i >= 300 && tr(i as int));
}
} // verus!