1 ! Copyright (C) 2003, 2011 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs combinators combinators.private kernel
4 kernel.private make namespaces sequences vectors ;
7 : with-datastack ( stack quot -- new-stack )
9 [ [ get-datastack ] dip swap [ { } like set-datastack ] dip ] dip
10 swap [ call get-datastack ] dip
11 swap [ set-datastack ] dip
12 ] ( stack quot -- new-stack ) call-effect-unsafe ;
14 SYMBOL: original-error
16 SYMBOL: error-continuation
22 : (get-catchstack) ( -- catchstack )
23 CONTEXT-OBJ-CATCHSTACK context-object { vector } declare ; inline
25 ! We have to defeat some optimizations to make continuations work
26 : dummy-1 ( -- obj ) f ;
27 : dummy-2 ( obj -- obj ) ;
29 : get-catchstack ( -- catchstack ) (get-catchstack) clone ; inline
31 : (set-catchstack) ( catchstack -- )
32 CONTEXT-OBJ-CATCHSTACK set-context-object ; inline
34 : set-catchstack ( catchstack -- )
35 >vector (set-catchstack) ; inline
37 : init-catchstack ( -- )
38 V{ } clone (set-catchstack) ;
42 TUPLE: continuation data call retain name catch ;
44 C: <continuation> continuation
46 : current-continuation ( -- continuation )
47 get-datastack get-callstack get-retainstack get-namestack get-catchstack
52 ERROR: not-a-continuation object ;
54 : >continuation< ( continuation -- data call retain name catch )
55 dup continuation? [ not-a-continuation ] unless
56 { [ data>> ] [ call>> ] [ retain>> ] [ name>> ] [ catch>> ] } cleave ; inline
60 : ifcc ( capture restore -- )
61 [ dummy-1 current-continuation ] 2dip [ dummy-2 ] prepose ?if ; inline
63 : callcc0 ( quot -- ) [ drop ] ifcc ; inline
65 : callcc1 ( quot -- obj ) [ ] ifcc ; inline
69 : (continue) ( continuation -- * )
77 ] ( continuation -- * ) call-effect-unsafe ;
81 : continue-with ( obj continuation -- * )
83 swap OBJ-CALLCC-1 set-special-object
90 OBJ-CALLCC-1 special-object
91 f OBJ-CALLCC-1 set-special-object
95 ] ( obj continuation -- * ) call-effect-unsafe ;
97 : continue ( continuation -- * )
98 f swap continue-with ;
100 SYMBOL: return-continuation
102 : with-return ( quot -- )
103 [ return-continuation ] dip [ with-variable ] 2curry callcc0 ; inline
106 return-continuation get continue ;
108 GENERIC: compute-restarts ( error -- seq )
112 : save-error ( error -- )
114 [ compute-restarts restarts set-global ] bi ;
118 GENERIC: error-in-thread ( error thread -- * )
120 SYMBOL: thread-error-hook ! ( error thread -- * )
122 thread-error-hook [ [ die drop rethrow ] ] initialize
124 M: object error-in-thread
125 thread-error-hook get-global call( error thread -- * ) ;
127 : in-callback? ( -- ? ) CONTEXT-OBJ-IN-CALLBACK-P context-object ;
129 SYMBOL: callback-error-hook ! ( error -- * )
131 callback-error-hook [ [ die rethrow ] ] initialize
133 : rethrow ( error -- * )
137 [ callback-error-hook get-global call( error -- * ) ]
138 [ OBJ-CURRENT-THREAD special-object error-in-thread ]
140 ] [ pop continue-with ] if-empty ;
142 : recover ( ..a try: ( ..a -- ..b ) recovery: ( ..a error -- ..b ) -- ..b )
145 [ (get-catchstack) push ] dip
147 (get-catchstack) pop*
151 : ignore-errors ( quot -- )
152 [ drop ] recover ; inline
154 : cleanup ( try cleanup-always cleanup-error -- )
155 [ compose [ dip rethrow ] curry recover ] [ drop ] 2bi call ; inline
157 ERROR: attempt-all-error ;
159 : attempt-all ( ... seq quot: ( ... elt -- ... obj ) -- ... obj )
164 [ [ , f ] compose [ , drop t ] recover ] curry all?
165 ] { } make last swap [ rethrow ] when
168 TUPLE: condition error restarts continuation ;
170 C: <condition> condition
172 : throw-restarts ( error restarts -- restart )
173 [ <condition> throw ] callcc1 2nip ;
175 : rethrow-restarts ( error restarts -- restart )
176 [ <condition> rethrow ] callcc1 2nip ;
178 : throw-continue ( error -- )
179 { { "Continue" t } } throw-restarts drop ;
181 TUPLE: restart name obj continuation ;
185 : continue-restart ( restart -- * )
186 [ obj>> ] [ continuation>> ] bi continue-with ;
188 M: object compute-restarts drop { } ;
190 M: condition compute-restarts
191 [ error>> compute-restarts ]
194 [ continuation>> [ <restart> ] curry ] bi
200 : init-error-handler ( -- )
204 OBJ-CURRENT-THREAD special-object error-thread set-global
205 current-continuation error-continuation set-global
206 [ original-error set-global ] [ rethrow ] bi
207 ] ERROR-HANDLER-QUOT set-special-object ;