-
Notifications
You must be signed in to change notification settings - Fork 1
/
095-check_dict_case.dfy
52 lines (46 loc) · 1.37 KB
/
095-check_dict_case.dfy
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
predicate IsLowerCase(s: string)
{
forall i :: 0 <= i < |s| ==> 'a' <= s[i] <= 'z'
}
predicate IsUpperCase(s: string)
{
forall i :: 0 <= i < |s| ==> 'A' <= s[i] <= 'Z'
}
type DictCase = map<string, string>
method CheckDictCase(dict: DictCase) returns (result: bool)
// post-conditions-start
ensures dict == map[] ==> !result
ensures result ==> (forall k :: k in dict ==> IsLowerCase(k)) || (forall k :: k in dict ==> IsUpperCase(k))
ensures !result ==> dict == map[] || ((exists k :: k in dict && !IsLowerCase(k)) && (exists k :: k in dict && !IsUpperCase(k)))
// post-conditions-end
{
// impl-start
if |dict| == 0 {
return false;
}
var allLower := true;
var allUpper := true;
var keys := dict.Keys;
while keys != {}
// invariants-start
invariant allLower ==> forall j :: j in dict.Keys - keys ==> IsLowerCase(j)
invariant allUpper ==> forall j :: j in dict.Keys - keys ==> IsUpperCase(j)
invariant !allLower ==> exists j :: j in dict.Keys - keys && !IsLowerCase(j)
invariant !allUpper ==> exists j :: j in dict.Keys - keys && !IsUpperCase(j)
// invariants-end
{
var k :| k in keys;
if !IsLowerCase(k) {
allLower := false;
}
if !IsUpperCase(k) {
allUpper := false;
}
if !allLower && !allUpper {
return false;
}
keys := keys - {k};
}
result := allLower || allUpper;
// impl-end
}