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
|
module Contract.Usage ( checkContractUsage ) where
import List
import FlatCurry.Annotated.Goodies
import FlatCurry.Typed.Types
import Contract.Names
checkContractUsage :: TAProg -> [(QName,String)]
checkContractUsage prog =
let mn = progName prog
allops = map nameArityOfFunDecl (progFuncs prog)
allopsnames = map fst3 allops
specops = map (\ (n,a,t) ->
(fromSpecName (decodeContractName n), a, t))
(funDeclsWithNameArity isSpecName prog)
preops = map (\ (n,a,t) ->
(fromPreCondName (decodeContractName n), a, t))
(funDeclsWithNameArity isPreCondName prog)
postops = map (\ (n,a,t) ->
(fromPostCondName (decodeContractName n), a-1, t))
(funDeclsWithNameArity isPostCondName prog)
nonfailops = map (\ (n,a,t) ->
(fromNonFailName (decodeContractName n), a, t))
(funDeclsWithNameArity isNonFailName prog)
onlyprecond = map fst3 preops \\ allopsnames
onlypostcond = map fst3 postops \\ allopsnames
onlyspec = map fst3 specops \\ allopsnames
onlynonfail = map fst3 nonfailops \\ allopsnames
errmsg = "No implementation for this "
preerrs = map (\ n -> ((mn, toPreCondName n), errmsg ++ "precondition"))
onlyprecond
posterrs = map (\ n -> ((mn, toPostCondName n),errmsg ++ "postcondition"))
onlypostcond
specerrs = map (\ n -> ((mn, toSpecName n), errmsg ++ "specification"))
onlyspec
nferrs = map (\ n -> ((mn, toNonFailName n),
errmsg ++ "non-fail condition"))
onlynonfail
in preerrs ++ posterrs ++ specerrs ++ nferrs ++
checkNonFailTypes mn allops nonfailops ++
checkPreTypes mn allops preops ++
checkPostTypes mn allops postops ++
checkSpecTypes mn allops specops
where
fst3 (x,_,_) = x
checkNonFailTypes :: String -> [(String,Int,TypeExpr)]
-> [(String,Int,TypeExpr)] -> [(QName,String)]
checkNonFailTypes mn allops nfops = concatMap checkNonFailTypeOf nfops
where
checkNonFailTypeOf (n,_,t) =
maybe (notFoundError "non-fail condition" (mn,n))
(\ (_,_,ft) -> checkNonFailType n t ft)
(find (\ (f,_,_) -> f == n) allops)
checkNonFailType n pt ft
| resultType pt /= TCons ("Prelude","Bool") []
= illegalTypeError "Non-fail condition" (mn, toNonFailName n)
| argTypes pt /= argTypes ft
= wrongTypeError "non-fail condition" (mn, toNonFailName n)
| otherwise
= []
checkPreTypes :: String -> [(String,Int,TypeExpr)] -> [(String,Int,TypeExpr)]
-> [(QName,String)]
checkPreTypes mn allops preops = concatMap checkPreTypeOf preops
where
checkPreTypeOf (n,_,t) =
maybe (notFoundError "precondition" (mn,n))
(\ (_,_,ft) -> checkPreType n t ft)
(find (\ (f,_,_) -> f == n) allops)
checkPreType n pt ft
| resultType pt /= TCons ("Prelude","Bool") []
= illegalTypeError "Precondition" (mn, toPreCondName n)
| argTypes pt /= argTypes ft
= wrongTypeError "precondition" (mn, toPreCondName n)
| otherwise
= []
checkPostTypes :: String -> [(String,Int,TypeExpr)] -> [(String,Int,TypeExpr)]
-> [(QName,String)]
checkPostTypes mn allops postops = concatMap checkPostTypeOf postops
where
checkPostTypeOf (n,_,t) =
maybe (notFoundError "postcondition" (mn,n))
(\ (_,_,ft) -> checkPostType n t ft)
(find (\ (f,_,_) -> f == n) allops)
checkPostType n pt ft
| resultType pt /= TCons ("Prelude","Bool") []
= illegalTypeError "Postcondition" (mn, toPostCondName n)
| argTypes pt /= argTypes ft ++ [resultType ft]
= wrongTypeError "postcondition" (mn, toPostCondName n)
| otherwise
= []
checkSpecTypes :: String -> [(String,Int,TypeExpr)] -> [(String,Int,TypeExpr)]
-> [(QName,String)]
checkSpecTypes mn allops specops = concatMap checkSpecTypeOf specops
where
checkSpecTypeOf (n,_,t) =
maybe (notFoundError "specification" (mn,n))
(\ (_,_,ft) -> checkSpecType n t ft)
(find (\ (f,_,_) -> f == n) allops)
checkSpecType n pt ft
| pt /= ft
= wrongTypeError "specification" (mn, toSpecName n)
| otherwise
= []
notFoundError :: String -> QName -> [(QName,String)]
notFoundError cond qn =
[(qn, "Operation for " ++ cond ++ " not found!")]
illegalTypeError :: String -> QName -> [(QName,String)]
illegalTypeError cond qn = [(qn, cond ++ " has illegal type")]
wrongTypeError :: String -> QName -> [(QName,String)]
wrongTypeError cond qn = [(qn, "Type of " ++ cond ++ " does not match")]
funDeclsWithNameArity :: (String -> Bool) -> TAProg
-> [(String,Int,TypeExpr)]
funDeclsWithNameArity pred prog =
map nameArityOfFunDecl
(filter (pred . snd . funcName) (progFuncs prog))
nameArityOfFunDecl :: TAFuncDecl -> (String,Int,TypeExpr)
nameArityOfFunDecl fd = (snd (funcName fd), length (argTypes ftype), ftype)
where
ftype = funcType fd
|