My working unpac repository
at opam/upstream/seq 167 lines 5.7 kB view raw
1(**************************************************************************) 2(* *) 3(* OCaml *) 4(* *) 5(* KC Sivaramakrishnan, Indian Institute of Technology, Madras *) 6(* *) 7(* Copyright 2021 Indian Institute of Technology, Madras *) 8(* *) 9(* All rights reserved. This file is distributed under the terms of *) 10(* the GNU Lesser General Public License version 2.1, with the *) 11(* special exception on linking described in the file LICENSE. *) 12(* *) 13(**************************************************************************) 14 15type 'a t = 'a eff = .. 16external perform : 'a t -> 'a = "%perform" 17 18type exn += Unhandled: 'a t -> exn 19exception Continuation_already_resumed 20 21let () = 22 let printer = function 23 | Unhandled x -> 24 let msg = Printf.sprintf "Stdlib.Effect.Unhandled(%s)" 25 (Printexc.string_of_extension_constructor @@ Obj.repr x) 26 in 27 Some msg 28 | _ -> None 29 in 30 Printexc.register_printer printer 31 32(* Register the exceptions so that the runtime can access it *) 33type _ t += Should_not_see_this__ : unit t 34let _ = Callback.register_exception "Effect.Unhandled" 35 (Unhandled Should_not_see_this__) 36let _ = Callback.register_exception "Effect.Continuation_already_resumed" 37 Continuation_already_resumed 38 39type ('a, 'b) stack [@@immediate] 40type last_fiber [@@immediate] 41 42external resume : 43 ('a, 'b) stack -> ('c -> 'a) -> 'c -> last_fiber -> 'b = "%resume" 44external runstack : ('a, 'b) stack -> ('c -> 'a) -> 'c -> 'b = "%runstack" 45 46module Deep = struct 47 48 type nonrec ('a,'b) continuation = ('a,'b) continuation 49 50 external take_cont_noexc : ('a, 'b) continuation -> ('a, 'b) stack = 51 "caml_continuation_use_noexc" [@@noalloc] 52 external alloc_stack : 53 ('a -> 'b) -> 54 (exn -> 'b) -> 55 ('c t -> ('c, 'b) continuation -> last_fiber -> 'b) -> 56 ('a, 'b) stack = "caml_alloc_stack" 57 external cont_last_fiber : ('a, 'b) continuation -> last_fiber = "%field1" 58 59 let continue k v = 60 resume (take_cont_noexc k) (fun x -> x) v (cont_last_fiber k) 61 62 let discontinue k e = 63 resume (take_cont_noexc k) (fun e -> raise e) e (cont_last_fiber k) 64 65 let discontinue_with_backtrace k e bt = 66 resume (take_cont_noexc k) (fun e -> Printexc.raise_with_backtrace e bt) 67 e (cont_last_fiber k) 68 69 type ('a,'b) handler = 70 { retc: 'a -> 'b; 71 exnc: exn -> 'b; 72 effc: 'c.'c t -> (('c,'b) continuation -> 'b) option } 73 74 external reperform : 75 'a t -> ('a, 'b) continuation -> last_fiber -> 'b = "%reperform" 76 77 let match_with comp arg handler = 78 let effc eff k last_fiber = 79 match handler.effc eff with 80 | Some f -> f k 81 | None -> reperform eff k last_fiber 82 in 83 let s = alloc_stack handler.retc handler.exnc effc in 84 runstack s comp arg 85 86 type 'a effect_handler = 87 { effc: 'b. 'b t -> (('b,'a) continuation -> 'a) option } 88 89 let try_with comp arg handler = 90 let effc' eff k last_fiber = 91 match handler.effc eff with 92 | Some f -> f k 93 | None -> reperform eff k last_fiber 94 in 95 let s = alloc_stack (fun x -> x) (fun e -> raise e) effc' in 96 runstack s comp arg 97 98 external get_callstack : 99 ('a,'b) continuation -> int -> Printexc.raw_backtrace = 100 "caml_get_continuation_callstack" 101end 102 103module Shallow = struct 104 105 type ('a,'b) continuation 106 107 external alloc_stack : 108 ('a -> 'b) -> 109 (exn -> 'b) -> 110 ('c t -> ('c, 'b) continuation -> last_fiber -> 'b) -> 111 ('a, 'b) stack = "caml_alloc_stack" 112 113 external cont_last_fiber : ('a, 'b) continuation -> last_fiber = "%field1" 114 115 let fiber : type a b. (a -> b) -> (a, b) continuation = fun f -> 116 let module M = struct type _ t += Initial_setup__ : a t end in 117 let exception E of (a,b) continuation in 118 let f' () = f (perform M.Initial_setup__) in 119 let error _ = failwith "impossible" in 120 let effc eff k _last_fiber = 121 match eff with 122 | M.Initial_setup__ -> raise_notrace (E k) 123 | _ -> error () 124 in 125 let s = alloc_stack error error effc in 126 match runstack s f' () with 127 | exception E k -> k 128 | _ -> error () 129 130 type ('a,'b) handler = 131 { retc: 'a -> 'b; 132 exnc: exn -> 'b; 133 effc: 'c.'c t -> (('c,'a) continuation -> 'b) option } 134 135 external update_handler : 136 ('a,'b) continuation -> 137 ('b -> 'c) -> 138 (exn -> 'c) -> 139 ('d t -> ('d,'b) continuation -> last_fiber -> 'c) -> 140 ('a,'c) stack = "caml_continuation_use_and_update_handler_noexc" [@@noalloc] 141 142 external reperform : 143 'a t -> ('a, 'b) continuation -> last_fiber -> 'c = "%reperform" 144 145 let continue_gen k resume_fun v handler = 146 let effc eff k last_fiber = 147 match handler.effc eff with 148 | Some f -> f k 149 | None -> reperform eff k last_fiber 150 in 151 let last_fiber = cont_last_fiber k in 152 let stack = update_handler k handler.retc handler.exnc effc in 153 resume stack resume_fun v last_fiber 154 155 let continue_with k v handler = 156 continue_gen k (fun x -> x) v handler 157 158 let discontinue_with k v handler = 159 continue_gen k (fun e -> raise e) v handler 160 161 let discontinue_with_backtrace k v bt handler = 162 continue_gen k (fun e -> Printexc.raise_with_backtrace e bt) v handler 163 164 external get_callstack : 165 ('a,'b) continuation -> int -> Printexc.raw_backtrace = 166 "caml_get_continuation_callstack" 167end