factor/core/inference/inference-tests.factor

550 lines
12 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 classes.tuple classes.union
classes.predicate debugger threads.private io.streams.string
io.timeouts io.thread sequences.private ;
2008-03-01 17:00:45 -05:00
IN: inference.tests
2007-09-20 18:09:08 -04:00
2008-04-04 01:33:06 -04:00
[ ] [ [ 1 ] dataflow [ ] transform-nodes drop ] unit-test
[ ] [ [ 1 2 3 ] dataflow [ ] transform-nodes drop ] unit-test
{ 0 2 } [ 2 "Hello" ] must-infer-as
{ 1 2 } [ dup ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 1 2 } [ [ dup ] call ] must-infer-as
[ [ call ] infer ] must-fail
2007-09-20 18:09:08 -04:00
{ 2 4 } [ 2dup ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 1 0 } [ [ ] [ ] if ] must-infer-as
[ [ if ] infer ] must-fail
[ [ [ ] if ] infer ] must-fail
[ [ [ 2 ] [ ] if ] infer ] must-fail
{ 4 3 } [ [ rot ] [ -rot ] if ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 4 3 } [
2007-09-20 18:09:08 -04:00
[
[ swap 3 ] [ nip 5 5 ] if
] [
-rot
] if
] must-infer-as
2007-09-20 18:09:08 -04:00
{ 1 1 } [ dup [ ] when ] must-infer-as
{ 1 1 } [ dup [ dup fixnum* ] when ] must-infer-as
{ 2 1 } [ [ dup fixnum* ] when ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 1 0 } [ [ drop ] when* ] must-infer-as
{ 1 1 } [ [ { { [ ] } } ] unless* ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 0 1 }
[ [ 2 2 fixnum+ ] dup [ ] when call ] must-infer-as
2007-09-20 18:09:08 -04:00
[
[ [ [ 2 2 fixnum+ ] ] [ [ 2 2 fixnum* ] ] if call ] infer
] must-fail
2007-09-20 18:09:08 -04:00
! 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 ] must-infer-as
2007-09-20 18:09:08 -04:00
: infinite-loop infinite-loop ;
[ [ infinite-loop ] infer ] must-fail
2007-09-20 18:09:08 -04:00
: no-base-case-1 dup [ no-base-case-1 ] [ no-base-case-1 ] if ;
[ [ no-base-case-1 ] infer ] must-fail
2007-09-20 18:09:08 -04:00
: simple-recursion-1 ( obj -- obj )
dup [ simple-recursion-1 ] [ ] if ;
{ 1 1 } [ simple-recursion-1 ] must-infer-as
2007-09-20 18:09:08 -04:00
: simple-recursion-2 ( obj -- obj )
dup [ ] [ simple-recursion-2 ] if ;
{ 1 1 } [ simple-recursion-2 ] must-infer-as
2007-09-20 18:09:08 -04:00
: bad-recursion-2 ( obj -- obj )
dup [ dup first swap second bad-recursion-2 ] [ ] if ;
[ [ bad-recursion-2 ] infer ] must-fail
2007-09-20 18:09:08 -04:00
: funny-recursion ( obj -- obj )
dup [ funny-recursion 1 ] [ 2 ] if drop ;
{ 1 1 } [ funny-recursion ] must-infer-as
2007-09-20 18:09:08 -04:00
! Simple combinators
{ 1 2 } [ [ first ] keep second ] must-infer-as
2007-09-20 18:09:08 -04:00
! 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 ] must-infer-as
{ 2 1 } [ foe ] must-infer-as
2007-09-20 18:09:08 -04:00
: nested-when ( -- )
t [
t [
5 drop
] when
] when ;
{ 0 0 } [ nested-when ] must-infer-as
2007-09-20 18:09:08 -04:00
: nested-when* ( obj -- )
[
[
drop
] when*
] when* ;
{ 1 0 } [ nested-when* ] must-infer-as
2007-09-20 18:09:08 -04:00
SYMBOL: sym-test
{ 0 1 } [ sym-test ] must-infer-as
2007-09-20 18:09:08 -04:00
: terminator-branch
dup [
length
] [
"foo" throw
] if ;
{ 1 1 } [ terminator-branch ] must-infer-as
2007-09-20 18:09:08 -04:00
: recursive-terminator ( obj -- )
dup [
recursive-terminator
] [
"Hi" throw
] if ;
{ 1 0 } [ recursive-terminator ] must-infer-as
2007-09-20 18:09:08 -04:00
GENERIC: potential-hang ( obj -- obj )
M: fixnum potential-hang dup [ potential-hang ] when ;
[ ] [ [ 5 potential-hang ] infer drop ] unit-test
2007-09-20 18:09:08 -04:00
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 ] must-infer-as
2007-09-20 18:09:08 -04:00
! Regression
: cat ( obj -- * ) dup [ throw ] [ throw ] if ;
: dog ( a b c -- ) dup [ cat ] [ 3drop ] if ;
{ 3 0 } [ dog ] must-infer-as
2007-09-20 18:09:08 -04:00
! Regression
DEFER: monkey
: friend ( a b c -- ) dup [ friend ] [ monkey ] if ;
: monkey ( a b c -- ) dup [ 3drop ] [ friend ] if ;
{ 3 0 } [ friend ] must-infer-as
2007-09-20 18:09:08 -04:00
! Regression -- same as above but we infer the second word first
2007-09-20 18:09:08 -04:00
DEFER: blah2
: blah ( a b c -- ) dup [ blah ] [ blah2 ] if ;
: blah2 ( a b c -- ) dup [ blah ] [ 3drop ] if ;
{ 3 0 } [ blah2 ] must-infer-as
2007-09-20 18:09:08 -04:00
! 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 ] must-infer-as
2007-09-20 18:09:08 -04:00
! Regression
: bad-combinator ( obj quot -- )
over [
2drop
] [
[ swap slip ] keep swap bad-combinator
] if ; inline
[ [ [ 1 ] [ ] bad-combinator ] infer ] must-fail
2007-09-20 18:09:08 -04:00
! Regression
: bad-input#
dup string? [ 2array throw ] unless
over string? [ 2array throw ] unless ;
{ 2 2 } [ bad-input# ] must-infer-as
2007-09-20 18:09:08 -04:00
! 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 ] must-fail
2007-09-20 18:09:08 -04:00
! 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 ] must-fail
2007-09-20 18:09:08 -04:00
! Regression
: too-deep ( a b -- c )
dup [ drop ] [ 2dup too-deep too-deep * ] if ; inline
{ 2 1 } [ too-deep ] must-infer-as
2007-09-20 18:09:08 -04:00
! Error reporting is wrong
MATH: xyz
M: fixnum xyz 2array ;
M: float xyz
2008-03-29 21:36:58 -04:00
[ 3 ] bi@ swapd >r 2array swap r> 2array swap ;
2007-09-20 18:09:08 -04:00
[ [ xyz ] infer ] [ inference-error? ] must-fail-with
2007-09-20 18:09:08 -04:00
! 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 ] must-infer-as
{ 1 0 } [ B ] must-infer-as
{ 1 0 } [ C ] must-infer-as
2007-09-20 18:09:08 -04:00
! 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 ] must-infer-as
{ 2 2 } [ Y ] must-infer-as
2007-09-20 18:09:08 -04:00
! 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 ] must-fail
[ [ #1 ] infer ] must-fail
2007-09-20 18:09:08 -04:00
! 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 ] must-fail
2007-09-20 18:09:08 -04:00
[ 1234 infer ] must-fail
2007-09-20 18:09:08 -04:00
! This used to hang
[ [ [ dup call ] dup call ] infer ]
[ inference-error? ] must-fail-with
2007-09-20 18:09:08 -04:00
: m dup call ; inline
[ [ [ m ] m ] infer ] [ inference-error? ] must-fail-with
2007-09-20 18:09:08 -04:00
: m' dup curry call ; inline
[ [ [ m' ] m' ] infer ] [ inference-error? ] must-fail-with
2007-09-20 18:09:08 -04:00
: m'' [ dup curry ] ; inline
: m''' m'' call call ; inline
[ [ [ m''' ] m''' ] infer ] [ inference-error? ] must-fail-with
2007-09-20 18:09:08 -04:00
: m-if t over if ; inline
[ [ [ m-if ] m-if ] infer ] [ inference-error? ] must-fail-with
2007-09-20 18:09:08 -04:00
! This doesn't hang but it's also an example of the
! undedicable case
[ [ [ [ drop 3 ] swap call ] dup call ] infer ]
[ inference-error? ] must-fail-with
2007-09-20 18:09:08 -04:00
! This form should not have a stack effect
: bad-recursion-1 ( a -- b )
dup [ drop bad-recursion-1 5 ] [ ] if ;
[ [ bad-recursion-1 ] infer ] must-fail
2007-09-20 18:09:08 -04:00
: bad-bin ( a b -- ) 5 [ 5 bad-bin bad-bin 5 ] [ 2drop ] if ;
[ [ bad-bin ] infer ] must-fail
2007-09-20 18:09:08 -04:00
2008-02-06 16:00:10 -05:00
[ [ r> ] infer ] [ inference-error? ] must-fail-with
2007-09-20 18:09:08 -04:00
2007-10-10 01:53:55 -04:00
! Regression
2008-02-06 16:00:10 -05:00
[ [ get-slots ] infer ] [ inference-error? ] must-fail-with
2007-10-10 01:53:55 -04:00
2007-09-20 18:09:08 -04:00
! Test some curry stuff
{ 1 1 } [ 3 [ ] curry 4 [ ] curry if ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 2 1 } [ [ ] curry 4 [ ] curry if ] must-infer-as
2007-09-20 18:09:08 -04:00
[ [ 3 [ ] curry 1 2 [ ] 2curry if ] infer ] must-fail
2007-09-20 18:09:08 -04:00
! Test number protocol
\ bitor must-infer
\ bitand must-infer
\ bitxor must-infer
\ mod must-infer
\ /i must-infer
\ /f must-infer
\ /mod must-infer
\ + must-infer
\ - must-infer
\ * must-infer
\ / must-infer
\ < must-infer
\ <= must-infer
\ > must-infer
\ >= must-infer
\ number= must-infer
2007-09-20 18:09:08 -04:00
! Test object protocol
\ = must-infer
\ clone must-infer
\ hashcode* must-infer
2007-09-20 18:09:08 -04:00
! Test sequence protocol
\ length must-infer
\ nth must-infer
\ set-length must-infer
\ set-nth must-infer
\ new must-infer
\ new-resizable must-infer
\ like must-infer
\ lengthen must-infer
2007-09-20 18:09:08 -04:00
! Test assoc protocol
\ at* must-infer
\ set-at must-infer
\ new-assoc must-infer
\ delete-at must-infer
\ clear-assoc must-infer
\ assoc-size must-infer
\ assoc-like must-infer
\ assoc-clone-like must-infer
\ >alist must-infer
{ 1 3 } [ [ 2drop f ] assoc-find ] must-infer-as
2007-09-20 18:09:08 -04:00
! Test some random library words
\ 1quotation must-infer
\ string>number must-infer
\ get must-infer
2007-09-20 18:09:08 -04:00
\ push must-infer
\ append must-infer
\ peek must-infer
2007-09-20 18:09:08 -04:00
\ reverse must-infer
\ member? must-infer
\ remove must-infer
\ natural-sort must-infer
2007-09-20 18:09:08 -04:00
\ forget must-infer
\ define-class must-infer
\ define-tuple-class must-infer
\ define-union-class must-infer
\ define-predicate-class must-infer
2007-09-20 18:09:08 -04:00
! Test words with continuations
{ 0 0 } [ [ drop ] callcc0 ] must-infer-as
{ 0 1 } [ [ 4 swap continue-with ] callcc1 ] must-infer-as
{ 2 1 } [ [ + ] [ ] [ ] cleanup ] must-infer-as
{ 2 1 } [ [ + ] [ 3drop 0 ] recover ] must-infer-as
2007-09-20 18:09:08 -04:00
\ dispose must-infer
2007-09-20 18:09:08 -04:00
! Test stream protocol
\ set-timeout must-infer
\ stream-read must-infer
\ stream-read1 must-infer
\ stream-readln must-infer
\ stream-read-until must-infer
\ stream-write must-infer
\ stream-write1 must-infer
\ stream-nl must-infer
\ stream-format must-infer
\ stream-write-table must-infer
\ stream-flush must-infer
\ make-span-stream must-infer
\ make-block-stream must-infer
\ make-cell-stream must-infer
2007-09-20 18:09:08 -04:00
! Test stream utilities
\ lines must-infer
\ contents must-infer
2007-09-20 18:09:08 -04:00
! Test prettyprinting
\ . must-infer
\ short. must-infer
\ unparse must-infer
2007-09-20 18:09:08 -04:00
\ describe must-infer
\ error. must-infer
2007-09-20 18:09:08 -04:00
! Test odds and ends
2008-02-21 03:08:08 -05:00
\ io-thread must-infer
2007-09-20 18:09:08 -04:00
! Incorrect stack declarations on inline recursive words should
! be caught
: fooxxx ( a b -- c ) over [ foo ] when ; inline
: barxxx fooxxx ;
[ [ barxxx ] infer ] must-fail
2007-09-20 18:09:08 -04:00
! A typo
{ 1 0 } [ { [ ] } dispatch ] must-infer-as
2007-09-20 18:09:08 -04:00
DEFER: inline-recursive-2
: inline-recursive-1 ( -- ) inline-recursive-2 ;
: inline-recursive-2 ( -- ) inline-recursive-1 ;
{ 0 0 } [ inline-recursive-1 ] must-infer-as
2007-09-20 18:09:08 -04:00
! 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 ] must-infer-as
2007-09-20 18:09:08 -04:00
DEFER: deferred-word
: calls-deferred-word [ deferred-word ] [ 3 ] if ;
{ 1 1 } [ calls-deferred-word ] must-infer-as
2007-09-20 18:09:08 -04:00
USE: inference.dataflow
{ 1 0 } [ [ iterate-next ] iterate-nodes ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 1 0 }
[
[ [ iterate-next ] iterate-nodes ] with-node-iterator
] must-infer-as
2007-09-20 18:09:08 -04:00
: 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 ]
must-infer-as
2007-09-20 18:09:08 -04:00
{ 0 0 } [ [ ] semisimple ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 1 0 } [ [ drop ] each-node ] must-infer-as
2007-09-20 18:09:08 -04:00
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 ] must-infer-as
2007-09-20 18:09:08 -04:00
{ 0 1 } [ [ 2 ] [ 2 ] [ + ] compose compose call ] must-infer-as
2007-09-20 18:09:08 -04:00
2008-03-20 16:00:49 -04:00
ERROR: custom-error ;
2007-09-20 18:09:08 -04:00
[ T{ effect f 0 0 t } ] [
2008-03-20 16:00:49 -04:00
[ custom-error ] infer
2007-09-20 18:09:08 -04:00
] 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 ] must-infer-as
2008-02-10 02:34:26 -05:00
! Regression
: missing->r-check >r ;
[ [ missing->r-check ] infer ] must-fail
2008-04-04 01:33:06 -04:00
{ 1 0 } [ [ ] map-children ] must-infer-as