factor/core/continuations/continuations.factor

185 lines
4.3 KiB
Factor
Raw Normal View History

2009-03-16 21:11:36 -04:00
! Copyright (C) 2003, 2009 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: arrays vectors kernel kernel.private sequences
namespaces make math splitting sorting quotations assocs
2009-05-01 09:21:31 -04:00
combinators combinators.private accessors words ;
2007-09-20 18:09:08 -04:00
IN: continuations
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
: catchstack* ( -- catchstack )
1 getenv { vector } declare ; inline
: >c ( continuation -- ) catchstack* push ;
: c> ( -- continuation ) catchstack* pop ;
2008-08-22 04:12:15 -04:00
! We have to defeat some optimizations to make continuations work
: dummy-1 ( -- obj ) f ;
: dummy-2 ( obj -- obj ) dup drop ;
2007-10-03 17:35:48 -04:00
2008-06-08 16:32:55 -04:00
: init-catchstack ( -- ) V{ } clone 1 setenv ;
2008-02-27 20:23:22 -05:00
2007-09-20 18:09:08 -04:00
PRIVATE>
: catchstack ( -- catchstack ) catchstack* clone ; inline
: set-catchstack ( catchstack -- ) >vector 1 setenv ; inline
TUPLE: continuation data call retain name catch ;
C: <continuation> continuation
: continuation ( -- continuation )
datastack callstack retainstack namestack catchstack
<continuation> ;
: >continuation< ( continuation -- data call retain name catch )
{
[ data>> ]
[ call>> ]
[ retain>> ]
[ name>> ]
[ catch>> ]
} cleave ;
2007-09-20 18:09:08 -04:00
: ifcc ( capture restore -- )
[ dummy-1 continuation ] 2dip [ dummy-2 ] prepose ?if ; inline
2007-09-20 18:09:08 -04:00
: callcc0 ( quot -- ) [ drop ] ifcc ; inline
2007-09-20 18:09:08 -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
] (( continuation -- * )) call-effect-unsafe ;
2009-04-13 00:01:14 -04:00
2007-09-20 18:09:08 -04:00
PRIVATE>
: continue-with ( obj continuation -- * )
2009-03-16 21:11:36 -04:00
[
swap 4 setenv
>continuation<
set-catchstack
set-namestack
set-retainstack
[ set-datastack drop 4 getenv f 4 setenv f ] dip
set-callstack
] (( obj continuation -- * )) call-effect-unsafe ;
2007-09-20 18:09:08 -04:00
: continue ( continuation -- * )
f swap continue-with ;
2008-05-07 08:49:29 -04:00
SYMBOL: return-continuation
: with-return ( quot -- )
[ [ return-continuation set ] prepose callcc0 ] with-scope ; inline
: return ( -- * )
2008-05-07 08:49:29 -04:00
return-continuation get continue ;
: with-datastack ( stack quot -- newstack )
[
[
[ [ { } like set-datastack ] dip call datastack ] dip
continue-with
2009-03-16 21:11:36 -04:00
] (( stack quot continuation -- * )) call-effect-unsafe
] callcc1 2nip ;
2007-09-20 18:09:08 -04:00
GENERIC: compute-restarts ( error -- seq )
<PRIVATE
: save-error ( error -- )
dup error set-global
compute-restarts restarts set-global ;
PRIVATE>
2008-02-18 06:07:40 -05:00
SYMBOL: thread-error-hook
2007-09-20 18:09:08 -04:00
: rethrow ( error -- * )
2008-02-21 02:24:24 -05:00
dup save-error
2008-02-18 06:07:40 -05:00
catchstack* empty? [
thread-error-hook get-global
2009-03-16 21:11:36 -04:00
[ (( error -- * )) call-effect-unsafe ] [ die ] if*
2008-02-18 06:07:40 -05:00
] when
2008-02-21 02:24:24 -05:00
c> continue-with ;
2007-09-20 18:09:08 -04:00
: recover ( try recovery -- )
[ [ swap >c call c> drop ] 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 -- )
[ compose [ dip rethrow ] curry recover ] [ drop ] 2bi call ; inline
2007-09-20 18:09:08 -04:00
ERROR: attempt-all-error ;
2007-09-20 18:09:08 -04:00
: attempt-all ( seq quot -- obj )
over empty? [
attempt-all-error
] [
[
[ [ , f ] compose [ , drop t ] recover ] curry all?
] { } make last swap [ rethrow ] when
] 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
2008-04-04 01:33:06 -04:00
C: <condition> condition ( error restarts cc -- 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 ;
TUPLE: restart name obj continuation ;
C: <restart> restart
: 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>> ]
[ 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 ( -- )
V{ } clone set-catchstack
! VM calls on error
[
! 63 = self
63 getenv error-thread set-global
continuation error-continuation set-global
rethrow
] 5 setenv
! VM adds this to kernel errors, so that user-space
! can identify them
"kernel-error" 6 setenv ;
PRIVATE>