304 code_const "op \<guillemotright>=" (OCaml "!(fun/ f'_/ ()/ ->/ f'_/ (_/ ())/ ())") |
304 code_const "op \<guillemotright>=" (OCaml "!(fun/ f'_/ ()/ ->/ f'_/ (_/ ())/ ())") |
305 code_const return (OCaml "!(fun/ ()/ ->/ _)") |
305 code_const return (OCaml "!(fun/ ()/ ->/ _)") |
306 code_const "Heap_Monad.Fail" (OCaml "Failure") |
306 code_const "Heap_Monad.Fail" (OCaml "Failure") |
307 code_const "Heap_Monad.raise_exc" (OCaml "!(fun/ ()/ ->/ raise/ _)") |
307 code_const "Heap_Monad.raise_exc" (OCaml "!(fun/ ()/ ->/ raise/ _)") |
308 |
308 |
309 setup {* let |
309 setup {* |
310 open Code_Thingol; |
310 |
311 |
311 let |
312 fun lookup naming = the o Code_Thingol.lookup_const naming; |
312 |
313 |
313 open Code_Thingol; |
314 fun imp_monad_bind'' bind' return' unit' ts = |
314 |
315 let |
315 fun imp_program naming = |
316 val dummy_name = ""; |
316 |
317 val dummy_type = ITyVar dummy_name; |
317 let |
318 val dummy_case_term = IVar dummy_name; |
318 fun is_const c = case lookup_const naming c |
319 (*assumption: dummy values are not relevant for serialization*) |
319 of SOME c' => (fn c'' => c' = c'') |
320 val unitt = IConst (unit', (([], []), [])); |
320 | NONE => K false; |
321 fun dest_abs ((v, ty) `|=> t, _) = ((v, ty), t) |
321 val is_bindM = is_const @{const_name bindM}; |
322 | dest_abs (t, ty) = |
322 val is_return = is_const @{const_name return}; |
323 let |
323 val dummy_name = "X"; |
324 val vs = Code_Thingol.fold_varnames cons t []; |
324 val dummy_type = ITyVar dummy_name; |
325 val v = Name.variant vs "x"; |
325 val dummy_case_term = IVar ""; |
326 val ty' = (hd o fst o Code_Thingol.unfold_fun) ty; |
326 (*assumption: dummy values are not relevant for serialization*) |
327 in ((v, ty'), t `$ IVar v) end; |
327 val unitt = case lookup_const naming @{const_name Unity} |
328 fun force (t as IConst (c, _) `$ t') = if c = return' |
328 of SOME unit' => IConst (unit', (([], []), [])) |
329 then t' else t `$ unitt |
329 | NONE => error ("Must include " ^ @{const_name Unity} ^ " in generated constants."); |
330 | force t = t `$ unitt; |
330 fun dest_abs ((v, ty) `|=> t, _) = ((v, ty), t) |
331 fun tr_bind' [(t1, _), (t2, ty2)] = |
331 | dest_abs (t, ty) = |
332 let |
332 let |
333 val ((v, ty), t) = dest_abs (t2, ty2); |
333 val vs = fold_varnames cons t []; |
334 in ICase (((force t1, ty), [(IVar v, tr_bind'' t)]), dummy_case_term) end |
334 val v = Name.variant vs "x"; |
335 and tr_bind'' t = case Code_Thingol.unfold_app t |
335 val ty' = (hd o fst o unfold_fun) ty; |
336 of (IConst (c, (_, ty1 :: ty2 :: _)), [x1, x2]) => if c = bind' |
336 in ((v, ty'), t `$ IVar v) end; |
337 then tr_bind' [(x1, ty1), (x2, ty2)] |
337 fun force (t as IConst (c, _) `$ t') = if is_return c |
338 else force t |
338 then t' else t `$ unitt |
339 | _ => force t; |
339 | force t = t `$ unitt; |
340 in (dummy_name, dummy_type) `|=> ICase (((IVar dummy_name, dummy_type), |
340 fun tr_bind' [(t1, _), (t2, ty2)] = |
341 [(unitt, tr_bind' ts)]), dummy_case_term) end |
341 let |
342 and imp_monad_bind' bind' return' unit' (const as (c, (_, tys))) ts = if c = bind' then case (ts, tys) |
342 val ((v, ty), t) = dest_abs (t2, ty2); |
343 of ([t1, t2], ty1 :: ty2 :: _) => imp_monad_bind'' bind' return' unit' [(t1, ty1), (t2, ty2)] |
343 in ICase (((force t1, ty), [(IVar v, tr_bind'' t)]), dummy_case_term) end |
344 | ([t1, t2, t3], ty1 :: ty2 :: _) => imp_monad_bind'' bind' return' unit' [(t1, ty1), (t2, ty2)] `$ t3 |
344 and tr_bind'' t = case unfold_app t |
345 | (ts, _) => imp_monad_bind bind' return' unit' (eta_expand 2 (const, ts)) |
345 of (IConst (c, (_, ty1 :: ty2 :: _)), [x1, x2]) => if is_bindM c |
346 else IConst const `$$ map (imp_monad_bind bind' return' unit') ts |
346 then tr_bind' [(x1, ty1), (x2, ty2)] |
347 and imp_monad_bind bind' return' unit' (IConst const) = imp_monad_bind' bind' return' unit' const [] |
347 else force t |
348 | imp_monad_bind bind' return' unit' (t as IVar _) = t |
348 | _ => force t; |
349 | imp_monad_bind bind' return' unit' (t as _ `$ _) = (case unfold_app t |
349 fun imp_monad_bind'' ts = (dummy_name, dummy_type) `|=> ICase (((IVar dummy_name, dummy_type), |
350 of (IConst const, ts) => imp_monad_bind' bind' return' unit' const ts |
350 [(unitt, tr_bind' ts)]), dummy_case_term) |
351 | (t, ts) => imp_monad_bind bind' return' unit' t `$$ map (imp_monad_bind bind' return' unit') ts) |
351 and imp_monad_bind' (const as (c, (_, tys))) ts = if is_bindM c then case (ts, tys) |
352 | imp_monad_bind bind' return' unit' (v_ty `|=> t) = v_ty `|=> imp_monad_bind bind' return' unit' t |
352 of ([t1, t2], ty1 :: ty2 :: _) => imp_monad_bind'' [(t1, ty1), (t2, ty2)] |
353 | imp_monad_bind bind' return' unit' (ICase (((t, ty), pats), t0)) = ICase |
353 | ([t1, t2, t3], ty1 :: ty2 :: _) => imp_monad_bind'' [(t1, ty1), (t2, ty2)] `$ t3 |
354 (((imp_monad_bind bind' return' unit' t, ty), (map o pairself) (imp_monad_bind bind' return' unit') pats), imp_monad_bind bind' return' unit' t0); |
354 | (ts, _) => imp_monad_bind (eta_expand 2 (const, ts)) |
355 |
355 else IConst const `$$ map imp_monad_bind ts |
356 fun imp_program naming = (Graph.map_nodes o map_terms_stmt) |
356 and imp_monad_bind (IConst const) = imp_monad_bind' const [] |
357 (imp_monad_bind (lookup naming @{const_name bindM}) |
357 | imp_monad_bind (t as IVar _) = t |
358 (lookup naming @{const_name return}) |
358 | imp_monad_bind (t as _ `$ _) = (case unfold_app t |
359 (lookup naming @{const_name Unity})); |
359 of (IConst const, ts) => imp_monad_bind' const ts |
|
360 | (t, ts) => imp_monad_bind t `$$ map imp_monad_bind ts) |
|
361 | imp_monad_bind (v_ty `|=> t) = v_ty `|=> imp_monad_bind t |
|
362 | imp_monad_bind (ICase (((t, ty), pats), t0)) = ICase |
|
363 (((imp_monad_bind t, ty), |
|
364 (map o pairself) imp_monad_bind pats), |
|
365 imp_monad_bind t0); |
|
366 |
|
367 in (Graph.map_nodes o map_terms_stmt) imp_monad_bind end; |
360 |
368 |
361 in |
369 in |
362 |
370 |
363 Code_Target.extend_target ("SML_imp", ("SML", imp_program)) |
371 Code_Target.extend_target ("SML_imp", ("SML", imp_program)) |
364 #> Code_Target.extend_target ("OCaml_imp", ("OCaml", imp_program)) |
372 #> Code_Target.extend_target ("OCaml_imp", ("OCaml", imp_program)) |
365 |
373 |
366 end |
374 end |
|
375 |
367 *} |
376 *} |
368 |
|
369 |
377 |
370 code_reserved OCaml Failure raise |
378 code_reserved OCaml Failure raise |
371 |
379 |
372 |
380 |
373 subsubsection {* Haskell *} |
381 subsubsection {* Haskell *} |