factor/library/inference/dataflow.factor

231 lines
5.9 KiB
Factor
Raw Normal View History

2005-05-15 21:17:56 -04:00
! Copyright (C) 2004, 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
2004-12-02 22:44:36 -05:00
IN: inference
2005-09-17 04:15:05 -04:00
USING: arrays generic hashtables interpreter kernel lists math
namespaces parser sequences words ;
2005-05-15 21:17:56 -04:00
2005-08-07 00:00:57 -04:00
! Recursive state. An alist, mapping words to labels.
SYMBOL: recursive-state
TUPLE: value recursion uid ;
C: value ( -- value )
gensym over set-value-uid
recursive-state get over set-value-recursion ;
M: value = eq? ;
2005-09-17 15:25:18 -04:00
M: value hashcode value-uid hashcode ;
2005-08-07 00:00:57 -04:00
TUPLE: literal value ;
C: literal ( obj -- value )
<value> over set-delegate
[ set-literal-value ] keep ;
2005-09-17 15:25:18 -04:00
M: literal hashcode delegate hashcode ;
2005-05-17 16:13:08 -04:00
! The dataflow IR is the first of the two intermediate
! representations used by Factor. It annotates concatenative
! code with stack flow information and types.
TUPLE: node param shuffle
classes literals history
successor children ;
2005-05-17 16:13:08 -04:00
M: node = eq? ;
2005-05-17 16:13:08 -04:00
: make-node ( param in-d out-d in-r out-r node -- node )
2005-09-23 01:22:04 -04:00
[ >r swapd <shuffle> f f f f f <node> r> set-delegate ] keep ;
: node-in-d node-shuffle shuffle-in-d ;
: node-in-r node-shuffle shuffle-in-r ;
: node-out-d node-shuffle shuffle-out-d ;
: node-out-r node-shuffle shuffle-out-r ;
: set-node-in-d node-shuffle set-shuffle-in-d ;
: set-node-in-r node-shuffle set-shuffle-in-r ;
: set-node-out-d node-shuffle set-shuffle-out-d ;
: set-node-out-r node-shuffle set-shuffle-out-r ;
: empty-node f { } { } { } { } ;
: param-node ( label) { } { } { } { } ;
: in-node ( inputs) >r f r> { } { } { } ;
: out-node ( outputs) >r f { } r> { } { } ;
2005-05-17 16:13:08 -04:00
: d-tail ( n -- list ) meta-d get tail* ;
: r-tail ( n -- list ) meta-r get tail* ;
2005-05-17 16:13:08 -04:00
2005-09-04 01:09:46 -04:00
: node-child node-children first ;
TUPLE: #label ;
C: #label make-node ;
2005-05-17 16:13:08 -04:00
: #label ( label -- node ) param-node <#label> ;
TUPLE: #entry ;
C: #entry make-node ;
: #entry ( -- node ) f param-node <#entry> ;
TUPLE: #call ;
C: #call make-node ;
2005-05-17 16:13:08 -04:00
: #call ( word -- node ) param-node <#call> ;
TUPLE: #call-label ;
C: #call-label make-node ;
2005-06-08 04:49:05 -04:00
: #call-label ( label -- node ) param-node <#call-label> ;
2005-05-17 16:13:08 -04:00
2005-09-04 17:07:59 -04:00
TUPLE: #shuffle ;
C: #shuffle make-node ;
: #shuffle ( -- node ) empty-node <#shuffle> ;
2005-09-17 22:25:18 -04:00
: #push ( outputs -- node ) d-tail out-node <#shuffle> ;
2005-05-17 16:13:08 -04:00
TUPLE: #values ;
C: #values make-node ;
2005-09-17 22:25:18 -04:00
: #values ( -- node ) meta-d get clone in-node <#values> ;
TUPLE: #return ;
C: #return make-node ;
2005-09-07 17:21:11 -04:00
: #return ( label -- node )
#! The parameter is the label we are returning from, or if
#! f, this is a top-level return.
2005-09-17 22:25:18 -04:00
meta-d get clone in-node <#return>
2005-09-07 17:21:11 -04:00
[ set-node-param ] keep ;
2005-05-17 16:13:08 -04:00
2005-09-24 15:21:17 -04:00
TUPLE: #if ;
C: #if make-node ;
: #if ( in -- node ) 1 d-tail in-node <#if> ;
2005-05-17 16:13:08 -04:00
TUPLE: #dispatch ;
C: #dispatch make-node ;
2005-09-17 22:25:18 -04:00
: #dispatch ( in -- node ) 1 d-tail in-node <#dispatch> ;
2005-05-17 16:13:08 -04:00
2005-07-27 01:46:06 -04:00
TUPLE: #merge ;
C: #merge make-node ;
2005-09-17 22:25:18 -04:00
: #merge ( -- node ) meta-d get clone out-node <#merge> ;
TUPLE: #terminate ;
C: #terminate make-node ;
: #terminate ( -- node ) empty-node <#terminate> ;
2005-07-27 01:46:06 -04:00
2005-05-17 16:13:08 -04:00
: node-inputs ( d-count r-count node -- )
tuck
>r r-tail r> set-node-in-r
>r d-tail r> set-node-in-d ;
: node-outputs ( d-count r-count node -- )
tuck
>r r-tail r> set-node-out-r
>r d-tail r> set-node-out-d ;
! Variable holding dataflow graph being built.
SYMBOL: dataflow-graph
2005-05-17 16:13:08 -04:00
! The most recently added node.
SYMBOL: current-node
2005-05-17 16:13:08 -04:00
: node, ( node -- )
dataflow-graph get [
dup current-node [ set-node-successor ] change
2004-12-02 22:44:36 -05:00
] [
2005-05-17 16:13:08 -04:00
! first node
dup dataflow-graph set current-node set
2005-09-24 15:21:17 -04:00
] if ;
2005-05-17 16:13:08 -04:00
: node-values ( node -- values )
[
dup node-in-d % dup node-out-d %
dup node-in-r % node-out-r %
] { } make ;
2005-05-22 02:35:38 -04:00
2005-09-17 04:15:05 -04:00
: uses-value? ( value node -- ? ) node-values memq? ;
2005-05-22 02:35:38 -04:00
2005-09-04 17:07:59 -04:00
: outputs-value? ( value node -- ? )
2dup node-out-d member? >r node-out-r member? r> or ;
2005-05-22 02:35:38 -04:00
: last-node ( node -- last )
2005-09-24 15:21:17 -04:00
dup node-successor [ last-node ] [ ] ?if ;
2005-05-22 02:35:38 -04:00
2005-08-29 21:00:39 -04:00
: penultimate-node ( node -- penultimate )
dup node-successor dup [
dup node-successor
2005-09-24 15:21:17 -04:00
[ nip penultimate-node ] [ drop ] if
2005-08-29 21:00:39 -04:00
] [
2drop f
2005-09-24 15:21:17 -04:00
] if ;
2005-08-29 21:00:39 -04:00
2005-09-04 17:07:59 -04:00
: drop-inputs ( node -- #shuffle )
2005-09-17 22:25:18 -04:00
node-in-d clone in-node <#shuffle> ;
2005-09-04 17:07:59 -04:00
: #drop ( n -- #shuffle )
2005-09-17 22:25:18 -04:00
d-tail in-node <#shuffle> ;
2005-08-29 21:00:39 -04:00
: each-node ( node quot -- | quot: node -- )
over [
[ call ] 2keep swap
[ node-children [ swap each-node ] each-with ] 2keep
node-successor swap each-node
] [
2drop
2005-09-24 15:21:17 -04:00
] if ; inline
: each-node-with ( obj node quot -- | quot: obj node -- )
swap [ with ] each-node 2drop ; inline
2005-08-07 00:00:57 -04:00
2005-08-29 21:00:39 -04:00
: all-nodes? ( node quot -- ? | quot: node -- ? )
over [
[ call ] 2keep rot [
[
swap node-children [ swap all-nodes? ] all-with?
] 2keep rot [
>r node-successor r> all-nodes?
] [
2drop f
2005-09-24 15:21:17 -04:00
] if
2005-08-29 21:00:39 -04:00
] [
2drop f
2005-09-24 15:21:17 -04:00
] if
2005-08-29 21:00:39 -04:00
] [
2drop t
2005-09-24 15:21:17 -04:00
] if ; inline
2005-08-29 21:00:39 -04:00
: all-nodes-with? ( obj node quot -- ? | quot: obj node -- ? )
swap [ with rot ] all-nodes? 2nip ; inline
2005-09-17 04:15:05 -04:00
: (subst-values) ( new old node -- )
[ node-in-d subst ] 3keep [ node-in-r subst ] 3keep
[ node-out-d subst ] 3keep node-out-r subst ;
2005-08-07 00:00:57 -04:00
: subst-values ( new old node -- )
#! Mutates the node.
2005-09-17 04:15:05 -04:00
[ >r 2dup r> (subst-values) ] each-node 2drop ;
: remember-node ( word node -- )
#! Annotate each node with the fact it was inlined from
#! 'word'.
[
2005-09-23 01:22:04 -04:00
dup #call?
[ [ node-history ?push ] keep set-node-history ]
2005-09-24 15:21:17 -04:00
[ 2drop ] if
] each-node-with ;
2005-08-13 04:01:21 -04:00
: (clone-node) ( node -- node )
clone dup node-shuffle clone over set-node-shuffle ;
2005-08-13 04:01:21 -04:00
: clone-node ( node -- node )
dup [
2005-08-13 04:01:21 -04:00
(clone-node)
dup node-children [ clone-node ] map over set-node-children
dup node-successor clone-node over set-node-successor
] when ;
2005-09-04 01:09:46 -04:00
GENERIC: calls-label* ( label node -- ? )
M: node calls-label* 2drop f ;
M: #call-label calls-label* node-param eq? ;
: calls-label? ( label node -- ? )
[ calls-label* not ] all-nodes-with? not ;
: recursive-label? ( node -- ? )
dup node-param swap calls-label? ;