New single stepper work in progress #2
parent
f2e9b80784
commit
74fecb134b
|
@ -1,42 +1,88 @@
|
|||
! Copyright (C) 2004, 2007 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: arrays assocs classes combinators sequences.private
|
||||
continuations continuations.private generic hashtables io kernel
|
||||
kernel.private math namespaces namespaces.private prettyprint
|
||||
quotations sequences splitting strings threads
|
||||
vectors words ;
|
||||
IN: tools.interpreter
|
||||
|
||||
: walk ( quot -- ) \ break add* call ;
|
||||
|
||||
TUPLE: interpreter continuation ;
|
||||
SYMBOL: walker-hook
|
||||
|
||||
: <interpreter> interpreter construct-empty ;
|
||||
! Thread local
|
||||
SYMBOL: interpreter-thread
|
||||
|
||||
GENERIC# restore 1 ( obj interpreter -- )
|
||||
: get-interpreter-thread ( -- thread )
|
||||
interpreter-thread tget dup [
|
||||
walker-hook get
|
||||
[ "No walker hook" throw ] or
|
||||
interpreter-thread
|
||||
] unless* ;
|
||||
|
||||
M: f restore
|
||||
set-interpreter-continuation ;
|
||||
: break ( -- )
|
||||
callstack [
|
||||
over set-continuation-callstack
|
||||
|
||||
M: continuation restore
|
||||
>r clone r> set-interpreter-continuation ;
|
||||
interpreter-thread send-synchronous {
|
||||
{ [ dup continuation? ] [ (continue) ] }
|
||||
{ [ dup quotation? ] [ call ] }
|
||||
{ [ dup not ] [ "Single stepping abandoned" throw ] }
|
||||
} cond
|
||||
] curry callcc0 ;
|
||||
|
||||
: with-interpreter-datastack ( quot interpreter -- )
|
||||
interpreter-continuation [
|
||||
continuation-data
|
||||
swap with-datastack
|
||||
] keep set-continuation-data ; inline
|
||||
SYMBOL: +suspended+
|
||||
SYMBOL: +running+
|
||||
SYMBOL: +stopped+
|
||||
|
||||
M: pair restore
|
||||
>r first2 r> [ restore ] keep
|
||||
>r [ nip f ] curry r> with-interpreter-datastack ;
|
||||
! Messages sent to interpreter thread
|
||||
SYMBOL: status
|
||||
|
||||
SYMBOL: step
|
||||
SYMBOL: step-out
|
||||
SYMBOL: step-into
|
||||
SYMBOL: step-all
|
||||
SYMBOL: step-back
|
||||
SYMBOL: detach
|
||||
SYMBOL: abandon
|
||||
SYMBOL: call-in
|
||||
|
||||
SYMBOL: get-thread
|
||||
SYMBOL: get-continuation
|
||||
|
||||
<PRIVATE
|
||||
|
||||
! Thread locals
|
||||
SYMBOL: interpreter-running?
|
||||
SYMBOL: interpreter-stepping?
|
||||
SYMBOL: interpreter-continuation
|
||||
SYMBOL: interpreter-history
|
||||
|
||||
: change-frame ( continuation quot -- continuation' )
|
||||
#! Applies quot to innermost call frame of the
|
||||
#! continuation.
|
||||
over continuation-call clone
|
||||
[
|
||||
dup innermost-frame-scan 1+
|
||||
swap innermost-frame-quot
|
||||
rot call
|
||||
] keep
|
||||
[ set-innermost-frame-quot ] keep
|
||||
over set-continuation-call ; inline
|
||||
|
||||
: step-msg ( continuation -- continuation' )
|
||||
[
|
||||
2dup nth \ break = [
|
||||
nip
|
||||
] [
|
||||
swap 1+ cut [ break ] swap 3append
|
||||
] if
|
||||
] change-frame ;
|
||||
|
||||
: step-out-msg ( continuation -- continuation' )
|
||||
[ nip \ break add ] change-frame ;
|
||||
|
||||
GENERIC: (step-into) ( obj -- )
|
||||
|
||||
M: wrapper (step-into) wrapped break ;
|
||||
M: object (step-into) break ;
|
||||
M: callable (step-into) \ break add* break ;
|
||||
|
||||
: (step-into-if) ? walk ;
|
||||
|
||||
: (step-into-dispatch)
|
||||
nth walk ;
|
||||
: (step-into-dispatch) nth walk ;
|
||||
|
||||
: (step-into-execute) ( word -- )
|
||||
dup "step-into" word-prop [
|
||||
|
@ -66,7 +112,8 @@ M: word (step-into) (step-into-execute) ;
|
|||
{
|
||||
>n ndrop >c c>
|
||||
continue continue-with
|
||||
(continue-with) stop
|
||||
(continue-with) stop yield suspend sleep (spawn)
|
||||
suspend
|
||||
} [
|
||||
dup [ execute break ] curry
|
||||
"step-into" set-word-prop
|
||||
|
@ -74,44 +121,107 @@ M: word (step-into) (step-into-execute) ;
|
|||
|
||||
\ break [ break ] "step-into" set-word-prop
|
||||
|
||||
! Stepping
|
||||
: change-innermost-frame ( quot interpreter -- )
|
||||
interpreter-continuation [
|
||||
continuation-call clone
|
||||
[
|
||||
dup innermost-frame-scan 1+
|
||||
swap innermost-frame-quot
|
||||
rot call
|
||||
] keep
|
||||
[ set-innermost-frame-quot ] keep
|
||||
] keep set-continuation-call ; inline
|
||||
|
||||
: (step) ( interpreter quot -- )
|
||||
swap
|
||||
[ change-innermost-frame ] keep
|
||||
[ interpreter-continuation with-walker-hook ] keep
|
||||
restore ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: step ( interpreter -- )
|
||||
[
|
||||
2dup nth \ break = [
|
||||
nip
|
||||
] [
|
||||
swap 1+ cut [ break ] swap 3append
|
||||
] if
|
||||
] (step) ;
|
||||
|
||||
: step-out ( interpreter -- )
|
||||
[ nip \ break add ] (step) ;
|
||||
|
||||
: step-into ( interpreter -- )
|
||||
: step-into-msg ( continuation -- continuation' )
|
||||
[
|
||||
swap cut [
|
||||
swap % unclip literalize , \ (step-into) , %
|
||||
] [ ] make
|
||||
] (step) ;
|
||||
|
||||
: step-all ( interpreter -- )
|
||||
interpreter-continuation [ (continue) ] curry in-thread ;
|
||||
: status-change ( symbol -- )
|
||||
+running+ interpreter-status tget set-model ;
|
||||
|
||||
: detach-msg ( -- f )
|
||||
+detached+ status-change
|
||||
f interpreter-stepping? tset
|
||||
f interpreter-running? tset
|
||||
f ;
|
||||
|
||||
: continuation-msg ( -- continuation )
|
||||
interpreter-thread tget thread-continuation box-value ;
|
||||
|
||||
: keep-running f interpreter-stepping? tset ;
|
||||
|
||||
: save-continuation ( continuation -- )
|
||||
dup interpreter-continuation tget set-model
|
||||
interpreter-history tget push ;
|
||||
|
||||
: handle-command ( continuation -- continuation' )
|
||||
t interpreter-stepping? tset
|
||||
[ interpreter-stepping? tget ] [
|
||||
[
|
||||
{
|
||||
! These are sent by the walker tool. We reply and
|
||||
! keep cycling.
|
||||
{ status [ +suspended+ ] }
|
||||
{ detach [ detach-msg ] }
|
||||
{ get-thread [ interpreter-thread tget ] }
|
||||
{ get-continuation [ dup ] }
|
||||
! These change the state of the thread being
|
||||
! interpreted, so we modify the continuation and
|
||||
! output f.
|
||||
{ step [ (step) keep-running ] }
|
||||
{ step-out [ (step-out) keep-running ] }
|
||||
{ step-into [ (step-into) keep-running ] }
|
||||
{ step-all [ keep-running ] }
|
||||
{ abandon [ drop f keep-running ] }
|
||||
! Pass quotation to debugged thread
|
||||
{ call-in [ nip keep-running ] }
|
||||
! Pass previous continuation to debugged thread
|
||||
{ step-back [ drop interpreter-history tget pop f ] }
|
||||
} case
|
||||
] handle-synchronous
|
||||
] [ ] while
|
||||
dup continuation? [ dup save-continuation ] when ;
|
||||
|
||||
: interpreter-stopped ( -- )
|
||||
[
|
||||
{
|
||||
{ detach [ detach-msg ] }
|
||||
{ status [ +stopped+ ] }
|
||||
{ get-thread [ interpreter-thread tget ] }
|
||||
{ get-continuation [ f ] }
|
||||
[ drop f ]
|
||||
} case
|
||||
] handle-synchronous
|
||||
interpreter-stopped ;
|
||||
|
||||
: interpreter-loop ( -- )
|
||||
[ interpreter-running? tget ] [
|
||||
[
|
||||
status-change
|
||||
{
|
||||
{ detach [ detach-msg ] }
|
||||
{ get-thread [ interpreter-thread tget ] }
|
||||
{ get-continuation [ f ] }
|
||||
! ignore these commands while the thread is
|
||||
! running
|
||||
{ step [ f ] }
|
||||
{ step-out [ f ] }
|
||||
{ step-into [ f ] }
|
||||
{ step-all [ f ] }
|
||||
{ step-back [ f ] }
|
||||
! thread has exited so we exit the monitor too
|
||||
{ f [ interpreter-stopped ] }
|
||||
! thread hit a breakpoint and sent us the
|
||||
! continuation, so we modify it and send it back.
|
||||
[ handle-command ]
|
||||
} case
|
||||
] handle-synchronous
|
||||
] [ ] while;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: start-interpreter-thread ( thread -- thread' )
|
||||
[
|
||||
[
|
||||
interpreter-thread tset
|
||||
t interpreter-running tset
|
||||
f interpreter-stepping tset
|
||||
f <model> interpreter-continuation tset
|
||||
V{ } clone interpreter-history tset
|
||||
interpreter-loop
|
||||
] curry
|
||||
] keep
|
||||
"Interpreter for " over thread-name append spawn
|
||||
dup rot set-thread-;
|
||||
|
|
Loading…
Reference in New Issue