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> inference-error ] [ pop ] if ;
49 : consume-r ( n -- seq )
51 [ too-many-r> inference-error ] when
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 inference-error ] 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 inference-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 quot -- )
128 #! quot is ( inputs outputs -- )
131 [ in>> length consume-d ]
132 [ out>> length produce-d ]
137 terminated?>> [ terminate ] when
140 : infer-word-def ( word -- )
141 [ specialized-def ] [ add-recursive-state ] bi infer-quot ;
144 meta-d clone #return, ;
146 : effect-required? ( word -- ? )
148 { [ dup inline? ] [ drop f ] }
149 { [ dup deferred? ] [ drop f ] }
150 { [ dup crossref? not ] [ drop f ] }
151 [ def>> [ word? ] contains? ]
154 : ?missing-effect ( word -- )
156 [ missing-effect inference-error ] [ drop ] if ;
158 : check-effect ( word effect -- )
160 { [ dup not ] [ 2drop ?missing-effect ] }
161 { [ 2dup effect<= ] [ 3drop ] }
165 : finish-word ( word -- )
168 [ drop recorded get push ]
169 [ "inferred-effect" set-word-prop ]
172 : cannot-infer-effect ( word -- * )
173 "cannot-infer" word-prop throw ;
175 : maybe-cannot-infer ( word quot -- )
176 [ [ "cannot-infer" set-word-prop ] keep throw ] recover ; inline
178 : infer-word ( word -- effect )
185 generic-dependencies off
186 [ infer-word-def end-infer ]
187 [ finish-word current-effect ]
190 ] maybe-cannot-infer ;
192 : apply-word/effect ( word effect -- )
193 swap '[ _ #call, ] consume/produce ;
195 : required-stack-effect ( word -- effect )
196 dup stack-effect [ ] [ \ missing-effect inference-error ] ?if ;
198 : call-recursive-word ( word -- )
199 dup required-stack-effect apply-word/effect ;
201 : cached-infer ( word -- )
202 dup "inferred-effect" word-prop apply-word/effect ;
204 : with-infer ( quot -- effect visitor )
207 V{ } clone recorded set
215 ] [ ] [ undo-infer ] cleanup
216 ] with-scope ; inline