2011-10-03 02:33:28 -04:00
|
|
|
! Copyright (C) 2003, 2011 Slava Pestov.
|
2007-09-20 18:09:08 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2012-07-27 22:21:47 -04:00
|
|
|
USING: accessors assocs combinators combinators.private kernel
|
|
|
|
kernel.private make namespaces sequences vectors ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: continuations
|
|
|
|
|
2010-04-03 19:10:21 -04:00
|
|
|
: with-datastack ( stack quot -- new-stack )
|
|
|
|
[
|
2015-08-13 13:11:59 -04:00
|
|
|
[ [ get-datastack ] dip swap [ { } like set-datastack ] dip ] dip
|
|
|
|
swap [ call get-datastack ] dip
|
2010-04-03 19:10:21 -04:00
|
|
|
swap [ set-datastack ] dip
|
2011-10-18 16:18:42 -04:00
|
|
|
] ( stack quot -- new-stack ) call-effect-unsafe ;
|
2010-04-03 19:10:21 -04:00
|
|
|
|
2010-04-30 05:33:34 -04:00
|
|
|
SYMBOL: original-error
|
2007-09-20 18:09:08 -04:00
|
|
|
SYMBOL: error
|
|
|
|
SYMBOL: error-continuation
|
2008-02-27 20:23:22 -05:00
|
|
|
SYMBOL: error-thread
|
2007-09-20 18:09:08 -04:00
|
|
|
SYMBOL: restarts
|
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
2015-08-13 20:52:40 -04:00
|
|
|
: (get-catchstack) ( -- catchstack )
|
2011-11-02 15:54:31 -04:00
|
|
|
CONTEXT-OBJ-CATCHSTACK context-object { vector } declare ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-08-22 04:12:15 -04:00
|
|
|
! We have to defeat some optimizations to make continuations work
|
|
|
|
: dummy-1 ( -- obj ) f ;
|
2011-10-03 02:33:28 -04:00
|
|
|
: dummy-2 ( obj -- obj ) ;
|
2007-10-03 17:35:48 -04:00
|
|
|
|
2015-08-13 20:52:40 -04:00
|
|
|
: get-catchstack ( -- catchstack ) (get-catchstack) clone ; inline
|
2008-02-27 20:23:22 -05:00
|
|
|
|
2013-03-06 13:08:48 -05:00
|
|
|
: (set-catchstack) ( catchstack -- )
|
|
|
|
CONTEXT-OBJ-CATCHSTACK set-context-object ; inline
|
|
|
|
|
2010-03-18 05:06:00 -04:00
|
|
|
: set-catchstack ( catchstack -- )
|
2013-03-06 13:08:48 -05:00
|
|
|
>vector (set-catchstack) ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2013-03-06 13:08:48 -05:00
|
|
|
: init-catchstack ( -- )
|
|
|
|
V{ } clone (set-catchstack) ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2010-03-18 05:06:00 -04:00
|
|
|
PRIVATE>
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2012-07-27 22:21:47 -04:00
|
|
|
TUPLE: continuation data call retain name catch ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
C: <continuation> continuation
|
|
|
|
|
2012-07-20 15:03:21 -04:00
|
|
|
: current-continuation ( -- continuation )
|
2015-08-13 13:11:59 -04:00
|
|
|
get-datastack get-callstack get-retainstack get-namestack get-catchstack
|
2007-09-20 18:09:08 -04:00
|
|
|
<continuation> ;
|
|
|
|
|
2010-03-18 05:06:00 -04:00
|
|
|
<PRIVATE
|
|
|
|
|
2014-12-01 11:04:49 -05:00
|
|
|
ERROR: not-a-continuation object ;
|
2012-09-14 17:59:38 -04:00
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
: >continuation< ( continuation -- data call retain name catch )
|
2015-08-13 19:13:05 -04:00
|
|
|
dup continuation? [ not-a-continuation ] unless
|
2012-09-14 17:59:38 -04:00
|
|
|
{ [ data>> ] [ call>> ] [ retain>> ] [ name>> ] [ catch>> ] } cleave ; inline
|
2010-03-18 05:06:00 -04:00
|
|
|
|
|
|
|
PRIVATE>
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2007-10-03 16:56:49 -04:00
|
|
|
: ifcc ( capture restore -- )
|
2012-07-20 15:03:21 -04:00
|
|
|
[ dummy-1 current-continuation ] 2dip [ dummy-2 ] prepose ?if ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2007-10-03 16:56:49 -04:00
|
|
|
: callcc0 ( quot -- ) [ drop ] ifcc ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2007-10-03 16:56:49 -04:00
|
|
|
: callcc1 ( quot -- obj ) [ ] ifcc ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
2009-03-16 21:11:36 -04:00
|
|
|
: (continue) ( continuation -- * )
|
2009-04-17 00:14:11 -04:00
|
|
|
[
|
|
|
|
>continuation<
|
|
|
|
set-catchstack
|
|
|
|
set-namestack
|
|
|
|
set-retainstack
|
|
|
|
[ set-datastack ] dip
|
|
|
|
set-callstack
|
2011-10-18 16:18:42 -04:00
|
|
|
] ( continuation -- * ) call-effect-unsafe ;
|
2009-04-13 00:01:14 -04:00
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
PRIVATE>
|
|
|
|
|
2009-02-23 21:27:05 -05:00
|
|
|
: continue-with ( obj continuation -- * )
|
2009-03-16 21:11:36 -04:00
|
|
|
[
|
2011-11-02 15:54:31 -04:00
|
|
|
swap OBJ-CALLCC-1 set-special-object
|
2009-03-16 21:11:36 -04:00
|
|
|
>continuation<
|
|
|
|
set-catchstack
|
|
|
|
set-namestack
|
|
|
|
set-retainstack
|
2011-11-02 15:54:31 -04:00
|
|
|
[
|
|
|
|
set-datastack drop
|
|
|
|
OBJ-CALLCC-1 special-object
|
|
|
|
f OBJ-CALLCC-1 set-special-object
|
|
|
|
f
|
|
|
|
] dip
|
2009-03-16 21:11:36 -04:00
|
|
|
set-callstack
|
2011-10-18 16:18:42 -04:00
|
|
|
] ( obj continuation -- * ) call-effect-unsafe ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2009-02-23 21:27:05 -05:00
|
|
|
: continue ( continuation -- * )
|
2007-10-03 16:56:49 -04:00
|
|
|
f swap continue-with ;
|
|
|
|
|
2008-05-07 08:49:29 -04:00
|
|
|
SYMBOL: return-continuation
|
|
|
|
|
|
|
|
: with-return ( quot -- )
|
2015-06-15 12:11:35 -04:00
|
|
|
[ return-continuation ] dip [ with-variable ] 2curry callcc0 ; inline
|
2008-05-07 08:49:29 -04:00
|
|
|
|
2009-02-23 21:27:05 -05:00
|
|
|
: return ( -- * )
|
2008-05-07 08:49:29 -04:00
|
|
|
return-continuation get continue ;
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
GENERIC: compute-restarts ( error -- seq )
|
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
|
|
|
: save-error ( error -- )
|
2010-04-30 05:33:34 -04:00
|
|
|
[ error set-global ]
|
|
|
|
[ compute-restarts restarts set-global ] bi ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
PRIVATE>
|
|
|
|
|
2011-10-03 02:33:28 -04:00
|
|
|
GENERIC: error-in-thread ( error thread -- * )
|
|
|
|
|
2016-03-29 01:27:35 -04:00
|
|
|
SYMBOL: thread-error-hook ! ( error thread -- * )
|
2011-10-03 02:33:28 -04:00
|
|
|
|
2016-03-29 01:27:35 -04:00
|
|
|
M: object error-in-thread
|
2011-10-03 02:33:28 -04:00
|
|
|
thread-error-hook get-global call( error thread -- * ) ;
|
|
|
|
|
2011-11-02 15:54:31 -04:00
|
|
|
: in-callback? ( -- ? ) CONTEXT-OBJ-IN-CALLBACK-P context-object ;
|
2011-10-03 02:33:28 -04:00
|
|
|
|
|
|
|
SYMBOL: callback-error-hook ! ( error -- * )
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
: rethrow ( error -- * )
|
2008-02-21 02:24:24 -05:00
|
|
|
dup save-error
|
2015-08-13 20:52:40 -04:00
|
|
|
(get-catchstack) [
|
2011-10-03 02:33:28 -04:00
|
|
|
in-callback?
|
|
|
|
[ callback-error-hook get-global call( error -- * ) ]
|
2011-11-02 15:54:31 -04:00
|
|
|
[ OBJ-CURRENT-THREAD special-object error-in-thread ]
|
2011-10-03 02:33:28 -04:00
|
|
|
if
|
|
|
|
] [ pop continue-with ] if-empty ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2016-04-06 20:55:47 -04:00
|
|
|
thread-error-hook [ [ die drop rethrow ] ] initialize
|
|
|
|
|
|
|
|
callback-error-hook [ [ die rethrow ] ] initialize
|
|
|
|
|
2010-03-08 21:28:19 -05:00
|
|
|
: recover ( ..a try: ( ..a -- ..b ) recovery: ( ..a error -- ..b ) -- ..b )
|
2011-10-03 02:33:28 -04:00
|
|
|
[
|
|
|
|
[
|
2015-08-13 20:52:40 -04:00
|
|
|
[ (get-catchstack) push ] dip
|
2011-10-03 02:33:28 -04:00
|
|
|
call
|
2015-08-13 20:52:40 -04:00
|
|
|
(get-catchstack) pop*
|
2011-10-03 02:33:28 -04:00
|
|
|
] curry
|
|
|
|
] dip ifcc ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-02-26 15:58:02 -05:00
|
|
|
: ignore-errors ( quot -- )
|
|
|
|
[ drop ] recover ; inline
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
: cleanup ( try cleanup-always cleanup-error -- )
|
2008-11-23 03:44:56 -05:00
|
|
|
[ compose [ dip rethrow ] curry recover ] [ drop ] 2bi call ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-05-12 19:53:22 -04:00
|
|
|
ERROR: attempt-all-error ;
|
|
|
|
|
2010-03-08 21:28:19 -05:00
|
|
|
: attempt-all ( ... seq quot: ( ... elt -- ... obj ) -- ... obj )
|
2008-05-12 19:53:22 -04:00
|
|
|
over empty? [
|
|
|
|
attempt-all-error
|
|
|
|
] [
|
|
|
|
[
|
|
|
|
[ [ , f ] compose [ , drop t ] recover ] curry all?
|
2009-05-25 17:38:33 -04:00
|
|
|
] { } make last swap [ rethrow ] when
|
2008-05-12 19:53:22 -04:00
|
|
|
] if ; inline
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-04-04 01:33:06 -04:00
|
|
|
TUPLE: condition error restarts continuation ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2012-09-14 17:59:38 -04:00
|
|
|
C: <condition> condition
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
: throw-restarts ( error restarts -- restart )
|
|
|
|
[ <condition> throw ] callcc1 2nip ;
|
|
|
|
|
|
|
|
: rethrow-restarts ( error restarts -- restart )
|
|
|
|
[ <condition> rethrow ] callcc1 2nip ;
|
|
|
|
|
2010-02-19 19:41:33 -05:00
|
|
|
: throw-continue ( error -- )
|
|
|
|
{ { "Continue" t } } throw-restarts drop ;
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
TUPLE: restart name obj continuation ;
|
|
|
|
|
|
|
|
C: <restart> restart
|
|
|
|
|
2013-03-23 20:18:09 -04:00
|
|
|
: continue-restart ( restart -- * )
|
2008-04-04 01:33:06 -04:00
|
|
|
[ obj>> ] [ continuation>> ] bi continue-with ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
M: object compute-restarts drop { } ;
|
|
|
|
|
|
|
|
M: condition compute-restarts
|
2008-04-04 01:33:06 -04:00
|
|
|
[ error>> compute-restarts ]
|
|
|
|
[
|
|
|
|
[ restarts>> ]
|
2008-08-31 08:45:33 -04:00
|
|
|
[ continuation>> [ <restart> ] curry ] bi
|
2008-04-04 01:33:06 -04:00
|
|
|
{ } assoc>map
|
|
|
|
] bi append ;
|
2008-07-28 23:03:13 -04:00
|
|
|
|
|
|
|
<PRIVATE
|
|
|
|
|
|
|
|
: init-error-handler ( -- )
|
2010-03-18 05:06:00 -04:00
|
|
|
init-catchstack
|
2008-07-28 23:03:13 -04:00
|
|
|
! VM calls on error
|
|
|
|
[
|
2011-11-02 15:54:31 -04:00
|
|
|
OBJ-CURRENT-THREAD special-object error-thread set-global
|
2012-07-20 15:03:21 -04:00
|
|
|
current-continuation error-continuation set-global
|
2010-04-30 05:33:34 -04:00
|
|
|
[ original-error set-global ] [ rethrow ] bi
|
2016-03-22 10:56:41 -04:00
|
|
|
] ERROR-HANDLER-QUOT set-special-object ;
|
2008-07-28 23:03:13 -04:00
|
|
|
|
|
|
|
PRIVATE>
|