1 ! Copyright (C) 2004, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: fry accessors alien alien.accessors arrays byte-arrays
4 classes sequences.private continuations.private effects generic
5 hashtables hashtables.private io io.backend io.files
6 io.files.private io.streams.c kernel kernel.private math
7 math.private memory namespaces namespaces.private parser
8 quotations quotations.private sbufs sbufs.private
9 sequences sequences.private slots.private strings
10 strings.private system threads.private classes.tuple
11 classes.tuple.private vectors vectors.private words definitions
12 words.private assocs summary compiler.units system.private
13 combinators locals locals.backend locals.types words.private
14 quotations.private combinators.private stack-checker.values
20 stack-checker.branches
21 stack-checker.transforms
22 stack-checker.recursive-state ;
23 IN: stack-checker.known-words
25 : infer-primitive ( word -- )
27 [ "input-classes" word-prop ]
28 [ "default-output-classes" word-prop ] bi <effect>
33 { 2drop (( x y -- )) }
34 { 3drop (( x y z -- )) }
35 { dup (( x -- x x )) }
36 { 2dup (( x y -- x y x y )) }
37 { 3dup (( x y z -- x y z x y z )) }
38 { rot (( x y z -- y z x )) }
39 { -rot (( x y z -- z x y )) }
40 { dupd (( x y -- x x y )) }
41 { swapd (( x y z -- y x z )) }
42 { nip (( x y -- y )) }
43 { 2nip (( x y z -- z )) }
44 { tuck (( x y -- y x y )) }
45 { over (( x y -- x y x )) }
46 { pick (( x y z -- x y z x )) }
47 { swap (( x y -- y x )) }
48 } [ "shuffle" set-word-prop ] assoc-each
50 : infer-shuffle ( shuffle -- )
51 [ in>> length consume-d ] keep ! inputs shuffle
52 [ drop ] [ shuffle dup copy-values dup output-d ] 2bi ! inputs outputs copies
53 [ nip f f ] [ swap zip ] 2bi ! in-d out-d in-r out-r mapping
56 : infer-shuffle-word ( word -- )
57 "shuffle" word-prop infer-shuffle ;
59 : infer-declare ( -- )
61 [ length ensure-d ] keep zip
64 GENERIC: infer-call* ( value known -- )
66 : (infer-call) ( value -- ) dup known infer-call* ;
68 : infer-call ( -- ) pop-d (infer-call) ;
70 M: literal infer-call*
71 [ 1array #drop, ] [ infer-literal-quot ] bi* ;
73 M: curried infer-call*
75 [ uncurry ] infer-quot-here
76 [ quot>> known pop-d [ set-known ] keep ]
77 [ obj>> known pop-d [ set-known ] keep ] bi
80 M: composed infer-call*
82 [ uncompose ] infer-quot-here
83 [ quot2>> known pop-d [ set-known ] keep ]
84 [ quot1>> known pop-d [ set-known ] keep ] bi
87 terminated? get [ 1 infer-r> infer-call ] unless ;
90 "literal quotation" literal-expected ;
92 : infer-nslip ( n -- )
93 [ infer->r infer-call ] [ infer-r> ] bi ;
95 : infer-slip ( -- ) 1 infer-nslip ;
97 : infer-2slip ( -- ) 2 infer-nslip ;
99 : infer-3slip ( -- ) 3 infer-nslip ;
101 : infer-ndip ( word n -- )
102 [ literals get ] 2dip
103 [ '[ _ def>> infer-quot-here ] ]
104 [ '[ _ [ pop ] dip [ infer->r infer-quot-here ] [ infer-r> ] bi ] ] bi*
107 : infer-dip ( -- ) \ dip 1 infer-ndip ;
109 : infer-2dip ( -- ) \ 2dip 2 infer-ndip ;
111 : infer-3dip ( -- ) \ 3dip 3 infer-ndip ;
113 : infer-builder ( quot word -- )
116 [ dup first2 ] dip call make-known
117 [ push-d ] [ 1array ] bi
118 ] dip #call, ; inline
120 : infer-curry ( -- ) [ <curried> ] \ curry infer-builder ;
122 : infer-compose ( -- ) [ <composed> ] \ compose infer-builder ;
124 : infer-execute ( -- )
130 "execute must be given a word" time-bomb
133 : infer-<tuple-boa> ( -- )
135 peek-d literal value>> second 1+ { tuple } <effect>
138 : infer-effect-unsafe ( word -- )
143 : infer-execute-effect-unsafe ( -- )
144 \ execute infer-effect-unsafe ;
146 : infer-call-effect-unsafe ( -- )
147 \ call infer-effect-unsafe ;
150 \ exit (( n -- * )) apply-word/effect ;
152 : infer-load-locals ( -- )
154 consume-d dup copy-values dup output-r
155 [ [ f f ] dip ] [ swap zip ] 2bi #shuffle, ;
157 : infer-get-local ( -- )
158 [let* | n [ pop-literal nip 1 swap - ]
160 out-d [ in-r first copy-value 1array ]
161 out-r [ in-r copy-values ] |
165 out-r in-r zip out-d first in-r first 2array suffix
169 : infer-drop-locals ( -- )
170 f f pop-literal nip consume-r f f #shuffle, ;
172 : infer-special ( word -- )
174 { \ declare [ infer-declare ] }
175 { \ call [ infer-call ] }
176 { \ (call) [ infer-call ] }
177 { \ slip [ infer-slip ] }
178 { \ 2slip [ infer-2slip ] }
179 { \ 3slip [ infer-3slip ] }
180 { \ dip [ infer-dip ] }
181 { \ 2dip [ infer-2dip ] }
182 { \ 3dip [ infer-3dip ] }
183 { \ curry [ infer-curry ] }
184 { \ compose [ infer-compose ] }
185 { \ execute [ infer-execute ] }
186 { \ (execute) [ infer-execute ] }
187 { \ execute-effect-unsafe [ infer-execute-effect-unsafe ] }
188 { \ call-effect-unsafe [ infer-call-effect-unsafe ] }
189 { \ if [ infer-if ] }
190 { \ dispatch [ infer-dispatch ] }
191 { \ <tuple-boa> [ infer-<tuple-boa> ] }
192 { \ exit [ infer-exit ] }
193 { \ load-local [ 1 infer->r ] }
194 { \ load-locals [ infer-load-locals ] }
195 { \ get-local [ infer-get-local ] }
196 { \ drop-locals [ infer-drop-locals ] }
197 { \ do-primitive [ unknown-primitive-error ] }
198 { \ alien-invoke [ infer-alien-invoke ] }
199 { \ alien-indirect [ infer-alien-indirect ] }
200 { \ alien-callback [ infer-alien-callback ] }
203 : infer-local-reader ( word -- )
204 (( -- value )) apply-word/effect ;
206 : infer-local-writer ( word -- )
207 (( value -- )) apply-word/effect ;
209 : infer-local-word ( word -- )
210 "local-word-def" word-prop infer-quot-here ;
213 declare call (call) slip 2slip 3slip dip 2dip 3dip curry compose
214 execute (execute) call-effect-unsafe execute-effect-unsafe if
215 dispatch <tuple-boa> exit load-local load-locals get-local
216 drop-locals do-primitive alien-invoke alien-indirect
218 } [ t "special" set-word-prop ] each
220 { call execute dispatch load-locals get-local drop-locals }
221 [ t "no-compile" set-word-prop ] each
223 : non-inline-word ( word -- )
224 dup called-dependency depends-on
226 { [ dup "shuffle" word-prop ] [ infer-shuffle-word ] }
227 { [ dup "special" word-prop ] [ infer-special ] }
228 { [ dup "primitive" word-prop ] [ infer-primitive ] }
229 { [ dup "transform-quot" word-prop ] [ apply-transform ] }
230 { [ dup "macro" word-prop ] [ apply-macro ] }
231 { [ dup "cannot-infer" word-prop ] [ cannot-infer-effect ] }
232 { [ dup "inferred-effect" word-prop ] [ cached-infer ] }
233 { [ dup local? ] [ infer-local-reader ] }
234 { [ dup local-reader? ] [ infer-local-reader ] }
235 { [ dup local-writer? ] [ infer-local-writer ] }
236 { [ dup local-word? ] [ infer-local-word ] }
237 { [ dup recursive-word? ] [ call-recursive-word ] }
238 [ dup infer-word apply-word/effect ]
241 : define-primitive ( word inputs outputs -- )
242 [ 2drop t "primitive" set-word-prop ]
243 [ drop "input-classes" set-word-prop ]
244 [ nip "default-output-classes" set-word-prop ]
247 ! Stack effects for all primitives
248 \ fixnum< { fixnum fixnum } { object } define-primitive
249 \ fixnum< make-foldable
251 \ fixnum<= { fixnum fixnum } { object } define-primitive
252 \ fixnum<= make-foldable
254 \ fixnum> { fixnum fixnum } { object } define-primitive
255 \ fixnum> make-foldable
257 \ fixnum>= { fixnum fixnum } { object } define-primitive
258 \ fixnum>= make-foldable
260 \ eq? { object object } { object } define-primitive
263 \ bignum>fixnum { bignum } { fixnum } define-primitive
264 \ bignum>fixnum make-foldable
266 \ float>fixnum { float } { fixnum } define-primitive
267 \ bignum>fixnum make-foldable
269 \ fixnum>bignum { fixnum } { bignum } define-primitive
270 \ fixnum>bignum make-foldable
272 \ float>bignum { float } { bignum } define-primitive
273 \ float>bignum make-foldable
275 \ fixnum>float { fixnum } { float } define-primitive
276 \ fixnum>float make-foldable
278 \ bignum>float { bignum } { float } define-primitive
279 \ bignum>float make-foldable
281 \ <ratio> { integer integer } { ratio } define-primitive
282 \ <ratio> make-foldable
284 \ string>float { string } { float } define-primitive
285 \ string>float make-foldable
287 \ float>string { float } { string } define-primitive
288 \ float>string make-foldable
290 \ float>bits { real } { integer } define-primitive
291 \ float>bits make-foldable
293 \ double>bits { real } { integer } define-primitive
294 \ double>bits make-foldable
296 \ bits>float { integer } { float } define-primitive
297 \ bits>float make-foldable
299 \ bits>double { integer } { float } define-primitive
300 \ bits>double make-foldable
302 \ <complex> { real real } { complex } define-primitive
303 \ <complex> make-foldable
305 \ both-fixnums? { object object } { object } define-primitive
307 \ fixnum+ { fixnum fixnum } { integer } define-primitive
308 \ fixnum+ make-foldable
310 \ fixnum+fast { fixnum fixnum } { fixnum } define-primitive
311 \ fixnum+fast make-foldable
313 \ fixnum- { fixnum fixnum } { integer } define-primitive
314 \ fixnum- make-foldable
316 \ fixnum-fast { fixnum fixnum } { fixnum } define-primitive
317 \ fixnum-fast make-foldable
319 \ fixnum* { fixnum fixnum } { integer } define-primitive
320 \ fixnum* make-foldable
322 \ fixnum*fast { fixnum fixnum } { fixnum } define-primitive
323 \ fixnum*fast make-foldable
325 \ fixnum/i { fixnum fixnum } { integer } define-primitive
326 \ fixnum/i make-foldable
328 \ fixnum/i-fast { fixnum fixnum } { fixnum } define-primitive
329 \ fixnum/i-fast make-foldable
331 \ fixnum-mod { fixnum fixnum } { fixnum } define-primitive
332 \ fixnum-mod make-foldable
334 \ fixnum/mod { fixnum fixnum } { integer fixnum } define-primitive
335 \ fixnum/mod make-foldable
337 \ fixnum/mod-fast { fixnum fixnum } { fixnum fixnum } define-primitive
338 \ fixnum/mod-fast make-foldable
340 \ fixnum-bitand { fixnum fixnum } { fixnum } define-primitive
341 \ fixnum-bitand make-foldable
343 \ fixnum-bitor { fixnum fixnum } { fixnum } define-primitive
344 \ fixnum-bitor make-foldable
346 \ fixnum-bitxor { fixnum fixnum } { fixnum } define-primitive
347 \ fixnum-bitxor make-foldable
349 \ fixnum-bitnot { fixnum } { fixnum } define-primitive
350 \ fixnum-bitnot make-foldable
352 \ fixnum-shift { fixnum fixnum } { integer } define-primitive
353 \ fixnum-shift make-foldable
355 \ fixnum-shift-fast { fixnum fixnum } { fixnum } define-primitive
356 \ fixnum-shift-fast make-foldable
358 \ bignum= { bignum bignum } { object } define-primitive
359 \ bignum= make-foldable
361 \ bignum+ { bignum bignum } { bignum } define-primitive
362 \ bignum+ make-foldable
364 \ bignum- { bignum bignum } { bignum } define-primitive
365 \ bignum- make-foldable
367 \ bignum* { bignum bignum } { bignum } define-primitive
368 \ bignum* make-foldable
370 \ bignum/i { bignum bignum } { bignum } define-primitive
371 \ bignum/i make-foldable
373 \ bignum-mod { bignum bignum } { bignum } define-primitive
374 \ bignum-mod make-foldable
376 \ bignum/mod { bignum bignum } { bignum bignum } define-primitive
377 \ bignum/mod make-foldable
379 \ bignum-bitand { bignum bignum } { bignum } define-primitive
380 \ bignum-bitand make-foldable
382 \ bignum-bitor { bignum bignum } { bignum } define-primitive
383 \ bignum-bitor make-foldable
385 \ bignum-bitxor { bignum bignum } { bignum } define-primitive
386 \ bignum-bitxor make-foldable
388 \ bignum-bitnot { bignum } { bignum } define-primitive
389 \ bignum-bitnot make-foldable
391 \ bignum-shift { bignum fixnum } { bignum } define-primitive
392 \ bignum-shift make-foldable
394 \ bignum< { bignum bignum } { object } define-primitive
395 \ bignum< make-foldable
397 \ bignum<= { bignum bignum } { object } define-primitive
398 \ bignum<= make-foldable
400 \ bignum> { bignum bignum } { object } define-primitive
401 \ bignum> make-foldable
403 \ bignum>= { bignum bignum } { object } define-primitive
404 \ bignum>= make-foldable
406 \ bignum-bit? { bignum integer } { object } define-primitive
407 \ bignum-bit? make-foldable
409 \ bignum-log2 { bignum } { bignum } define-primitive
410 \ bignum-log2 make-foldable
412 \ byte-array>bignum { byte-array } { bignum } define-primitive
413 \ byte-array>bignum make-foldable
415 \ float= { float float } { object } define-primitive
416 \ float= make-foldable
418 \ float+ { float float } { float } define-primitive
419 \ float+ make-foldable
421 \ float- { float float } { float } define-primitive
422 \ float- make-foldable
424 \ float* { float float } { float } define-primitive
425 \ float* make-foldable
427 \ float/f { float float } { float } define-primitive
428 \ float/f make-foldable
430 \ float< { float float } { object } define-primitive
431 \ float< make-foldable
433 \ float-mod { float float } { float } define-primitive
434 \ float-mod make-foldable
436 \ float<= { float float } { object } define-primitive
437 \ float<= make-foldable
439 \ float> { float float } { object } define-primitive
440 \ float> make-foldable
442 \ float>= { float float } { object } define-primitive
443 \ float>= make-foldable
445 \ <word> { object object } { word } define-primitive
446 \ <word> make-flushable
448 \ word-xt { word } { integer integer } define-primitive
449 \ word-xt make-flushable
451 \ getenv { fixnum } { object } define-primitive
452 \ getenv make-flushable
454 \ setenv { object fixnum } { } define-primitive
456 \ (exists?) { string } { object } define-primitive
458 \ gc { } { } define-primitive
460 \ gc-stats { } { array } define-primitive
462 \ save-image { string } { } define-primitive
464 \ save-image-and-exit { string } { } define-primitive
466 \ data-room { } { integer integer array } define-primitive
467 \ data-room make-flushable
469 \ code-room { } { integer integer integer integer } define-primitive
470 \ code-room make-flushable
472 \ micros { } { integer } define-primitive
473 \ micros make-flushable
475 \ tag { object } { fixnum } define-primitive
478 \ dlopen { string } { dll } define-primitive
480 \ dlsym { string object } { c-ptr } define-primitive
482 \ dlclose { dll } { } define-primitive
484 \ <byte-array> { integer } { byte-array } define-primitive
485 \ <byte-array> make-flushable
487 \ (byte-array) { integer } { byte-array } define-primitive
488 \ (byte-array) make-flushable
490 \ <displaced-alien> { integer c-ptr } { c-ptr } define-primitive
491 \ <displaced-alien> make-flushable
493 \ alien-signed-cell { c-ptr integer } { integer } define-primitive
494 \ alien-signed-cell make-flushable
496 \ set-alien-signed-cell { integer c-ptr integer } { } define-primitive
498 \ alien-unsigned-cell { c-ptr integer } { integer } define-primitive
499 \ alien-unsigned-cell make-flushable
501 \ set-alien-unsigned-cell { integer c-ptr integer } { } define-primitive
503 \ alien-signed-8 { c-ptr integer } { integer } define-primitive
504 \ alien-signed-8 make-flushable
506 \ set-alien-signed-8 { integer c-ptr integer } { } define-primitive
508 \ alien-unsigned-8 { c-ptr integer } { integer } define-primitive
509 \ alien-unsigned-8 make-flushable
511 \ set-alien-unsigned-8 { integer c-ptr integer } { } define-primitive
513 \ alien-signed-4 { c-ptr integer } { integer } define-primitive
514 \ alien-signed-4 make-flushable
516 \ set-alien-signed-4 { integer c-ptr integer } { } define-primitive
518 \ alien-unsigned-4 { c-ptr integer } { integer } define-primitive
519 \ alien-unsigned-4 make-flushable
521 \ set-alien-unsigned-4 { integer c-ptr integer } { } define-primitive
523 \ alien-signed-2 { c-ptr integer } { fixnum } define-primitive
524 \ alien-signed-2 make-flushable
526 \ set-alien-signed-2 { integer c-ptr integer } { } define-primitive
528 \ alien-unsigned-2 { c-ptr integer } { fixnum } define-primitive
529 \ alien-unsigned-2 make-flushable
531 \ set-alien-unsigned-2 { integer c-ptr integer } { } define-primitive
533 \ alien-signed-1 { c-ptr integer } { fixnum } define-primitive
534 \ alien-signed-1 make-flushable
536 \ set-alien-signed-1 { integer c-ptr integer } { } define-primitive
538 \ alien-unsigned-1 { c-ptr integer } { fixnum } define-primitive
539 \ alien-unsigned-1 make-flushable
541 \ set-alien-unsigned-1 { integer c-ptr integer } { } define-primitive
543 \ alien-float { c-ptr integer } { float } define-primitive
544 \ alien-float make-flushable
546 \ set-alien-float { float c-ptr integer } { } define-primitive
548 \ alien-double { c-ptr integer } { float } define-primitive
549 \ alien-double make-flushable
551 \ set-alien-double { float c-ptr integer } { } define-primitive
553 \ alien-cell { c-ptr integer } { simple-c-ptr } define-primitive
554 \ alien-cell make-flushable
556 \ set-alien-cell { c-ptr c-ptr integer } { } define-primitive
558 \ alien-address { alien } { integer } define-primitive
559 \ alien-address make-flushable
561 \ slot { object fixnum } { object } define-primitive
562 \ slot make-flushable
564 \ set-slot { object object fixnum } { } define-primitive
566 \ string-nth { fixnum string } { fixnum } define-primitive
567 \ string-nth make-flushable
569 \ set-string-nth-slow { fixnum fixnum string } { } define-primitive
570 \ set-string-nth-fast { fixnum fixnum string } { } define-primitive
572 \ resize-array { integer array } { array } define-primitive
573 \ resize-array make-flushable
575 \ resize-byte-array { integer byte-array } { byte-array } define-primitive
576 \ resize-byte-array make-flushable
578 \ resize-string { integer string } { string } define-primitive
579 \ resize-string make-flushable
581 \ <array> { integer object } { array } define-primitive
582 \ <array> make-flushable
584 \ begin-scan { } { } define-primitive
586 \ next-object { } { object } define-primitive
588 \ end-scan { } { } define-primitive
590 \ size { object } { fixnum } define-primitive
591 \ size make-flushable
593 \ die { } { } define-primitive
595 \ fopen { string string } { alien } define-primitive
597 \ fgetc { alien } { object } define-primitive
599 \ fwrite { string alien } { } define-primitive
601 \ fputc { object alien } { } define-primitive
603 \ fread { integer string } { object } define-primitive
605 \ fflush { alien } { } define-primitive
607 \ fclose { alien } { } define-primitive
609 \ <wrapper> { object } { wrapper } define-primitive
610 \ <wrapper> make-foldable
612 \ (clone) { object } { object } define-primitive
613 \ (clone) make-flushable
615 \ <string> { integer integer } { string } define-primitive
616 \ <string> make-flushable
618 \ array>quotation { array } { quotation } define-primitive
619 \ array>quotation make-flushable
621 \ quotation-xt { quotation } { integer } define-primitive
622 \ quotation-xt make-flushable
624 \ <tuple> { tuple-layout } { tuple } define-primitive
625 \ <tuple> make-flushable
627 \ datastack { } { array } define-primitive
628 \ datastack make-flushable
630 \ check-datastack { array integer integer } { object } define-primitive
631 \ check-datastack make-flushable
633 \ retainstack { } { array } define-primitive
634 \ retainstack make-flushable
636 \ callstack { } { callstack } define-primitive
637 \ callstack make-flushable
639 \ callstack>array { callstack } { array } define-primitive
640 \ callstack>array make-flushable
642 \ (sleep) { integer } { } define-primitive
644 \ become { array array } { } define-primitive
646 \ innermost-frame-quot { callstack } { quotation } define-primitive
648 \ innermost-frame-scan { callstack } { fixnum } define-primitive
650 \ set-innermost-frame-quot { quotation callstack } { } define-primitive
652 \ dll-valid? { object } { object } define-primitive
654 \ modify-code-heap { array } { } define-primitive
656 \ unimplemented { } { } define-primitive
658 \ gc-reset { } { } define-primitive
660 \ gc-stats { } { array } define-primitive
662 \ jit-compile { quotation } { } define-primitive