comparison src/rpcify.sml @ 956:d80734855790

Don't try to check if functions are already tail-recursive
author Adam Chlipala <adamc@hcoop.net>
date Thu, 17 Sep 2009 17:17:49 -0400
parents 01a4d936395a
children 2831be2daf2e
comparison
equal deleted inserted replaced
955:01a4d936395a 956:d80734855790
168 val (d, st) = 168 val (d, st) =
169 case #1 d of 169 case #1 d of
170 DValRec vis => 170 DValRec vis =>
171 if List.exists (fn (_, _, _, e, _) => makesServerCall e) vis then 171 if List.exists (fn (_, _, _, e, _) => makesServerCall e) vis then
172 let 172 let
173 val all = foldl (fn ((_, n, _, _, _), all) => IS.add (all, n)) IS.empty vis 173 val rpc = foldl (fn ((_, n, _, _, _), rpc) =>
174 174 IS.add (rpc, n)) (#rpc st) vis
175 val usesRec = U.Exp.exists {kind = fn _ => false, 175
176 con = fn _ => false, 176 val (cpsed, vis') =
177 exp = fn ENamed n => IS.member (all, n) 177 foldl (fn (vi as (x, n, t, e, s), (cpsed, vis')) =>
178 | _ => false} 178 let
179 179 fun getArgs (t, acc) =
180 val noRec = not o usesRec 180 case #1 t of
181 181 TFun (dom, ran) =>
182 fun tailOnly (e, _) = 182 getArgs (ran, dom :: acc)
183 case e of 183 | _ => (rev acc, t)
184 EPrim _ => true 184 val (ts, ran) = getArgs (t, [])
185 | ERel _ => true 185 val ran = case #1 ran of
186 | ENamed _ => true 186 CApp (_, ran) => ran
187 | ECon (_, _, _, SOME e) => noRec e 187 | _ => raise Fail "Rpcify: Tail function not transactional"
188 | ECon _ => true 188 val len = length ts
189 | EFfi _ => true 189
190 | EFfiApp (_, _, es) => List.all noRec es 190 val loc = #2 e
191 | EApp (e1, e2) => noRec e2 andalso tailOnly e1 191 val args = ListUtil.mapi
192 | EAbs (_, _, _, e) => noRec e 192 (fn (i, _) =>
193 | ECApp (e1, _) => tailOnly e1 193 (ERel (len - i - 1), loc))
194 | ECAbs (_, _, e) => noRec e 194 ts
195 195 val k = (EFfi ("Basis", "return"), loc)
196 | EKAbs (_, e) => noRec e 196 val trans = (CFfi ("Basis", "transaction"), loc)
197 | EKApp (e1, _) => tailOnly e1 197 val k = (ECApp (k, trans), loc)
198 198 val k = (ECApp (k, ran), loc)
199 | ERecord xes => List.all (noRec o #2) xes 199 val k = (EApp (k, (EFfi ("Basis", "transaction_monad"),
200 | EField (e1, _, _) => noRec e1 200 loc)), loc)
201 | EConcat (e1, _, e2, _) => noRec e1 andalso noRec e2 201 val re = (ETailCall (n, args, k, ran, ran), loc)
202 | ECut (e1, _, _) => noRec e1 202 val (re, _) = foldr (fn (dom, (re, ran)) =>
203 | ECutMulti (e1, _, _) => noRec e1 203 ((EAbs ("x", dom, ran, re),
204 204 loc),
205 | ECase (e1, pes, _) => noRec e1 andalso List.all (tailOnly o #2) pes 205 (TFun (dom, ran), loc)))
206 206 (re, ran) ts
207 | EWrite e1 => noRec e1 207
208 208 val be = multiLiftExpInExp (len + 1) e
209 | EClosure (_, es) => List.all noRec es 209 val be = ListUtil.foldli
210 210 (fn (i, _, be) =>
211 | ELet (_, _, e1, e2) => noRec e1 andalso tailOnly e2 211 (EApp (be, (ERel (len - i), loc)), loc))
212 212 be ts
213 | EServerCall (_, es, (EAbs (_, _, _, e), _), _, _) => 213 val ne = (EFfi ("Basis", "bind"), loc)
214 List.all noRec es andalso tailOnly e 214 val ne = (ECApp (ne, trans), loc)
215 | EServerCall (_, es, e, _, _) => List.all noRec es andalso noRec e 215 val ne = (ECApp (ne, ran), loc)
216 216 val unit = (TRecord (CRecord ((KType, loc), []),
217 | ETailCall _ => raise Fail "Rpcify: ETailCall too early" 217 loc), loc)
218 218 val ne = (ECApp (ne, unit), loc)
219 fun tailOnlyF e = 219 val ne = (EApp (ne, (EFfi ("Basis", "transaction_monad"),
220 case #1 e of 220 loc)), loc)
221 EAbs (_, _, _, e) => tailOnlyF e 221 val ne = (EApp (ne, be), loc)
222 | ECAbs (_, _, e) => tailOnlyF e 222 val ne = (EApp (ne, (ERel 0, loc)), loc)
223 | EKAbs (_, e) => tailOnlyF e 223 val tunit = (CApp (trans, unit), loc)
224 | _ => tailOnly e 224 val kt = (TFun (ran, tunit), loc)
225 225 val ne = (EAbs ("k", kt, tunit, ne), loc)
226 val nonTail = foldl (fn ((_, n, _, e, _), nonTail) => 226 val (ne, res) = foldr (fn (dom, (ne, ran)) =>
227 if tailOnlyF e then 227 ((EAbs ("x", dom, ran, ne), loc),
228 nonTail 228 (TFun (dom, ran), loc)))
229 else 229 (ne, (TFun (kt, tunit), loc)) ts
230 IS.add (nonTail, n)) IS.empty vis 230 in
231 (IM.insert (cpsed, n, #1 re),
232 (x, n, res, ne, s) :: vis')
233 end)
234 (#cpsed st, []) vis
231 in 235 in
232 if IS.isEmpty nonTail then 236 ((DValRec (rev vis'), ErrorMsg.dummySpan),
233 (d, {exported = #exported st, 237 {exported = #exported st,
234 export_decls = #export_decls st, 238 export_decls = #export_decls st,
235 cpsed = #cpsed st, 239 cpsed = cpsed,
236 rpc = IS.union (#rpc st, all)}) 240 rpc = rpc})
237 else
238 let
239 val rpc = foldl (fn ((_, n, _, _, _), rpc) =>
240 IS.add (rpc, n)) (#rpc st) vis
241
242 val (cpsed, vis') =
243 foldl (fn (vi as (x, n, t, e, s), (cpsed, vis')) =>
244 if IS.member (nonTail, n) then
245 let
246 fun getArgs (t, acc) =
247 case #1 t of
248 TFun (dom, ran) =>
249 getArgs (ran, dom :: acc)
250 | _ => (rev acc, t)
251 val (ts, ran) = getArgs (t, [])
252 val ran = case #1 ran of
253 CApp (_, ran) => ran
254 | _ => raise Fail "Rpcify: Tail function not transactional"
255 val len = length ts
256
257 val loc = #2 e
258 val args = ListUtil.mapi
259 (fn (i, _) =>
260 (ERel (len - i - 1), loc))
261 ts
262 val k = (EFfi ("Basis", "return"), loc)
263 val trans = (CFfi ("Basis", "transaction"), loc)
264 val k = (ECApp (k, trans), loc)
265 val k = (ECApp (k, ran), loc)
266 val k = (EApp (k, (EFfi ("Basis", "transaction_monad"),
267 loc)), loc)
268 val re = (ETailCall (n, args, k, ran, ran), loc)
269 val (re, _) = foldr (fn (dom, (re, ran)) =>
270 ((EAbs ("x", dom, ran, re),
271 loc),
272 (TFun (dom, ran), loc)))
273 (re, ran) ts
274
275 val be = multiLiftExpInExp (len + 1) e
276 val be = ListUtil.foldli
277 (fn (i, _, be) =>
278 (EApp (be, (ERel (len - i), loc)), loc))
279 be ts
280 val ne = (EFfi ("Basis", "bind"), loc)
281 val ne = (ECApp (ne, trans), loc)
282 val ne = (ECApp (ne, ran), loc)
283 val unit = (TRecord (CRecord ((KType, loc), []),
284 loc), loc)
285 val ne = (ECApp (ne, unit), loc)
286 val ne = (EApp (ne, (EFfi ("Basis", "transaction_monad"),
287 loc)), loc)
288 val ne = (EApp (ne, be), loc)
289 val ne = (EApp (ne, (ERel 0, loc)), loc)
290 val tunit = (CApp (trans, unit), loc)
291 val kt = (TFun (ran, tunit), loc)
292 val ne = (EAbs ("k", kt, tunit, ne), loc)
293 val (ne, res) = foldr (fn (dom, (ne, ran)) =>
294 ((EAbs ("x", dom, ran, ne), loc),
295 (TFun (dom, ran), loc)))
296 (ne, (TFun (kt, tunit), loc)) ts
297 in
298 (IM.insert (cpsed, n, #1 re),
299 (x, n, res, ne, s) :: vis')
300 end
301 else
302 (cpsed, vi :: vis'))
303 (#cpsed st, []) vis
304 in
305 ((DValRec (rev vis'), ErrorMsg.dummySpan),
306 {exported = #exported st,
307 export_decls = #export_decls st,
308 cpsed = cpsed,
309 rpc = rpc})
310 end
311 end 241 end
312 else 242 else
313 (d, st) 243 (d, st)
314 | DVal (x, n, t, e, s) => 244 | DVal (x, n, t, e, s) =>
315 (d, 245 (d,