1 ! Copyright (C) 2003, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays vectors kernel kernel.private sequences
4 namespaces math splitting sorting quotations assocs
5 combinators accessors ;
9 SYMBOL: error-continuation
15 : catchstack* ( -- catchstack )
16 1 getenv { vector } declare ; inline
18 : >c ( continuation -- ) catchstack* push ;
20 : c> ( -- continuation ) catchstack* pop ;
23 #! Optimizing compiler assumes stack won't be messed with
24 #! in-transit. To ensure that a value is actually reified
25 #! on the stack, we put it in a non-inline word together
26 #! with a declaration.
27 f { object } declare ;
29 : init-catchstack ( -- ) V{ } clone 1 setenv ;
33 : catchstack ( -- catchstack ) catchstack* clone ; inline
35 : set-catchstack ( catchstack -- ) >vector 1 setenv ; inline
37 TUPLE: continuation data call retain name catch ;
39 C: <continuation> continuation
41 : continuation ( -- continuation )
42 datastack callstack retainstack namestack catchstack
45 : >continuation< ( continuation -- data call retain name catch )
54 : ifcc ( capture restore -- )
55 #! After continuation is being captured, the stacks looks
57 #! ( f continuation r:capture r:restore )
58 #! so the 'capture' branch is taken.
60 #! Note that the continuation itself is not captured as part
65 #! After the continuation is resumed, (continue-with) pushes
66 #! the given value together with f,
67 #! so now, the stacks looks like:
68 #! ( value f r:capture r:restore )
69 #! Execution begins right after the call to 'continuation'.
70 #! The 'restore' branch is taken.
71 >r >r dummy continuation r> r> ?if ; inline
73 : callcc0 ( quot -- ) [ drop ] ifcc ; inline
75 : callcc1 ( quot -- obj ) [ ] ifcc ; inline
79 : (continue) ( continuation -- )
87 : (continue-with) ( obj continuation -- )
93 >r set-datastack drop 4 getenv f 4 setenv f r>
98 : continue-with ( obj continuation -- )
99 [ (continue-with) ] 2 (throw) ;
101 : continue ( continuation -- )
102 f swap continue-with ;
104 SYMBOL: return-continuation
106 : with-return ( quot -- )
107 [ [ return-continuation set ] prepose callcc0 ] with-scope ; inline
110 return-continuation get continue ;
112 : with-datastack ( stack quot -- newstack )
115 [ [ { } like set-datastack ] dip call datastack ] dip
120 GENERIC: compute-restarts ( error -- seq )
124 : save-error ( error -- )
126 compute-restarts restarts set-global ;
130 SYMBOL: thread-error-hook
132 : rethrow ( error -- * )
135 thread-error-hook get-global
136 [ 1 (throw) ] [ die ] if*
140 : recover ( try recovery -- )
141 >r [ swap >c call c> drop ] curry r> ifcc ; inline
143 : ignore-errors ( quot -- )
144 [ drop ] recover ; inline
146 : cleanup ( try cleanup-always cleanup-error -- )
147 over >r compose [ dip rethrow ] curry
148 recover r> call ; inline
150 ERROR: attempt-all-error ;
152 : attempt-all ( seq quot -- obj )
157 [ [ , f ] compose [ , drop t ] recover ] curry all?
158 ] { } make peek swap [ rethrow ] when
161 TUPLE: condition error restarts continuation ;
163 C: <condition> condition ( error restarts cc -- condition )
165 : throw-restarts ( error restarts -- restart )
166 [ <condition> throw ] callcc1 2nip ;
168 : rethrow-restarts ( error restarts -- restart )
169 [ <condition> rethrow ] callcc1 2nip ;
171 TUPLE: restart name obj continuation ;
175 : restart ( restart -- )
176 [ obj>> ] [ continuation>> ] bi continue-with ;
178 M: object compute-restarts drop { } ;
180 M: condition compute-restarts
181 [ error>> compute-restarts ]
184 [ condition-continuation [ <restart> ] curry ] bi
190 : init-error-handler ( -- )
191 V{ } clone set-catchstack
195 63 getenv error-thread set-global
196 continuation error-continuation set-global
199 ! VM adds this to kernel errors, so that user-space
201 "kernel-error" 6 setenv ;