1 ! Copyright (C) 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: fry namespaces assocs kernel sequences words accessors
4 definitions math math.order effects classes arrays combinators
11 stack-checker.known-words ;
12 IN: stack-checker.inlining
14 ! Code to handle inline words. Much of the complexity stems from
15 ! having to handle recursive inline words.
17 : (inline-word) ( word label -- )
18 [ [ def>> ] keep ] dip infer-quot-recursive ;
20 TUPLE: inline-recursive < identity-tuple
23 enter-out enter-recursive
29 M: inline-recursive hashcode* id>> hashcode* ;
31 : inlined-block? ( word -- ? ) "inlined-block" word-prop ;
33 : <inline-recursive> ( word -- label )
35 gensym dup t "inlined-block" set-word-prop >>id
38 : quotation-param? ( obj -- ? )
39 dup pair? [ second effect? ] [ drop f ] if ;
41 : make-copies ( values effect-in -- values' )
43 [ quotation-param? [ copy-value ] [ drop <value> ] if ] 2map
44 [ make-values ] dip append ;
49 : prepare-stack ( word -- )
50 required-stack-effect in>>
51 [ length ensure-d drop ] [
52 meta-d get clone enter-in set
53 meta-d get swap make-copies enter-out set
56 : emit-enter-recursive ( label -- )
57 enter-out get >>enter-out
58 enter-in get enter-out get #enter-recursive,
59 enter-out get >vector meta-d set ;
61 : entry-stack-height ( label -- stack )
64 : check-return ( word label -- )
66 [ stack-effect effect-height ]
67 [ entry-stack-height current-stack-height swap - ]
70 terminated? get [ 2drop ] [
71 word>> current-stack-height
72 unbalanced-recursion-error inference-error
76 : end-recursive-word ( word label -- )
78 [ meta-d get dup copy-values dup meta-d set #return-recursive, ]
81 : recursive-word-inputs ( label -- n )
82 entry-stack-height d-in get + ;
84 : (inline-recursive-word) ( word -- label in out visitor terminated? )
90 dup <inline-recursive>
91 [ dup emit-enter-recursive (inline-word) ]
92 [ end-recursive-word ]
98 dup recursive-word-inputs
104 : inline-recursive-word ( word -- )
105 (inline-recursive-word)
106 [ [ consume-d ] [ output-d ] [ ] tri* #recursive, ] dip
109 : check-call-height ( label -- )
110 dup entry-stack-height current-stack-height >
111 [ word>> diverging-recursion-error inference-error ] [ drop ] if ;
113 : trim-stack ( label seq -- stack )
114 swap word>> required-stack-effect in>> length tail* ;
116 : call-site-stack ( label -- stack )
117 meta-d get trim-stack ;
119 : trimmed-enter-out ( label -- stack )
120 dup enter-out>> trim-stack ;
122 : check-call-site-stack ( label -- )
123 [ ] [ call-site-stack ] [ trimmed-enter-out ] tri
124 [ dup known [ [ known ] bi@ = ] [ 2drop t ] if ] 2all?
125 [ drop ] [ word>> inconsistent-recursive-call-error inference-error ] if ;
127 : check-call ( label -- )
128 [ check-call-height ] [ check-call-site-stack ] bi ;
130 : adjust-stack-effect ( effect -- effect' )
131 [ in>> ] [ out>> ] bi
132 meta-d get length pick length [-]
133 object <repetition> '[ _ prepend ] bi@
136 : call-recursive-inline-word ( word -- )
137 dup "recursive" word-prop [
138 [ required-stack-effect adjust-stack-effect ] [ ] [ recursive-label ] tri
139 [ 2nip check-call ] [ nip '[ _ #call-recursive, ] consume/produce ] 3bi
140 ] [ undeclared-recursion-error inference-error ] if ;
142 : inline-word ( word -- )
143 [ inlined-dependency depends-on ]
146 { [ dup inline-recursive-label ] [ call-recursive-inline-word ] }
147 { [ dup "recursive" word-prop ] [ inline-recursive-word ] }
148 [ dup (inline-word) ]
153 dup inline? [ inline-word ] [ non-inline-word ] if ;