Change high-level IR to not use 'successor' links; add normalization pass

db4
Slava Pestov 2008-07-27 20:25:42 -05:00
parent 10322c11e3
commit 74197538f5
24 changed files with 280 additions and 210 deletions

View File

@ -0,0 +1,5 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler.tree.branch-fusion
: fuse-branches ( nodes -- nodes' ) ;

View File

@ -7,11 +7,11 @@ stack-checker.state stack-checker.visitor stack-checker.errors
stack-checker.backend compiler.tree ; stack-checker.backend compiler.tree ;
IN: compiler.tree.builder IN: compiler.tree.builder
: with-tree-builder ( quot -- dataflow ) : with-tree-builder ( quot -- nodes )
[ node-list new stack-visitor set ] prepose [ V{ } clone stack-visitor set ] prepose
with-infer first>> ; inline with-infer ; inline
GENERIC# build-tree-with 1 ( quot stack -- dataflow ) GENERIC# build-tree-with 1 ( quot stack -- nodes )
M: callable build-tree-with M: callable build-tree-with
#! Not safe to call from inference transforms. #! Not safe to call from inference transforms.
@ -20,7 +20,7 @@ M: callable build-tree-with
f infer-quot f infer-quot
] with-tree-builder nip ; ] with-tree-builder nip ;
: build-tree ( quot -- dataflow ) f build-tree-with ; : build-tree ( quot -- nodes ) f build-tree-with ;
: (make-specializer) ( class picker -- quot ) : (make-specializer) ( class picker -- quot )
swap "predicate" word-prop append ; swap "predicate" word-prop append ;
@ -65,7 +65,7 @@ M: callable build-tree-with
[ drop ] [ drop ]
} cond ; } cond ;
: build-tree-from-word ( word -- effect dataflow ) : build-tree-from-word ( word -- effect nodes )
[ [
[ [
dup +cannot-infer+ word-prop [ cannot-infer-effect ] when dup +cannot-infer+ word-prop [ cannot-infer-effect ] when

View File

@ -0,0 +1,5 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler.tree.cleanup
: cleanup ( nodes -- nodes' ) ;

View File

@ -1,17 +1,4 @@
IN: compiler.tree.combinators.tests IN: compiler.tree.combinators.tests
USING: compiler.tree.combinators compiler.tree.builder tools.test USING: compiler.tree.combinators tools.test kernel ;
kernel ;
[ ] [ [ 1 ] build-tree [ ] transform-nodes drop ] unit-test
[ ] [ [ 1 2 3 ] build-tree [ ] transform-nodes drop ] unit-test
{ 1 0 } [ [ iterate-next ] iterate-nodes ] must-infer-as
{ 1 0 }
[
[ [ iterate-next ] iterate-nodes ] with-node-iterator
] must-infer-as
{ 1 0 } [ [ drop ] each-node ] must-infer-as { 1 0 } [ [ drop ] each-node ] must-infer-as
{ 1 0 } [ [ ] map-children ] must-infer-as

View File

@ -1,64 +1,17 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: fry arrays generic assocs kernel math namespaces parser USING: fry kernel accessors sequences compiler.tree ;
sequences words vectors math.intervals effects classes
accessors combinators compiler.tree ;
IN: compiler.tree.combinators IN: compiler.tree.combinators
SYMBOL: node-stack : each-node ( nodes quot -- )
dup dup '[
: >node ( node -- ) node-stack get push ; , [
: node> ( -- node ) node-stack get pop ; dup #branch? [
: node@ ( -- node ) node-stack get peek ; children>> [ , each-node ] each
] [
: iterate-next ( -- node ) node@ successor>> ; dup #recursive? [
child>> , each-node
: iterate-nodes ( node quot -- ) ] [ drop ] if
over [ ] if
[ swap >node call node> drop ] keep iterate-nodes ] bi
] [ ] each ; inline
2drop
] if ; inline
: (each-node) ( quot -- next )
node@ [ swap call ] 2keep
children>> [
first>> [
[ (each-node) ] keep swap
] iterate-nodes
] each drop
iterate-next ; inline
: with-node-iterator ( quot -- )
>r V{ } clone node-stack r> with-variable ; inline
: each-node ( node quot -- )
[
swap [
[ (each-node) ] keep swap
] iterate-nodes drop
] with-node-iterator ; inline
: map-children ( node quot -- )
[ children>> ] dip '[ , change-first drop ] each ; inline
: (transform-nodes) ( prev node quot -- )
dup >r call dup [
>>successor
successor>> dup successor>>
r> (transform-nodes)
] [
r> 2drop f >>successor drop
] if ; inline
: transform-nodes ( node quot -- new-node )
over [
[ call dup dup successor>> ] keep (transform-nodes)
] [ drop ] if ; inline
: tail-call? ( -- ? )
#! We don't consider calls which do non-local exits to be
#! tail calls, because this gives better error traces.
node-stack get [
successor>> [ #tail? ] [ #terminate? not ] bi and
] all? ;

View File

@ -1,8 +1,8 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: compiler.tree.dfa.backward IN: compiler.tree.dataflow-analysis.backward
USING: accessors sequences assocs kernel compiler.tree USING: accessors sequences assocs kernel compiler.tree
compiler.tree.dfa ; compiler.tree.dataflow-analysis ;
GENERIC: backward ( value node -- ) GENERIC: backward ( value node -- )

View File

@ -3,7 +3,7 @@
USING: fry accessors namespaces assocs dequeues search-dequeues USING: fry accessors namespaces assocs dequeues search-dequeues
kernel sequences words sets stack-checker.inlining compiler.tree kernel sequences words sets stack-checker.inlining compiler.tree
compiler.tree.def-use compiler.tree.combinators ; compiler.tree.def-use compiler.tree.combinators ;
IN: compiler.tree.dfa IN: compiler.tree.dataflow-analysis
! Dataflow analysis ! Dataflow analysis
SYMBOL: work-list SYMBOL: work-list

View File

@ -3,8 +3,8 @@
USING: fry accessors namespaces assocs dequeues search-dequeues USING: fry accessors namespaces assocs dequeues search-dequeues
kernel sequences words sets stack-checker.inlining kernel sequences words sets stack-checker.inlining
compiler.tree compiler.tree
compiler.tree.dfa compiler.tree.dataflow-analysis
compiler.tree.dfa.backward compiler.tree.dataflow-analysis.backward
compiler.tree.combinators ; compiler.tree.combinators ;
IN: compiler.tree.dead-code IN: compiler.tree.dead-code

View File

@ -1,7 +1,7 @@
! Copyright (C) 2004, 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces assocs sequences kernel generic assocs classes USING: arrays namespaces assocs sequences kernel generic assocs
vectors accessors combinators sets stack-checker.state classes vectors accessors combinators sets stack-checker.state
compiler.tree compiler.tree.combinators ; compiler.tree compiler.tree.combinators ;
IN: compiler.tree.def-use IN: compiler.tree.def-use
@ -9,60 +9,60 @@ SYMBOL: def-use
TUPLE: definition value node uses ; TUPLE: definition value node uses ;
: <definition> ( value -- definition ) : <definition> ( node value -- definition )
definition new definition new
swap >>value swap >>value
swap >>node
V{ } clone >>uses ; V{ } clone >>uses ;
: def-of ( value -- definition ) : def-of ( value -- definition )
def-use get [ <definition> ] cache ; def-use get at* [ "No def" throw ] unless ;
: def-value ( node value -- ) : def-value ( node value -- )
def-of [ [ "Multiple defs" throw ] when ] change-node drop ; def-use get 2dup key? [
"Multiple defs" throw
] [
[ [ <definition> ] keep ] dip set-at
] if ;
: used-by ( value -- nodes ) def-of uses>> ; : used-by ( value -- nodes ) def-of uses>> ;
: use-value ( node value -- ) used-by push ; : use-value ( node value -- ) used-by push ;
: defined-by ( value -- node ) def-use get at node>> ; : defined-by ( value -- node ) def-of node>> ;
GENERIC: node-uses-values ( node -- values ) GENERIC: node-uses-values ( node -- values )
M: #declare node-uses-values declaration>> keys ; M: #introduce node-uses-values drop f ;
M: #push node-uses-values drop f ;
M: #phi node-uses-values
[ phi-in-d>> concat ] [ phi-in-r>> concat ] bi
append sift prune ;
M: #r> node-uses-values in-r>> ; M: #r> node-uses-values in-r>> ;
M: #phi node-uses-values
[ phi-in-d>> ] [ phi-in-r>> ] bi append concat sift prune ;
M: #declare node-uses-values declaration>> keys ;
M: node node-uses-values in-d>> ; M: node node-uses-values in-d>> ;
GENERIC: node-defs-values ( node -- values ) GENERIC: node-defs-values ( node -- values )
M: #introduce node-defs-values values>> ; M: #introduce node-defs-values value>> 1array ;
M: #>r node-defs-values out-r>> ; M: #>r node-defs-values out-r>> ;
M: #branch node-defs-values drop f ;
M: #phi node-defs-values [ out-d>> ] [ out-r>> ] bi append ; M: #phi node-defs-values [ out-d>> ] [ out-r>> ] bi append ;
M: #declare node-defs-values drop f ;
M: #return node-defs-values drop f ;
M: #recursive node-defs-values drop f ;
M: #terminate node-defs-values drop f ;
M: node node-defs-values out-d>> ; M: node node-defs-values out-d>> ;
: node-def-use ( node -- ) : node-def-use ( node -- )
[ dup node-uses-values [ use-value ] with each ] [ dup node-uses-values [ use-value ] with each ]
[ dup node-defs-values [ def-value ] with each ] bi ; [ dup node-defs-values [ def-value ] with each ] bi ;
: check-def ( node -- )
[ "No def" throw ] unless ;
: check-use ( uses -- ) : check-use ( uses -- )
[ empty? [ "No use" throw ] when ] [ empty? [ "No use" throw ] when ]
[ all-unique? [ "Uses not all unique" throw ] unless ] bi ; [ all-unique? [ "Uses not all unique" throw ] unless ] bi ;
: check-def-use ( -- ) : check-def-use ( -- )
def-use get [ def-use get [ nip uses>> check-use ] assoc-each ;
nip [ node>> check-def ] [ uses>> check-use ] bi
] assoc-each ;
: compute-def-use ( node -- node ) : compute-def-use ( node -- node )
H{ } clone def-use set H{ } clone def-use set

View File

@ -0,0 +1,5 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler.tree.loop-detection
: detect-loops ( nodes -- nodes' ) ;

View File

@ -0,0 +1,27 @@
IN: compiler.tree.normalization.tests
USING: compiler.tree.builder compiler.tree.normalization
compiler.tree sequences accessors tools.test kernel ;
\ collect-introductions must-infer
\ fixup-enter-recursive must-infer
\ eliminate-introductions must-infer
\ normalize must-infer
[ 3 ] [ [ 3drop 1 2 3 ] build-tree collect-introductions ] unit-test
[ 4 ] [ [ 3drop 1 2 3 3drop drop ] build-tree collect-introductions ] unit-test
[ 3 ] [ [ [ drop ] [ 2drop 3 ] if ] build-tree collect-introductions ] unit-test
[ 2 ] [ [ 3 [ drop ] [ 2drop 3 ] if ] build-tree collect-introductions ] unit-test
: foo ( -- ) swap ; inline recursive
: recursive-inputs ( nodes -- n )
[ #recursive? ] find nip child>> first in-d>> length ;
[ 0 2 ] [
[ foo ] build-tree
[ recursive-inputs ]
[ normalize recursive-inputs ] bi
] unit-test

View File

@ -0,0 +1,94 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: namespaces sequences math accessors kernel arrays
stack-checker.backend compiler.tree compiler.tree.combinators ;
IN: compiler.tree.normalization
! A transform pass done before optimization can begin to
! fix up some oddities in the tree output by the stack checker:
!
! - We rewrite the code is that #introduce nodes only appear
! at the top level, and not inside #recursive. This enables more
! accurate type inference for 'row polymorphic' combinators.
!
! - We collect #return-recursive and #call-recursive nodes and
! store them in the #recursive's label slot.
GENERIC: normalize* ( node -- )
! Collect introductions
SYMBOL: introductions
GENERIC: collect-introductions* ( node -- )
: collect-introductions ( nodes -- n )
[
0 introductions set
[ collect-introductions* ] each
introductions get
] with-scope ;
M: #introduce collect-introductions* drop introductions inc ;
M: #branch collect-introductions*
children>>
[ collect-introductions ] map supremum
introductions [ + ] change ;
M: node collect-introductions* drop ;
! Eliminate introductions
SYMBOL: introduction-stack
: fixup-enter-recursive ( recursive -- )
[ child>> first ] [ in-d>> ] bi >>in-d
[ introduction-stack get prepend ] change-out-d
drop ;
GENERIC: eliminate-introductions* ( node -- node' )
: pop-introduction ( -- value )
introduction-stack [ unclip-last swap ] change ;
M: #introduce eliminate-introductions*
pop-introduction swap value>> [ 1array ] bi@ #copy ;
SYMBOL: remaining-introductions
M: #branch eliminate-introductions*
dup children>> [
[
[ eliminate-introductions* ] change-each
introduction-stack get
] with-scope
] map
[ remaining-introductions set ]
[ [ length ] map infimum introduction-stack [ swap head ] change ]
bi ;
M: #phi eliminate-introductions*
remaining-introductions get swap
[ flip [ over length tail append ] 2map flip ] change-phi-in-d ;
M: node eliminate-introductions* ;
: eliminate-introductions ( recursive n -- )
make-values introduction-stack set
[ fixup-enter-recursive ]
[ child>> [ eliminate-introductions* ] change-each ] bi ;
M: #recursive normalize*
[
[ child>> collect-introductions ]
[ swap eliminate-introductions ]
bi
] with-scope ;
! Collect label info
M: #return-recursive normalize* dup label>> (>>return) ;
M: #call-recursive normalize* dup label>> calls>> push ;
M: node normalize* drop ;
: normalize ( node -- node ) dup [ normalize* ] each-node ;

View File

@ -0,0 +1,21 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: compiler.tree.normalization compiler.tree.copy-equiv
compiler.tree.propagation compiler.tree.cleanup
compiler.tree.def-use compiler.tree.untupling
compiler.tree.dead-code compiler.tree.strength-reduction
compiler.tree.loop-detection compiler.tree.branch-fusion ;
IN: compiler.tree.optimizer
: optimize-tree ( nodes -- nodes' )
normalize
compute-copy-equiv
propagate
cleanup
compute-def-use
unbox-tuples
compute-def-use
remove-dead-code
strength-reduce
detect-loops
fuse-branches ;

View File

@ -31,21 +31,23 @@ M: #dispatch live-children
[ children>> ] [ in-d>> first value-info interval>> ] bi [ children>> ] [ in-d>> first value-info interval>> ] bi
'[ , interval-contains? [ drop f ] unless ] map-index ; '[ , interval-contains? [ drop f ] unless ] map-index ;
: infer-children ( node -- assocs ) SYMBOL: infer-children-data
: infer-children ( node -- )
[ live-children ] [ child-constraints ] bi [ [ live-children ] [ child-constraints ] bi [
[ [
over [ over [
value-infos [ clone ] change value-infos [ clone ] change
constraints [ clone ] change constraints [ clone ] change
assume assume
first>> (propagate) (propagate)
] [ ] [
2drop 2drop
value-infos off value-infos off
constraints off constraints off
] if ] if
] H{ } make-assoc ] H{ } make-assoc
] 2map ; ] 2map infer-children-data set ;
: (merge-value-infos) ( inputs results -- infos ) : (merge-value-infos) ( inputs results -- infos )
'[ , [ [ value-info ] bind ] 2map value-infos-union ] map ; '[ , [ [ value-info ] bind ] 2map value-infos-union ] map ;
@ -53,7 +55,8 @@ M: #dispatch live-children
: merge-value-infos ( results inputs outputs -- ) : merge-value-infos ( results inputs outputs -- )
[ swap (merge-value-infos) ] dip set-value-infos ; [ swap (merge-value-infos) ] dip set-value-infos ;
: propagate-branch-phi ( results #phi -- ) M: #phi propagate-before ( #phi -- )
infer-children-data get swap
[ [ phi-in-d>> ] [ out-d>> ] bi merge-value-infos ] [ [ phi-in-d>> ] [ out-d>> ] bi merge-value-infos ]
[ [ phi-in-r>> ] [ out-r>> ] bi merge-value-infos ] [ [ phi-in-r>> ] [ out-r>> ] bi merge-value-infos ]
2bi ; 2bi ;
@ -67,10 +70,10 @@ M: #dispatch live-children
] [ 3drop ] if ] [ 3drop ] if
] 2each ; ] 2each ;
: merge-children ( results node -- ) ! : merge-children
[ successor>> propagate-branch-phi ] ! [ successor>> propagate-branch-phi ]
[ [ in-d>> first ] [ successor>> ] bi 2drop ] ! branch-phi-constraints ] ! [ [ in-d>> first ] [ successor>> ] bi 2drop ] ! branch-phi-constraints ]
bi ; ! bi ;
M: #branch propagate-around M: #branch propagate-around
[ infer-children ] [ merge-children ] [ annotate-node ] tri ; [ infer-children ] [ annotate-node ] bi ;

View File

@ -0,0 +1,3 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler.tree.propagation.inlining

View File

@ -14,9 +14,4 @@ GENERIC: propagate-after ( node -- )
GENERIC: propagate-around ( node -- ) GENERIC: propagate-around ( node -- )
: (propagate) ( node -- ) : (propagate) ( node -- ) [ [ propagate-around ] each ] when* ;
[
USING: classes prettyprint ; dup class .
[ propagate-around ] [ successor>> ] bi
(propagate)
] when* ;

View File

@ -1,6 +1,6 @@
USING: kernel compiler.tree.builder compiler.tree USING: kernel compiler.tree.builder compiler.tree
compiler.tree.propagation compiler.tree.copy-equiv compiler.tree.propagation compiler.tree.copy-equiv
compiler.tree.def-use tools.test math math.order compiler.tree.normalization tools.test math math.order
accessors sequences arrays kernel.private vectors accessors sequences arrays kernel.private vectors
alien.accessors alien.c-types sequences.private alien.accessors alien.c-types sequences.private
byte-arrays classes.algebra classes.tuple.private byte-arrays classes.algebra classes.tuple.private
@ -13,10 +13,10 @@ IN: compiler.tree.propagation.tests
: final-info ( quot -- seq ) : final-info ( quot -- seq )
build-tree build-tree
compute-def-use normalize
compute-copy-equiv compute-copy-equiv
propagate propagate
last-node node-input-infos ; peek node-input-infos ;
: final-classes ( quot -- seq ) : final-classes ( quot -- seq )
final-info [ class>> ] map ; final-info [ class>> ] map ;

View File

@ -59,7 +59,7 @@ M: #recursive propagate-around ( #recursive -- )
iter-counter inc iter-counter inc
iter-counter get 10 > [ "Oops" throw ] when iter-counter get 10 > [ "Oops" throw ] when
dup label>> t >>fixed-point drop dup label>> t >>fixed-point drop
[ node-child first>> [ propagate-recursive-phi ] [ (propagate) ] bi ] [ child>> [ first propagate-recursive-phi ] [ (propagate) ] bi ]
[ dup label>> fixed-point>> [ drop ] [ propagate-around ] if ] [ dup label>> fixed-point>> [ drop ] [ propagate-around ] if ]
bi ; bi ;

View File

@ -13,7 +13,7 @@ compiler.tree.propagation.constraints ;
IN: compiler.tree.propagation.simple IN: compiler.tree.propagation.simple
M: #introduce propagate-before M: #introduce propagate-before
object <class-info> swap values>> [ set-value-info ] with each ; value>> object <class-info> swap set-value-info ;
M: #push propagate-before M: #push propagate-before
[ literal>> value>> <literal-info> ] [ out-d>> first ] bi [ literal>> value>> <literal-info> ] [ out-d>> first ] bi

View File

@ -0,0 +1,5 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler.tree.strength-reduction
: strength-reduce ( nodes -- nodes' ) ;

View File

@ -6,41 +6,17 @@ accessors combinators stack-checker.state stack-checker.visitor ;
IN: compiler.tree IN: compiler.tree
! High-level tree SSA form. ! High-level tree SSA form.
!
! Invariants: TUPLE: node < identity-tuple info ;
! 1) Each value has exactly one definition. A "definition" means
! the value appears in the out-d or out-r slot of a node, or the
! values slot of an #introduce node.
! 2) Each value appears only once in the inputs of a node, where
! the inputs are the concatenation of in-d and in-r, or in the
! case of a #phi node, the sequence of sequences in the phi-in-r
! and phi-in-d slots.
! 3) A value is never used in the same node where it is defined.
TUPLE: node < identity-tuple
in-d out-d in-r out-r info
successor children ;
M: node hashcode* drop node hashcode* ; M: node hashcode* drop node hashcode* ;
: node-child ( node -- child ) children>> first ; TUPLE: #introduce < node value ;
: last-node ( node -- last ) : #introduce ( value -- node )
dup successor>> [ last-node ] [ ] ?if ; \ #introduce new swap >>value ;
: penultimate-node ( node -- penultimate ) TUPLE: #call < node word history in-d out-d ;
dup successor>> dup [
dup successor>>
[ nip penultimate-node ] [ drop ] if
] [
2drop f
] if ;
TUPLE: #introduce < node values ;
: #introduce ( values -- node )
\ #introduce new swap >>values ;
TUPLE: #call < node word history ;
: #call ( inputs outputs word -- node ) : #call ( inputs outputs word -- node )
\ #call new \ #call new
@ -48,7 +24,7 @@ TUPLE: #call < node word history ;
swap >>out-d swap >>out-d
swap >>in-d ; swap >>in-d ;
TUPLE: #call-recursive < node label ; TUPLE: #call-recursive < node label in-d out-d ;
: #call-recursive ( inputs outputs label -- node ) : #call-recursive ( inputs outputs label -- node )
\ #call-recursive new \ #call-recursive new
@ -56,14 +32,14 @@ TUPLE: #call-recursive < node label ;
swap >>out-d swap >>out-d
swap >>in-d ; swap >>in-d ;
TUPLE: #push < node literal ; TUPLE: #push < node literal out-d ;
: #push ( literal value -- node ) : #push ( literal value -- node )
\ #push new \ #push new
swap 1array >>out-d swap 1array >>out-d
swap >>literal ; swap >>literal ;
TUPLE: #shuffle < node mapping ; TUPLE: #shuffle < node mapping in-d out-d ;
: #shuffle ( inputs outputs mapping -- node ) : #shuffle ( inputs outputs mapping -- node )
\ #shuffle new \ #shuffle new
@ -74,27 +50,27 @@ TUPLE: #shuffle < node mapping ;
: #drop ( inputs -- node ) : #drop ( inputs -- node )
{ } { } #shuffle ; { } { } #shuffle ;
TUPLE: #>r < node ; TUPLE: #>r < node in-d out-r ;
: #>r ( inputs outputs -- node ) : #>r ( inputs outputs -- node )
\ #>r new \ #>r new
swap >>out-r swap >>out-r
swap >>in-d ; swap >>in-d ;
TUPLE: #r> < node ; TUPLE: #r> < node in-r out-d ;
: #r> ( inputs outputs -- node ) : #r> ( inputs outputs -- node )
\ #r> new \ #r> new
swap >>out-d swap >>out-d
swap >>in-r ; swap >>in-r ;
TUPLE: #terminate < node ; TUPLE: #terminate < node in-d ;
: #terminate ( stack -- node ) : #terminate ( stack -- node )
\ #terminate new \ #terminate new
swap >>in-d ; swap >>in-d ;
TUPLE: #branch < node ; TUPLE: #branch < node in-d children ;
: new-branch ( value children class -- node ) : new-branch ( value children class -- node )
new new
@ -111,7 +87,7 @@ TUPLE: #dispatch < #branch ;
: #dispatch ( n branches -- node ) : #dispatch ( n branches -- node )
\ #dispatch new-branch ; \ #dispatch new-branch ;
TUPLE: #phi < node phi-in-d phi-in-r ; TUPLE: #phi < node phi-in-d phi-in-r out-d out-r ;
: #phi ( d-phi-in d-phi-out r-phi-in r-phi-out -- node ) : #phi ( d-phi-in d-phi-out r-phi-in r-phi-out -- node )
\ #phi new \ #phi new
@ -126,22 +102,22 @@ TUPLE: #declare < node declaration ;
\ #declare new \ #declare new
swap >>declaration ; swap >>declaration ;
TUPLE: #return < node ; TUPLE: #return < node in-d ;
: #return ( stack -- node ) : #return ( stack -- node )
\ #return new \ #return new
swap >>in-d ; swap >>in-d ;
TUPLE: #recursive < node word label loop? returns calls ; TUPLE: #recursive < node in-d word label loop? returns calls child ;
: #recursive ( word label inputs child -- node ) : #recursive ( word label inputs child -- node )
\ #recursive new \ #recursive new
swap 1array >>children swap >>child
swap >>in-d swap >>in-d
swap >>label swap >>label
swap >>word ; swap >>word ;
TUPLE: #enter-recursive < node label ; TUPLE: #enter-recursive < node in-d out-d label ;
: #enter-recursive ( label inputs outputs -- node ) : #enter-recursive ( label inputs outputs -- node )
\ #enter-recursive new \ #enter-recursive new
@ -149,7 +125,7 @@ TUPLE: #enter-recursive < node label ;
swap >>in-d swap >>in-d
swap >>label ; swap >>label ;
TUPLE: #return-recursive < node label ; TUPLE: #return-recursive < node in-d out-d label ;
: #return-recursive ( label inputs outputs -- node ) : #return-recursive ( label inputs outputs -- node )
\ #return-recursive new \ #return-recursive new
@ -157,44 +133,31 @@ TUPLE: #return-recursive < node label ;
swap >>in-d swap >>in-d
swap >>label ; swap >>label ;
TUPLE: #copy < node ; TUPLE: #copy < node in-d out-d ;
: #copy ( inputs outputs -- node ) : #copy ( inputs outputs -- node )
\ #copy new \ #copy new
swap >>out-d swap >>out-d
swap >>in-d ; swap >>in-d ;
DEFER: #tail? : node, ( node -- ) stack-visitor get push ;
PREDICATE: #tail-phi < #phi successor>> #tail? ; M: vector child-visitor V{ } clone ;
M: vector #introduce, #introduce node, ;
UNION: #tail POSTPONE: f #return #tail-phi #terminate ; M: vector #call, #call node, ;
M: vector #push, #push node, ;
TUPLE: node-list first last ; M: vector #shuffle, #shuffle node, ;
M: vector #drop, #drop node, ;
: node, ( node -- ) M: vector #>r, #>r node, ;
stack-visitor get swap M: vector #r>, #r> node, ;
over last>> M: vector #return, #return node, ;
[ [ [ last>> ] dip >>successor drop ] [ >>last drop ] 2bi ] M: vector #enter-recursive, #enter-recursive node, ;
[ [ >>first ] [ >>last ] bi drop ] M: vector #return-recursive, #return-recursive node, ;
if ; M: vector #call-recursive, #call-recursive node, ;
M: vector #terminate, #terminate node, ;
M: node-list child-visitor node-list new ; M: vector #if, #if node, ;
M: node-list #introduce, #introduce node, ; M: vector #dispatch, #dispatch node, ;
M: node-list #call, #call node, ; M: vector #phi, #phi node, ;
M: node-list #push, #push node, ; M: vector #declare, #declare node, ;
M: node-list #shuffle, #shuffle node, ; M: vector #recursive, #recursive node, ;
M: node-list #drop, #drop node, ; M: vector #copy, #copy node, ;
M: node-list #>r, #>r node, ;
M: node-list #r>, #r> node, ;
M: node-list #return, #return node, ;
M: node-list #enter-recursive, #enter-recursive node, ;
M: node-list #return-recursive, #return-recursive [ node, ] [ dup label>> (>>return) ] bi ;
M: node-list #call-recursive, #call-recursive [ node, ] [ dup label>> calls>> push ] bi ;
M: node-list #terminate, #terminate node, ;
M: node-list #if, #if node, ;
M: node-list #dispatch, #dispatch node, ;
M: node-list #phi, #phi node, ;
M: node-list #declare, #declare node, ;
M: node-list #recursive, #recursive node, ;
M: node-list #copy, #copy node, ;

