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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
|
module FlatCurry.Typed.NonDet2Det
( nondetOfFuncDecls, addChoiceFuncDecl )
where
import Data.List ( maximum, nub )
import FlatCurry.Annotated.Goodies
import FlatCurry.Typed.Goodies ( funcsOfExpr, pre )
import FlatCurry.Typed.Types
nondetOfFuncDecls :: [TAFuncDecl] -> [(QName,Bool)]
nondetOfFuncDecls fds = ndIterate (map (\fd -> (funcName fd, False)) fds)
where
ndIterate nds =
let newnds = map (\fd -> (funcName fd, isNonDetFunc nds fd)) fds
in if newnds == nds then nds
else ndIterate newnds
isNonDetFunc nds fdecl =
choiceName `elem` fs || or (map (\f -> maybe False id (lookup f nds)) fs)
where fs = choicesOfFuncDecl fdecl
choicesOfFuncDecl :: TAFuncDecl -> [QName]
choicesOfFuncDecl fd =
nub (trRule (\_ _ e -> choicesOfExp e) (\_ _ -> []) (funcRule fd))
where
choicesOfExp =
trExpr (\_ _ -> [])
(\_ _ -> [])
(\_ ct (qn,_) fs ->
if isCombTypeFuncCall ct || isCombTypeFuncPartCall ct
then qn : concat fs
else concat fs)
(\_ bs fs -> concatMap snd bs ++ fs)
(\_ _ _ -> [choiceName])
(\_ _ _ -> [choiceName])
(\_ _ fs fss -> concat (fs:fss))
(\_ -> id)
(\_ fs _ -> fs)
choiceName :: QName
choiceName = pre "?"
hasNonDetInfo :: [(QName,Bool)] -> QName -> Bool
hasNonDetInfo ndinfo qn = maybe False id (lookup qn ndinfo)
addChoiceFuncDecl :: [(QName,Bool)] -> (TypeExpr,QName,QName,QName)
-> TAFuncDecl -> TAFuncDecl
addChoiceFuncDecl _ _ fdecl@(AFunc _ _ _ _ (AExternal _ _)) = fdecl
addChoiceFuncDecl ndinfo (cpType,chooseF,lchoiceF,rchoiceF)
fdecl@(AFunc qn ar vis texp (ARule tr args rhs)) =
if hasNonDetInfo ndinfo qn
then AFunc qn (ar + 1) vis (FuncType cpType texp)
(ARule tr (carg : args) (snd (choiceExp choices rhs)))
else fdecl
where
cpVar = maximum (0 : map fst args ++ allVars rhs) + 1
carg = (cpVar, cpType)
numnds = orOfExpr rhs +
length (filter (hasNonDetInfo ndinfo) (funcsOfExpr rhs))
choices = choicesFor numnds (AVar cpType cpVar)
choiceExp chs exp = case exp of
ALit _ _ -> (chs,exp)
AVar _ _ -> (chs,exp)
AComb te ct (qf,qt) cargs ->
if hasNonDetInfo ndinfo qf
then let (ch1,targs) = choiceExps (tail chs) cargs in
(ch1, AComb te ct (qf, FuncType cpType qt) (head chs : targs))
else let (ch1,targs) = choiceExps chs cargs in
(ch1, AComb te ct (qf,qt) targs)
ACase te ct e brs ->
let (ch1,e1:bes1) = choiceExps chs (e : map (\ (ABranch _ be) -> be) brs)
in (ch1, ACase te ct e1
(map (\ (ABranch p _,be1) -> ABranch p be1) (zip brs bes1)))
AOr te e1 e2 ->
let (ch1,es) = choiceExps (tail chs) [e1,e2] in
(ch1,
AComb te FuncCall
(pre "if_then_else",
FuncType (TCons (pre "Bool") []) (FuncType te (FuncType te te)))
(AComb boolType FuncCall (chooseF, chooseType) [head chs] : es))
ALet te bs e ->
let (ch1,e1:bes1) = choiceExps chs (e : map snd bs)
in (ch1, ALet te (zip (map fst bs) bes1) e1)
AFree te fvs e -> let (ch1,e1) = choiceExp chs e
in (ch1, AFree te fvs e1)
ATyped te e ty -> let (ch1,e1) = choiceExp chs e
in (ch1, ATyped te e1 ty)
where
boolType = TCons (pre "Bool") []
chooseType = FuncType cpType boolType
choiceExps chs [] = (chs,[])
choiceExps chs (e:es) = let (ch1,e1) = choiceExp chs e
(ch2,es1) = choiceExps ch1 es
in (ch2, e1:es1)
choicesFor :: Int -> TAExpr -> [TAExpr]
choicesFor n ch
| n <= 1
= [ch]
| otherwise
= choicesFor (n `div` 2)
(AComb cpType FuncCall (lchoiceF, lrchType) [ch]) ++
choicesFor (n - n `div` 2)
(AComb cpType FuncCall (rchoiceF, lrchType) [ch])
where
lrchType = FuncType cpType cpType
orOfExpr :: TAExpr -> Int
orOfExpr = trExpr (\_ _ -> 0)
(\_ _ -> 0)
(\_ _ _ ns -> foldr (+) 0 ns)
(\_ bs n -> n + foldr (+) 0 (map snd bs))
(\_ _ n -> n)
(\_ n1 n2 -> 1 + n1 + n2)
(\_ _ n bs -> n + foldr (+) 0 bs)
(\_ n -> n)
(\_ n _ -> n)
dropArgTypes :: Int -> TypeExpr -> TypeExpr
dropArgTypes n ty
| n==0 = ty
| otherwise = case ty of FuncType _ rt -> dropArgTypes (n-1) rt
_ -> error "dropArgTypes: too few argument types"
|