2008-07-20 05:24:37 -04:00
|
|
|
! Copyright (C) 2008 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
|
|
USING: fry namespaces assocs kernel sequences words accessors
|
2008-08-15 00:35:19 -04:00
|
|
|
definitions math math.order effects classes arrays combinators
|
|
|
|
vectors arrays
|
2008-07-20 05:24:37 -04:00
|
|
|
stack-checker.state
|
|
|
|
stack-checker.visitor
|
|
|
|
stack-checker.backend
|
|
|
|
stack-checker.branches
|
2008-07-23 01:17:08 -04:00
|
|
|
stack-checker.errors
|
|
|
|
stack-checker.known-words ;
|
2008-07-20 05:24:37 -04:00
|
|
|
IN: stack-checker.inlining
|
|
|
|
|
|
|
|
! Code to handle inline words. Much of the complexity stems from
|
|
|
|
! having to handle recursive inline words.
|
|
|
|
|
|
|
|
: (inline-word) ( word label -- )
|
|
|
|
[ [ def>> ] keep ] dip infer-quot-recursive ;
|
|
|
|
|
2008-08-10 02:58:39 -04:00
|
|
|
TUPLE: inline-recursive < identity-tuple
|
|
|
|
id
|
2008-08-07 02:08:11 -04:00
|
|
|
word
|
|
|
|
enter-out enter-recursive
|
|
|
|
return calls
|
|
|
|
fixed-point
|
2008-08-10 02:58:39 -04:00
|
|
|
introductions
|
|
|
|
loop? ;
|
|
|
|
|
|
|
|
M: inline-recursive hashcode* id>> hashcode* ;
|
2008-07-20 05:24:37 -04:00
|
|
|
|
2008-08-12 00:30:18 -04:00
|
|
|
: inlined-block? ( word -- ? ) "inlined-block" word-prop ;
|
|
|
|
|
2008-07-20 05:24:37 -04:00
|
|
|
: <inline-recursive> ( word -- label )
|
2008-08-10 02:58:39 -04:00
|
|
|
inline-recursive new
|
2008-08-12 03:41:18 -04:00
|
|
|
gensym dup t "inlined-block" set-word-prop >>id
|
2008-08-10 02:58:39 -04:00
|
|
|
swap >>word ;
|
2008-07-20 05:24:37 -04:00
|
|
|
|
|
|
|
: quotation-param? ( obj -- ? )
|
|
|
|
dup pair? [ second effect? ] [ drop f ] if ;
|
|
|
|
|
|
|
|
: make-copies ( values effect-in -- values' )
|
|
|
|
[ quotation-param? [ copy-value ] [ drop <value> ] if ] 2map ;
|
|
|
|
|
2008-07-27 03:32:40 -04:00
|
|
|
SYMBOL: enter-in
|
|
|
|
SYMBOL: enter-out
|
2008-07-20 05:24:37 -04:00
|
|
|
|
|
|
|
: prepare-stack ( word -- )
|
|
|
|
required-stack-effect in>> [ length ensure-d ] keep
|
2008-07-27 03:32:40 -04:00
|
|
|
[ drop enter-in set ] [ make-copies enter-out set ] 2bi ;
|
2008-07-20 05:24:37 -04:00
|
|
|
|
2008-07-27 03:32:40 -04:00
|
|
|
: emit-enter-recursive ( label -- )
|
|
|
|
enter-out get >>enter-out
|
|
|
|
enter-in get enter-out get #enter-recursive,
|
|
|
|
enter-out get >vector meta-d set ;
|
2008-07-20 05:24:37 -04:00
|
|
|
|
|
|
|
: entry-stack-height ( label -- stack )
|
2008-07-27 03:32:40 -04:00
|
|
|
enter-out>> length ;
|
2008-07-20 05:24:37 -04:00
|
|
|
|
|
|
|
: check-return ( word label -- )
|
|
|
|
2dup
|
|
|
|
[ stack-effect effect-height ]
|
|
|
|
[ entry-stack-height current-stack-height swap - ]
|
|
|
|
bi*
|
|
|
|
= [ 2drop ] [
|
|
|
|
word>> current-stack-height
|
|
|
|
unbalanced-recursion-error inference-error
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
: end-recursive-word ( word label -- )
|
|
|
|
[ check-return ]
|
2008-07-27 03:32:40 -04:00
|
|
|
[ meta-d get dup copy-values dup meta-d set #return-recursive, ]
|
2008-07-20 05:24:37 -04:00
|
|
|
bi ;
|
|
|
|
|
|
|
|
: recursive-word-inputs ( label -- n )
|
|
|
|
entry-stack-height d-in get + ;
|
|
|
|
|
|
|
|
: (inline-recursive-word) ( word -- word label in out visitor )
|
|
|
|
dup prepare-stack
|
|
|
|
[
|
|
|
|
init-inference
|
|
|
|
nest-visitor
|
|
|
|
|
|
|
|
dup <inline-recursive>
|
2008-07-27 03:32:40 -04:00
|
|
|
[ dup emit-enter-recursive (inline-word) ]
|
2008-07-20 05:24:37 -04:00
|
|
|
[ end-recursive-word ]
|
|
|
|
[ ]
|
|
|
|
2tri
|
|
|
|
|
|
|
|
check->r
|
|
|
|
|
|
|
|
dup recursive-word-inputs
|
|
|
|
meta-d get
|
2008-07-24 00:50:21 -04:00
|
|
|
stack-visitor get
|
2008-07-20 05:24:37 -04:00
|
|
|
] with-scope ;
|
|
|
|
|
|
|
|
: inline-recursive-word ( word -- )
|
|
|
|
(inline-recursive-word)
|
2008-07-27 03:32:40 -04:00
|
|
|
[ consume-d ] [ output-d ] [ ] tri* #recursive, ;
|
2008-07-20 05:24:37 -04:00
|
|
|
|
|
|
|
: check-call-height ( word label -- )
|
|
|
|
entry-stack-height current-stack-height >
|
|
|
|
[ diverging-recursion-error inference-error ] [ drop ] if ;
|
|
|
|
|
|
|
|
: call-site-stack ( label -- stack )
|
|
|
|
required-stack-effect in>> length meta-d get swap tail* ;
|
|
|
|
|
|
|
|
: check-call-site-stack ( stack label -- )
|
2008-07-27 03:32:40 -04:00
|
|
|
tuck enter-out>>
|
2008-07-20 05:24:37 -04:00
|
|
|
[ dup known [ [ known ] bi@ = ] [ 2drop t ] if ] 2all?
|
|
|
|
[ drop ] [ word>> inconsistent-recursive-call-error inference-error ] if ;
|
|
|
|
|
|
|
|
: add-call ( word label -- )
|
|
|
|
[ check-call-height ]
|
2008-07-27 03:32:40 -04:00
|
|
|
[ [ call-site-stack ] dip check-call-site-stack ] 2bi ;
|
2008-07-20 05:24:37 -04:00
|
|
|
|
|
|
|
: adjust-stack-effect ( effect -- effect' )
|
|
|
|
[ in>> ] [ out>> ] bi
|
2008-08-15 00:35:19 -04:00
|
|
|
meta-d get length pick length - 0 max
|
|
|
|
object <repetition> '[ , prepend ] bi@
|
2008-07-20 05:24:37 -04:00
|
|
|
<effect> ;
|
|
|
|
|
|
|
|
: call-recursive-inline-word ( word -- )
|
|
|
|
dup "recursive" word-prop [
|
|
|
|
[ required-stack-effect adjust-stack-effect ] [ ] [ recursive-label ] tri
|
|
|
|
[ add-call drop ]
|
|
|
|
[ nip '[ , #call-recursive, ] consume/produce ]
|
2008-08-01 00:01:20 -04:00
|
|
|
3bi
|
2008-07-20 05:24:37 -04:00
|
|
|
] [ undeclared-recursion-error inference-error ] if ;
|
|
|
|
|
|
|
|
: inline-word ( word -- )
|
|
|
|
[ +inlined+ depends-on ]
|
|
|
|
[
|
|
|
|
{
|
|
|
|
{ [ dup inline-recursive-label ] [ call-recursive-inline-word ] }
|
|
|
|
{ [ dup "recursive" word-prop ] [ inline-recursive-word ] }
|
|
|
|
[ dup (inline-word) ]
|
|
|
|
} cond
|
|
|
|
] bi ;
|
|
|
|
|
|
|
|
M: word apply-object
|
|
|
|
dup inline? [ inline-word ] [ non-inline-word ] if ;
|