View File

@ -3,7 +3,8 @@
USING: accessors slots.private kernel namespaces disjoint-sets USING: accessors slots.private kernel namespaces disjoint-sets
math sequences assocs classes.tuple.private combinators fry sets math sequences assocs classes.tuple.private combinators fry sets
compiler.tree compiler.tree.combinators compiler.tree.copy-equiv compiler.tree compiler.tree.combinators compiler.tree.copy-equiv
compiler.tree.dfa compiler.tree.dfa.backward ; compiler.tree.dataflow-analysis
compiler.tree.dataflow-analysis.backward ;
IN: compiler.tree.untupling IN: compiler.tree.untupling
SYMBOL: escaping-values SYMBOL: escaping-values

View File

@ -41,7 +41,7 @@ SYMBOL: visited
: pop-d ( -- obj ) : pop-d ( -- obj )
meta-d get dup empty? [ meta-d get dup empty? [
drop <value> dup 1array #introduce, d-in inc drop <value> dup #introduce, d-in inc
] [ pop ] if ; ] [ pop ] if ;
: peek-d ( -- obj ) pop-d dup push-d ; : peek-d ( -- obj ) pop-d dup push-d ;
@ -52,8 +52,11 @@ SYMBOL: visited
: ensure-d ( n -- values ) consume-d dup output-d ; : ensure-d ( n -- values ) consume-d dup output-d ;
: make-values ( n -- values )
[ <value> ] replicate ;
: produce-d ( n -- values ) : produce-d ( n -- values )
[ <value> ] replicate dup meta-d get push-all ; make-values dup meta-d get push-all ;
: push-r ( obj -- ) meta-r get push ; : push-r ( obj -- ) meta-r get push ;

View File

@ -9,7 +9,7 @@ HOOK: child-visitor stack-visitor ( -- visitor )
: nest-visitor ( -- ) child-visitor stack-visitor set ; : nest-visitor ( -- ) child-visitor stack-visitor set ;
HOOK: #introduce, stack-visitor ( values -- ) HOOK: #introduce, stack-visitor ( value -- )
HOOK: #call, stack-visitor ( inputs outputs word -- ) HOOK: #call, stack-visitor ( inputs outputs word -- )
HOOK: #call-recursive, stack-visitor ( inputs outputs word -- ) HOOK: #call-recursive, stack-visitor ( inputs outputs word -- )
HOOK: #push, stack-visitor ( literal value -- ) HOOK: #push, stack-visitor ( literal value -- )