factor/basis/compiler/tree/propagation/info/info.factor

279 lines
7.7 KiB
Factor
Raw Normal View History

2008-07-22 05:45:03 -04:00
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
2008-07-25 03:07:45 -04:00
USING: assocs classes classes.algebra kernel
accessors math math.intervals namespaces sequences words
combinators combinators.short-circuit arrays
2008-08-07 07:34:28 -04:00
compiler.tree.propagation.copy ;
2008-07-22 05:45:03 -04:00
IN: compiler.tree.propagation.info
: false-class? ( class -- ? ) \ f class<= ;
: true-class? ( class -- ? ) \ f class-not class<= ;
: null-class? ( class -- ? ) null class<= ;
2008-07-22 05:45:03 -04:00
SYMBOL: +interval+
GENERIC: eql? ( obj1 obj2 -- ? )
M: object eql? eq? ;
M: fixnum eql? eq? ;
M: bignum eql? over bignum? [ = ] [ 2drop f ] if ;
M: ratio eql? over ratio? [ = ] [ 2drop f ] if ;
M: float eql? over float? [ [ double>bits ] bi@ = ] [ 2drop f ] if ;
M: complex eql? over complex? [ = ] [ 2drop f ] if ;
2008-07-22 05:45:03 -04:00
! Value info represents a set of objects. Don't mutate value infos
! you receive, always construct new ones. We don't declare the
2008-07-25 03:07:45 -04:00
! slots read-only to allow cloning followed by writing, and to
! simplify constructors.
2008-07-22 05:45:03 -04:00
TUPLE: value-info
2008-07-25 03:07:45 -04:00
class
interval
2008-07-22 05:45:03 -04:00
literal
2008-07-24 18:34:08 -04:00
literal?
2008-07-25 03:07:45 -04:00
length
slots ;
2008-07-22 05:45:03 -04:00
2008-07-27 03:32:40 -04:00
: null-info T{ value-info f null empty-interval } ; inline
: object-info T{ value-info f object T{ interval f { -1.0/0.0 t } { 1.0/0.0 t } } } ; inline
2008-07-22 05:45:03 -04:00
: class-interval ( class -- interval )
dup real class<=
[ +interval+ word-prop [-inf,inf] or ] [ drop f ] if ;
: interval>literal ( class interval -- literal literal? )
#! If interval has zero length and the class is sufficiently
#! precise, we can turn it into a literal
dup empty-interval eq? [
2drop f f
] [
dup from>> first {
{ [ over interval-length 0 > ] [ 3drop f f ] }
{ [ pick bignum class<= ] [ 2nip >bignum t ] }
{ [ pick integer class<= ] [ 2nip >fixnum t ] }
{ [ pick float class<= ] [
2nip dup zero? [ drop f f ] [ >float t ] if
] }
[ 3drop f f ]
} cond
] if ;
2008-07-22 05:45:03 -04:00
2008-07-24 18:34:08 -04:00
: <value-info> ( -- info ) \ value-info new ;
: init-value-info ( info -- info )
dup literal?>> [
dup literal>> class >>class
dup literal>> dup real? [ [a,a] ] [ drop [-inf,inf] ] if >>interval
2008-07-22 05:45:03 -04:00
] [
dup [ class>> null-class? ] [ interval>> empty-interval eq? ] bi or [
2008-07-24 18:34:08 -04:00
null >>class
empty-interval >>interval
] [
2008-07-25 03:07:45 -04:00
[ [-inf,inf] or ] change-interval
2008-07-24 18:34:08 -04:00
dup class>> integer class<= [ [ integral-closure ] change-interval ] when
dup [ class>> ] [ interval>> ] bi interval>literal
[ >>literal ] [ >>literal? ] bi*
2008-07-22 05:45:03 -04:00
] if
2008-07-24 18:34:08 -04:00
] if ;
2008-07-22 05:45:03 -04:00
: <class/interval-info> ( class interval -- info )
2008-07-24 18:34:08 -04:00
<value-info>
swap >>interval
swap >>class
init-value-info ; foldable
2008-07-22 05:45:03 -04:00
: <class-info> ( class -- info )
dup word? [ dup +interval+ word-prop ] [ f ] if [-inf,inf] or
<class/interval-info> ; foldable
2008-07-22 05:45:03 -04:00
: <interval-info> ( interval -- info )
2008-07-24 18:34:08 -04:00
<value-info>
real >>class
swap >>interval
init-value-info ; foldable
2008-07-22 05:45:03 -04:00
: <literal-info> ( literal -- info )
2008-07-24 18:34:08 -04:00
<value-info>
swap >>literal
t >>literal?
init-value-info ; foldable
: <sequence-info> ( value -- info )
<value-info>
object >>class
swap value-info >>length
init-value-info ; foldable
2008-07-22 05:45:03 -04:00
2008-07-25 03:07:45 -04:00
: <tuple-info> ( slots class -- info )
<value-info>
swap >>class
swap >>slots
init-value-info ;
2008-07-24 18:34:08 -04:00
: >literal< ( info -- literal literal? )
[ literal>> ] [ literal?>> ] bi ;
2008-07-22 05:45:03 -04:00
: intersect-literals ( info1 info2 -- literal literal? )
{
{ [ dup literal?>> not ] [ drop >literal< ] }
{ [ over literal?>> not ] [ nip >literal< ] }
{ [ 2dup [ literal>> ] bi@ eql? not ] [ 2drop f f ] }
[ drop >literal< ]
} cond ;
2008-07-24 18:34:08 -04:00
DEFER: value-info-intersect
DEFER: (value-info-intersect)
2008-07-24 18:34:08 -04:00
: intersect-lengths ( info1 info2 -- length )
[ length>> ] bi@ {
{ [ dup not ] [ drop ] }
{ [ over not ] [ nip ] }
[ value-info-intersect ]
} cond ;
: intersect-slot ( info1 info2 -- info )
{
{ [ dup not ] [ nip ] }
{ [ over not ] [ drop ] }
[ (value-info-intersect) ]
} cond ;
2008-07-25 03:07:45 -04:00
: intersect-slots ( info1 info2 -- slots )
[ slots>> ] bi@ {
{ [ dup not ] [ drop ] }
{ [ over not ] [ nip ] }
[
2dup [ length ] bi@ =
[ [ intersect-slot ] 2map ] [ 2drop f ] if
]
} cond ;
2008-07-25 03:07:45 -04:00
2008-07-24 01:14:13 -04:00
: (value-info-intersect) ( info1 info2 -- info )
2008-07-24 18:34:08 -04:00
[ <value-info> ] 2dip
{
[ [ class>> ] bi@ class-and >>class ]
[ [ interval>> ] bi@ interval-intersect >>interval ]
[ intersect-literals [ >>literal ] [ >>literal? ] bi* ]
[ intersect-lengths >>length ]
2008-07-25 03:07:45 -04:00
[ intersect-slots >>slots ]
2008-07-24 18:34:08 -04:00
} 2cleave
init-value-info ;
2008-07-22 05:45:03 -04:00
2008-07-24 01:14:13 -04:00
: value-info-intersect ( info1 info2 -- info )
{
{ [ dup class>> null-class? ] [ nip ] }
{ [ over class>> null-class? ] [ drop ] }
2008-07-24 01:14:13 -04:00
[ (value-info-intersect) ]
} cond ;
2008-07-22 05:45:03 -04:00
: union-literals ( info1 info2 -- literal literal? )
2dup [ literal?>> ] both? [
[ literal>> ] bi@ 2dup eql? [ drop t ] [ 2drop f f ] if
] [ 2drop f f ] if ;
2008-07-24 18:34:08 -04:00
DEFER: value-info-union
DEFER: (value-info-union)
2008-07-24 18:34:08 -04:00
: union-lengths ( info1 info2 -- length )
[ length>> ] bi@ {
{ [ dup not ] [ nip ] }
{ [ over not ] [ drop ] }
[ value-info-union ]
} cond ;
: union-slot ( info1 info2 -- info )
{
{ [ dup not ] [ nip ] }
{ [ over not ] [ drop ] }
[ (value-info-union) ]
} cond ;
2008-07-25 03:07:45 -04:00
: union-slots ( info1 info2 -- slots )
[ slots>> ] bi@
2dup [ length ] bi@ =
[ [ union-slot ] 2map ] [ 2drop f ] if ;
2008-07-25 03:07:45 -04:00
2008-07-24 01:14:13 -04:00
: (value-info-union) ( info1 info2 -- info )
2008-07-24 18:34:08 -04:00
[ <value-info> ] 2dip
{
[ [ class>> ] bi@ class-or >>class ]
[ [ interval>> ] bi@ interval-union >>interval ]
[ union-literals [ >>literal ] [ >>literal? ] bi* ]
[ union-lengths >>length ]
2008-07-25 03:07:45 -04:00
[ union-slots >>slots ]
2008-07-24 18:34:08 -04:00
} 2cleave
init-value-info ;
2008-07-22 05:45:03 -04:00
2008-07-24 01:14:13 -04:00
: value-info-union ( info1 info2 -- info )
{
{ [ dup class>> null-class? ] [ drop ] }
{ [ over class>> null-class? ] [ nip ] }
2008-07-24 01:14:13 -04:00
[ (value-info-union) ]
} cond ;
2008-07-22 05:45:03 -04:00
: value-infos-union ( infos -- info )
dup empty?
2008-07-27 03:32:40 -04:00
[ drop null-info ]
[ dup first [ value-info-union ] reduce ] if ;
2008-07-22 05:45:03 -04:00
: literals<= ( info1 info2 -- ? )
{
{ [ dup literal?>> not ] [ 2drop t ] }
{ [ over literal?>> not ] [ 2drop f ] }
[ [ literal>> ] bi@ eql? ]
} cond ;
: value-info<= ( info1 info2 -- ? )
{
{ [ dup not ] [ 2drop t ] }
{ [ over not ] [ 2drop f ] }
[
{
[ [ class>> ] bi@ class<= ]
[ [ interval>> ] bi@ interval-subset? ]
[ literals<= ]
[ [ length>> ] bi@ value-info<= ]
[ [ slots>> ] bi@ [ value-info<= ] 2all? ]
} 2&&
]
} cond ;
2008-07-22 05:45:03 -04:00
! Current value --> info mapping
SYMBOL: value-infos
: value-info ( value -- info )
2008-07-27 03:32:40 -04:00
resolve-copy value-infos get at null-info or ;
2008-07-22 05:45:03 -04:00
: set-value-info ( info value -- )
resolve-copy value-infos get set-at ;
: refine-value-info ( info value -- )
resolve-copy value-infos get [ value-info-intersect ] change-at ;
: value-literal ( value -- obj ? )
value-info >literal< ;
: possible-boolean-values ( info -- values )
dup literal?>> [
literal>> 1array
] [
class>> {
{ [ dup null-class? ] [ { } ] }
{ [ dup true-class? ] [ { t } ] }
{ [ dup false-class? ] [ { f } ] }
[ { t f } ]
} cond nip
] if ;
2008-07-24 18:34:08 -04:00
2008-07-27 03:32:40 -04:00
: node-value-info ( node value -- info )
swap info>> at* [ drop null-info ] unless ;
: node-input-infos ( node -- seq )
dup in-d>> [ node-value-info ] with map ;
: node-output-infos ( node -- seq )
dup out-d>> [ node-value-info ] with map ;