1 ! Copyright (C) 2004, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: fry arrays generic io io.streams.string kernel math
4 namespaces parser sequences strings vectors words quotations
5 effects classes continuations assocs combinators
6 compiler.errors accessors math.order definitions sets
7 generic.standard.engines.tuple hints stack-checker.state
8 stack-checker.visitor stack-checker.errors stack-checker.values
9 stack-checker.recursive-state ;
10 IN: stack-checker.backend
12 : push-d ( obj -- ) meta-d push ;
16 <value> dup 1array #introduce, d-in inc
19 : peek-d ( -- obj ) pop-d dup push-d ;
21 : make-values ( n -- values )
22 [ <value> ] replicate ;
24 : ensure-d ( n -- values )
25 meta-d 2dup length > [
27 [ nip >array ] [ length - make-values ] [ nip delete-all ] 2tri
28 [ length d-in +@ ] [ #introduce, ] [ meta-d push-all ] tri
32 : shorten-by ( n seq -- )
33 [ length swap - ] keep shorten ; inline
35 : consume-d ( n -- seq )
36 [ ensure-d ] [ meta-d shorten-by ] bi ;
38 : output-d ( values -- ) meta-d push-all ;
40 : produce-d ( n -- values )
41 make-values dup meta-d push-all ;
43 : push-r ( obj -- ) meta-r push ;
47 [ too-many-r> ] [ pop ] if ;
49 : consume-r ( n -- seq )
52 [ swap tail* ] [ shorten-by ] 2bi ;
54 : output-r ( seq -- ) meta-r push-all ;
56 : push-literal ( obj -- )
59 : pop-literal ( -- rstate obj )
63 [ literal [ recursion>> ] [ value>> ] bi ] bi
64 ] [ pop recursive-state get swap ] if-empty ;
66 : literals-available? ( n -- literals ? )
67 literals get 2dup length <=
68 [ [ swap tail* ] [ shorten-by ] 2bi t ] [ 2drop f f ] if ;
70 GENERIC: apply-object ( obj -- )
72 M: wrapper apply-object
74 [ dup word? [ called-dependency depends-on ] [ drop ] if ]
78 M: object apply-object push-literal ;
81 terminated? on meta-d clone meta-r clone #terminate, ;
84 meta-r empty? [ too-many->r ] unless ;
86 : infer-quot-here ( quot -- )
88 V{ } clone \ meta-r set
89 [ apply-object terminated? get not ] all?
90 [ commit-literals check->r ] [ literals get delete-all ] if
93 : infer-quot ( quot rstate -- )
97 ] dip recursive-state set ;
99 : time-bomb ( error -- )
100 '[ _ throw ] infer-quot-here ;
103 "call must be given a callable" time-bomb ;
105 : infer-literal-quot ( literal -- )
106 dup recursive-quotation? [
107 value>> recursive-quotation-error
109 dup value>> callable? [
111 [ [ recursion>> ] keep add-local-quotation ]
119 consume-d dup copy-values [ nip output-r ] [ #>r, ] 2bi ;
122 consume-r dup copy-values [ nip output-d ] [ #r>, ] 2bi ;
125 recorded get [ f "inferred-effect" set-word-prop ] each ;
127 : (consume/produce) ( effect -- inputs outputs )
128 [ in>> length consume-d ] [ out>> length produce-d ] bi ;
130 : consume/produce ( effect quot: ( inputs outputs -- ) -- )
131 '[ (consume/produce) @ ]
132 [ terminated?>> [ terminate ] when ]
135 : infer-word-def ( word -- )
136 [ specialized-def ] [ add-recursive-state ] bi infer-quot ;
139 meta-d clone #return, ;
141 : required-stack-effect ( word -- effect )
142 dup stack-effect [ ] [ missing-effect ] ?if ;
144 : check-effect ( word effect -- )
145 over required-stack-effect 2dup effect<=
146 [ 3drop ] [ effect-error ] if ;
148 : finish-word ( word -- )
149 [ current-effect check-effect ]
150 [ recorded get push ]
151 [ t "inferred-effect" set-word-prop ]
154 : cannot-infer-effect ( word -- * )
155 "cannot-infer" word-prop rethrow ;
157 : maybe-cannot-infer ( word quot -- )
158 [ [ "cannot-infer" set-word-prop ] keep throw ] recover ; inline
160 : infer-word ( word -- effect )
167 generic-dependencies off
168 [ infer-word-def end-infer ]
173 ] maybe-cannot-infer ;
175 : apply-word/effect ( word effect -- )
176 swap '[ _ #call, ] consume/produce ;
178 : call-recursive-word ( word -- )
179 dup required-stack-effect apply-word/effect ;
181 : cached-infer ( word -- )
182 dup stack-effect apply-word/effect ;
184 : with-infer ( quot -- effect visitor )
187 V{ } clone recorded set
195 ] [ ] [ undo-infer ] cleanup
196 ] with-scope ; inline