factor/core/inference/inference-tests.factor

563 lines
16 KiB
Factor
Raw Normal View History

2007-09-20 18:09:08 -04:00
USING: arrays generic inference inference.backend
inference.dataflow kernel classes kernel.private math
math.parser math.private namespaces namespaces.private parser
sequences strings vectors words quotations effects tools.test
continuations generic.standard sorting assocs definitions
prettyprint io inspector bootstrap.image tuples
classes.union classes.predicate debugger bootstrap.image
bootstrap.image.private io.launcher threads.private
io.streams.string combinators.private ;
IN: temporary
: short-effect
dup effect-in length swap effect-out length 2array ;
[ { 0 2 } ] [ [ 2 "Hello" ] infer short-effect ] unit-test
[ { 1 2 } ] [ [ dup ] infer short-effect ] unit-test
[ { 1 2 } ] [ [ [ dup ] call ] infer short-effect ] unit-test
[ [ call ] infer short-effect ] unit-test-fails
[ { 2 4 } ] [ [ 2dup ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ [ ] [ ] if ] infer short-effect ] unit-test
[ [ if ] infer short-effect ] unit-test-fails
[ [ [ ] if ] infer short-effect ] unit-test-fails
[ [ [ 2 ] [ ] if ] infer short-effect ] unit-test-fails
[ { 4 3 } ] [ [ [ rot ] [ -rot ] if ] infer short-effect ] unit-test
[ { 4 3 } ] [
[
[
[ swap 3 ] [ nip 5 5 ] if
] [
-rot
] if
] infer short-effect
] unit-test
[ { 1 1 } ] [ [ dup [ ] when ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ dup [ dup fixnum* ] when ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ [ dup fixnum* ] when ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ [ drop ] when* ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ [ { { [ ] } } ] unless* ] infer short-effect ] unit-test
[ { 0 1 } ] [
[ [ 2 2 fixnum+ ] dup [ ] when call ] infer short-effect
] unit-test
[
[ [ [ 2 2 fixnum+ ] ] [ [ 2 2 fixnum* ] ] if call ] infer
] unit-test-fails
! Test inference of termination of control flow
: termination-test-1
"foo" throw ;
: termination-test-2 [ termination-test-1 ] [ 3 ] if ;
[ { 1 1 } ] [ [ termination-test-2 ] infer short-effect ] unit-test
: infinite-loop infinite-loop ;
[ [ infinite-loop ] infer short-effect ] unit-test-fails
: no-base-case-1 dup [ no-base-case-1 ] [ no-base-case-1 ] if ;
[ [ no-base-case-1 ] infer short-effect ] unit-test-fails
: simple-recursion-1 ( obj -- obj )
dup [ simple-recursion-1 ] [ ] if ;
[ { 1 1 } ] [ [ simple-recursion-1 ] infer short-effect ] unit-test
: simple-recursion-2 ( obj -- obj )
dup [ ] [ simple-recursion-2 ] if ;
[ { 1 1 } ] [ [ simple-recursion-2 ] infer short-effect ] unit-test
: bad-recursion-2 ( obj -- obj )
dup [ dup first swap second bad-recursion-2 ] [ ] if ;
[ [ bad-recursion-2 ] infer short-effect ] unit-test-fails
: funny-recursion ( obj -- obj )
dup [ funny-recursion 1 ] [ 2 ] if drop ;
[ { 1 1 } ] [ [ funny-recursion ] infer short-effect ] unit-test
! Simple combinators
[ { 1 2 } ] [ [ [ first ] keep second ] infer short-effect ] unit-test
! Mutual recursion
DEFER: foe
: fie ( element obj -- ? )
dup array? [ foe ] [ eq? ] if ;
: foe ( element tree -- ? )
dup [
2dup first fie [
nip
] [
second dup array? [
foe
] [
fie
] if
] if
] [
2drop f
] if ;
[ { 2 1 } ] [ [ fie ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ foe ] infer short-effect ] unit-test
: nested-when ( -- )
t [
t [
5 drop
] when
] when ;
[ { 0 0 } ] [ [ nested-when ] infer short-effect ] unit-test
: nested-when* ( obj -- )
[
[
drop
] when*
] when* ;
[ { 1 0 } ] [ [ nested-when* ] infer short-effect ] unit-test
SYMBOL: sym-test
[ { 0 1 } ] [ [ sym-test ] infer short-effect ] unit-test
: terminator-branch
dup [
length
] [
"foo" throw
] if ;
[ { 1 1 } ] [ [ terminator-branch ] infer short-effect ] unit-test
: recursive-terminator ( obj -- )
dup [
recursive-terminator
] [
"Hi" throw
] if ;
[ { 1 0 } ] [ [ recursive-terminator ] infer short-effect ] unit-test
GENERIC: potential-hang ( obj -- obj )
M: fixnum potential-hang dup [ potential-hang ] when ;
[ ] [ [ 5 potential-hang ] infer short-effect drop ] unit-test
TUPLE: funny-cons car cdr ;
GENERIC: iterate ( obj -- )
M: funny-cons iterate funny-cons-cdr iterate ;
M: f iterate drop ;
M: real iterate drop ;
[ { 1 0 } ] [ [ iterate ] infer short-effect ] unit-test
! Regression
: cat ( obj -- * ) dup [ throw ] [ throw ] if ;
: dog ( a b c -- ) dup [ cat ] [ 3drop ] if ;
[ { 3 0 } ] [ [ dog ] infer short-effect ] unit-test
! Regression
DEFER: monkey
: friend ( a b c -- ) dup [ friend ] [ monkey ] if ;
: monkey ( a b c -- ) dup [ 3drop ] [ friend ] if ;
[ { 3 0 } ] [ [ friend ] infer short-effect ] unit-test
! Regression -- same as above but we infer short-effect the second word first
DEFER: blah2
: blah ( a b c -- ) dup [ blah ] [ blah2 ] if ;
: blah2 ( a b c -- ) dup [ blah ] [ 3drop ] if ;
[ { 3 0 } ] [ [ blah2 ] infer short-effect ] unit-test
! Regression
DEFER: blah4
: blah3 ( a b c -- )
dup [ blah3 ] [ dup [ blah4 ] [ blah3 ] if ] if ;
: blah4 ( a b c -- )
dup [ blah4 ] [ dup [ 3drop ] [ blah3 ] if ] if ;
[ { 3 0 } ] [ [ blah4 ] infer short-effect ] unit-test
! Regression
: bad-combinator ( obj quot -- )
over [
2drop
] [
[ swap slip ] keep swap bad-combinator
] if ; inline
[ [ [ 1 ] [ ] bad-combinator ] infer short-effect ] unit-test-fails
! Regression
: bad-input#
dup string? [ 2array throw ] unless
over string? [ 2array throw ] unless ;
[ { 2 2 } ] [ [ bad-input# ] infer short-effect ] unit-test
! Regression
! This order of branches works
DEFER: do-crap
: more-crap ( obj -- ) dup [ drop ] [ dup do-crap call ] if ;
: do-crap ( obj -- ) dup [ more-crap ] [ do-crap ] if ;
[ [ do-crap ] infer short-effect ] unit-test-fails
! This one does not
DEFER: do-crap*
: more-crap* ( obj -- ) dup [ drop ] [ dup do-crap* call ] if ;
: do-crap* ( obj -- ) dup [ do-crap* ] [ more-crap* ] if ;
[ [ do-crap* ] infer short-effect ] unit-test-fails
! Regression
: too-deep ( a b -- c )
dup [ drop ] [ 2dup too-deep too-deep * ] if ; inline
[ { 2 1 } ] [ [ too-deep ] infer short-effect ] unit-test
! Error reporting is wrong
MATH: xyz
M: fixnum xyz 2array ;
M: float xyz
[ 3 ] 2apply swapd >r 2array swap r> 2array swap ;
2007-09-20 18:09:08 -04:00
[ t ] [ [ [ xyz ] infer short-effect ] catch inference-error? ] unit-test
! Doug Coleman discovered this one while working on the
! calendar library
DEFER: A
DEFER: B
DEFER: C
: A ( a -- )
dup {
[ drop ]
[ A ]
[ \ A no-method ]
[ dup C A ]
} dispatch ;
: B ( b -- )
dup {
[ C ]
[ B ]
[ \ B no-method ]
[ dup B B ]
} dispatch ;
: C ( c -- )
dup {
[ A ]
[ C ]
[ \ C no-method ]
[ dup B C ]
} dispatch ;
[ { 1 0 } ] [ [ A ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ B ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ C ] infer short-effect ] unit-test
! I found this bug by thinking hard about the previous one
DEFER: Y
: X ( a b -- c d ) dup [ swap Y ] [ ] if ;
: Y ( a b -- c d ) X ;
[ { 2 2 } ] [ [ X ] infer short-effect ] unit-test
[ { 2 2 } ] [ [ Y ] infer short-effect ] unit-test
! This one comes from UI code
DEFER: #1
: #2 ( a b -- ) dup [ call ] [ 2drop ] if ; inline
: #3 ( a -- ) [ #1 ] #2 ;
: #4 ( a -- ) dup [ drop ] [ dup #4 dup #3 call ] if ;
: #1 ( a -- ) dup [ dup #4 dup #3 ] [ ] if drop ;
[ \ #4 word-def infer short-effect ] unit-test-fails
[ [ #1 ] infer short-effect ] unit-test-fails
! Similar
DEFER: bar
: foo ( a b -- c d ) dup [ 2drop f f bar ] [ ] if ;
: bar ( a b -- ) [ 2 2 + ] t foo drop call drop ;
[ [ foo ] infer short-effect ] unit-test-fails
[ 1234 infer short-effect ] unit-test-fails
! This used to hang
[ t ] [
[ [ [ dup call ] dup call ] infer ] catch
inference-error?
] unit-test
: m dup call ; inline
[ t ] [
[ [ [ m ] m ] infer ] catch inference-error?
] unit-test
: m' dup curry call ; inline
[ t ] [
[ [ [ m' ] m' ] infer ] catch inference-error?
] unit-test
: m'' [ dup curry ] ; inline
: m''' m'' call call ; inline
[ t ] [
[ [ [ m''' ] m''' ] infer ] catch inference-error?
] unit-test
: m-if t over if ; inline
[ t ] [
[ [ [ m-if ] m-if ] infer ] catch inference-error?
] unit-test
! This doesn't hang but it's also an example of the
! undedicable case
[ t ] [
[ [ [ [ drop 3 ] swap call ] dup call ] infer ] catch
inference-error?
] unit-test
! This form should not have a stack effect
: bad-recursion-1 ( a -- b )
dup [ drop bad-recursion-1 5 ] [ ] if ;
[ [ bad-recursion-1 ] infer short-effect ] unit-test-fails
: bad-bin ( a b -- ) 5 [ 5 bad-bin bad-bin 5 ] [ 2drop ] if ;
[ [ bad-bin ] infer short-effect ] unit-test-fails
[ t ] [ [ [ r> ] infer short-effect ] catch inference-error? ] unit-test
2007-10-10 01:53:55 -04:00
! Regression
[ t ] [ [ [ get-slots ] infer ] catch inference-error? ] unit-test
2007-09-20 18:09:08 -04:00
! Test some curry stuff
[ { 1 1 } ] [ [ 3 [ ] curry 4 [ ] curry if ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ [ ] curry 4 [ ] curry if ] infer short-effect ] unit-test
[ [ 3 [ ] curry 1 2 [ ] 2curry if ] infer ] unit-test-fails
! Test number protocol
[ { 2 1 } ] [ [ bitor ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ bitand ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ bitxor ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ mod ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ /i ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ /f ] infer short-effect ] unit-test
[ { 2 2 } ] [ [ /mod ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ + ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ - ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ * ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ / ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ < ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ <= ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ > ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ >= ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ number= ] infer short-effect ] unit-test
! Test object protocol
[ { 2 1 } ] [ [ = ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ clone ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ hashcode* ] infer short-effect ] unit-test
! Test sequence protocol
[ { 1 1 } ] [ [ length ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ nth ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ set-length ] infer short-effect ] unit-test
[ { 3 0 } ] [ [ set-nth ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ new ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ new-resizable ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ like ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ lengthen ] infer short-effect ] unit-test
! Test assoc protocol
[ { 2 2 } ] [ [ at* ] infer short-effect ] unit-test
[ { 3 0 } ] [ [ set-at ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ new-assoc ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ delete-at ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ clear-assoc ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ assoc-size ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ assoc-like ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ assoc-clone-like ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ >alist ] infer short-effect ] unit-test
[ { 1 3 } ] [ [ [ 2drop f ] assoc-find ] infer short-effect ] unit-test
! Test some random library words
[ { 1 1 } ] [ [ 1quotation ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ string>number ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ get ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ push ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ append ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ peek ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ reverse ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ member? ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ remove ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ natural-sort ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ forget ] infer short-effect ] unit-test
[ { 4 0 } ] [ [ define-class ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ define-tuple-class ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ define-union-class ] infer short-effect ] unit-test
[ { 3 0 } ] [ [ define-predicate-class ] infer short-effect ] unit-test
! Test words with continuations
[ { 0 0 } ] [ [ [ drop ] callcc0 ] infer short-effect ] unit-test
[ { 0 1 } ] [ [ [ 4 swap continue-with ] callcc1 ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ [ + ] [ ] [ ] cleanup ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ [ + ] [ 3drop 0 ] recover ] infer short-effect ] unit-test
! Test stream protocol
[ { 2 0 } ] [ [ set-timeout ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ stream-read ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ stream-read1 ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ stream-readln ] infer short-effect ] unit-test
[ { 2 2 } ] [ [ stream-read-until ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ stream-write ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ stream-write1 ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ stream-nl ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ stream-close ] infer short-effect ] unit-test
[ { 3 0 } ] [ [ stream-format ] infer short-effect ] unit-test
[ { 3 0 } ] [ [ stream-write-table ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ stream-flush ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ make-span-stream ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ make-block-stream ] infer short-effect ] unit-test
[ { 2 1 } ] [ [ make-cell-stream ] infer short-effect ] unit-test
! Test stream utilities
[ { 1 1 } ] [ [ lines ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ contents ] infer short-effect ] unit-test
! Test prettyprinting
[ { 1 0 } ] [ [ . ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ short. ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ unparse ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ describe ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ error. ] infer short-effect ] unit-test
! Test odds and ends
[ { 1 1 } ] [ [ ' ] infer short-effect ] unit-test
[ { 2 0 } ] [ [ write-image ] infer short-effect ] unit-test
[ { 1 1 } ] [ [ <process-stream> ] infer short-effect ] unit-test
[ { 0 0 } ] [ [ idle-thread ] infer short-effect ] unit-test
! Incorrect stack declarations on inline recursive words should
! be caught
: fooxxx ( a b -- c ) over [ foo ] when ; inline
: barxxx fooxxx ;
[ [ barxxx ] infer ] unit-test-fails
! A typo
[ { 1 0 } ] [ [ { [ ] } dispatch ] infer short-effect ] unit-test
DEFER: inline-recursive-2
: inline-recursive-1 ( -- ) inline-recursive-2 ;
: inline-recursive-2 ( -- ) inline-recursive-1 ;
[ { 0 0 } ] [ [ inline-recursive-1 ] infer short-effect ] unit-test
! Hooks
SYMBOL: my-var
HOOK: my-hook my-var ( -- x )
M: integer my-hook "an integer" ;
M: string my-hook "a string" ;
[ { 0 1 } ] [ [ my-hook ] infer short-effect ] unit-test
DEFER: deferred-word
: calls-deferred-word [ deferred-word ] [ 3 ] if ;
[ { 1 1 } ] [ [ calls-deferred-word ] infer short-effect ] unit-test
USE: inference.dataflow
[ { 1 0 } ] [ [ [ iterate-next ] iterate-nodes ] infer short-effect ] unit-test
[ { 1 0 } ] [
[
[ [ iterate-next ] iterate-nodes ] with-node-iterator
] infer short-effect
] unit-test
: nilpotent ( quot -- )
t [ [ call ] keep nilpotent ] [ drop ] if ; inline
: semisimple ( quot -- )
[ call ] keep [ [ semisimple ] keep ] nilpotent drop ; inline
[ { 0 1 } ] [
[ [ ] [ call ] keep [ [ call ] keep ] nilpotent ]
infer short-effect
] unit-test
[ { 0 0 } ] [ [ [ ] semisimple ] infer short-effect ] unit-test
[ { 1 0 } ] [ [ [ drop ] each-node ] infer short-effect ] unit-test
DEFER: an-inline-word
: normal-word-3 ( -- )
3 [ [ 2 + ] curry ] an-inline-word call drop ;
: normal-word-2 ( -- )
normal-word-3 ;
: normal-word ( x -- x )
dup [ normal-word-2 ] when ;
: an-inline-word ( obj quot -- )
>r normal-word r> call ; inline
[ { 1 1 } ] [ [ [ 3 * ] an-inline-word ] infer short-effect ] unit-test
[ { 0 1 } ] [ [ [ 2 ] [ 2 ] [ + ] compose compose call ] infer short-effect ] unit-test
TUPLE: custom-error ;
[ T{ effect f 0 0 t } ] [
[ custom-error construct-boa throw ] infer
] unit-test
: funny-throw throw ; inline
[ T{ effect f 0 0 t } ] [
[ 3 funny-throw ] infer
] unit-test
[ T{ effect f 0 0 t } ] [
[ custom-error inference-error ] infer
] unit-test
[ T{ effect f 1 1 t } ] [
[ dup >r 3 throw r> ] infer
] unit-test
! This was a false trigger of the undecidable quotation
! recursion bug
[ { 2 1 } ] [ [ find-last-sep ] infer short-effect ] unit-test