1 ! Copyright (C) 2004, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: fry arrays generic io io.streams.string kernel math namespaces
4 parser sequences strings vectors words quotations effects classes
5 continuations assocs combinators compiler.errors accessors math.order
6 definitions locals sets hints macros stack-checker.state
7 stack-checker.visitor stack-checker.errors stack-checker.values
8 stack-checker.recursive-state stack-checker.dependencies summary ;
9 FROM: sequences.private => from-end ;
10 IN: stack-checker.backend
12 : push-d ( obj -- ) meta-d push ;
14 : introduce-values ( values -- )
15 [ [ [ input-parameter ] dip set-known ] each ]
16 [ length input-count +@ ]
20 : update-inner-d ( new -- )
21 inner-d-index get min inner-d-index set ;
25 [ <value> dup 1array introduce-values ]
26 [ pop meta-d length update-inner-d ] if-empty ;
28 : peek-d ( -- obj ) pop-d dup push-d ;
30 : make-values ( n -- values )
31 [ <value> ] replicate ;
33 : ensure-d ( n -- values )
34 meta-d 2dup length > [
36 [ nip >array ] [ length - make-values ] [ nip delete-all ] 2tri
37 [ introduce-values ] [ meta-d push-all ] bi
40 swap from-end [ tail ] [ update-inner-d ] bi ;
42 : shorten-by ( n seq -- )
43 [ length swap - ] keep shorten ; inline
46 meta-d shorten-by meta-d length update-inner-d ;
48 : consume-d ( n -- seq )
49 [ ensure-d ] [ shorten-d ] bi ;
51 : output-d ( values -- ) meta-d push-all ;
53 : produce-d ( n -- values )
54 make-values dup meta-d push-all ;
56 : push-r ( obj -- ) meta-r push ;
60 [ too-many-r> ] [ pop ] if ;
62 : consume-r ( n -- seq )
65 [ swap tail* ] [ shorten-by ] 2bi ;
67 : output-r ( seq -- ) meta-r push-all ;
69 : push-literal ( obj -- )
72 : pop-literal ( -- rstate obj )
76 [ literal [ recursion>> ] [ value>> ] bi ] bi
77 ] [ pop recursive-state get swap ] if-empty ;
79 : literals-available? ( n -- literals ? )
80 literals get 2dup length <=
81 [ [ swap tail* ] [ shorten-by ] 2bi t ] [ 2drop f f ] if ;
83 GENERIC: apply-object ( obj -- )
85 M: wrapper apply-object
87 [ dup word? [ depends-on-effect ] [ drop ] if ]
91 M: object apply-object push-literal ;
94 terminated? on meta-d clone meta-r clone #terminate, ;
97 meta-r empty? [ too-many->r ] unless ;
99 : infer-quot-here ( quot -- )
101 V{ } clone \ meta-r set
102 [ apply-object terminated? get not ] all?
103 [ commit-literals check->r ] [ literals get delete-all ] if
106 : infer-quot ( quot rstate -- )
107 recursive-state get [
110 ] dip recursive-state set ;
112 : time-bomb ( error -- )
113 '[ _ throw ] infer-quot-here ;
115 ERROR: bad-call obj ;
118 drop "call must be given a callable" ;
120 : infer-literal-quot ( literal -- )
121 dup recursive-quotation? [
122 value>> recursive-quotation-error
124 dup value>> callable? [
126 [ [ recursion>> ] keep add-local-quotation ]
129 value>> \ bad-call boa time-bomb
134 consume-d dup copy-values [ nip output-r ] [ #>r, ] 2bi ;
137 consume-r dup copy-values [ nip output-d ] [ #r>, ] 2bi ;
139 : consume/produce ( ..a effect quot: ( ..a inputs outputs -- ..b ) -- ..b )
140 '[ [ in>> length consume-d ] [ out>> length produce-d ] bi @ ]
141 [ terminated?>> [ terminate ] when ]
144 : apply-word/effect ( word effect -- )
145 swap '[ _ #call, ] consume/produce ;
148 meta-d clone #return, ;
150 : required-stack-effect ( word -- effect )
151 dup stack-effect [ ] [ missing-effect ] ?if ;
153 : infer-word ( word -- )
155 { [ dup macro? ] [ do-not-compile ] }
156 { [ dup "no-compile" word-prop ] [ do-not-compile ] }
157 [ dup required-stack-effect apply-word/effect ]
160 : with-infer ( quot -- effect visitor )
169 ] with-scope ; inline
171 : (infer) ( quot -- effect )
172 [ infer-quot-here ] with-infer drop ;
174 : ?quotation-effect ( in -- effect/f )
175 dup pair? [ second dup effect? [ drop f ] unless ] [ drop f ] if ;
177 :: declare-effect-d ( word effect variables branches n -- )
178 meta-d length :> d-length
180 d-length 1 - n - :> n'
181 n' meta-d nth :> value
183 known word effect variables branches <declared-effect> :> known'
184 known' value set-known
186 ] [ word unknown-macro-input ] if ;
188 :: declare-input-effects ( word -- )
189 H{ } clone :> variables
190 V{ } clone :> branches
191 word stack-effect in>> <reversed> [| in n |
192 in ?quotation-effect [| effect |
193 word effect variables branches n declare-effect-d