Debugging new optimizer
parent
a61e13f7be
commit
e1987d4af9
|
@ -15,4 +15,4 @@ M: column length seq>> length ;
|
|||
INSTANCE: column virtual-sequence
|
||||
|
||||
: <flipped> ( seq -- seq' )
|
||||
dup empty? [ first length [ <column> ] with map ] unless ;
|
||||
dup empty? [ dup first length [ <column> ] with map ] unless ;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
! Copyright (C) 2004, 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel namespaces arrays sequences io debugger words
|
||||
USING: kernel namespaces arrays sequences io debugger words fry
|
||||
compiler.units continuations vocabs assocs dlists definitions
|
||||
math threads graphs generic combinators dequeues search-dequeues
|
||||
stack-checker stack-checker.state compiler.generator
|
||||
|
@ -47,10 +47,10 @@ SYMBOL: +failed+
|
|||
|
||||
: (compile) ( word -- )
|
||||
USE: prettyprint dup .
|
||||
[
|
||||
'[
|
||||
H{ } clone dependencies set
|
||||
|
||||
{
|
||||
, {
|
||||
[ compile-begins ]
|
||||
[
|
||||
[ build-tree-from-word ] [ compile-failed return ] recover
|
||||
|
@ -59,7 +59,7 @@ SYMBOL: +failed+
|
|||
[ dup generate ]
|
||||
[ compile-succeeded ]
|
||||
} cleave
|
||||
] curry with-return ;
|
||||
] with-return ;
|
||||
|
||||
: compile-loop ( dequeue -- )
|
||||
[ (compile) yield ] slurp-dequeue ;
|
||||
|
|
|
@ -92,7 +92,7 @@ M: node generate-node drop iterate-next ;
|
|||
%jump-label ;
|
||||
|
||||
: generate-call ( label -- next )
|
||||
dup maybe-compile
|
||||
! dup maybe-compile
|
||||
end-basic-block
|
||||
dup compiling-loops get at [
|
||||
%jump-label f
|
||||
|
@ -107,7 +107,7 @@ M: node generate-node drop iterate-next ;
|
|||
] ?if ;
|
||||
|
||||
! #recursive
|
||||
: compile-recursive ( node -- )
|
||||
: compile-recursive ( node -- next )
|
||||
dup label>> id>> generate-call >r
|
||||
[ child>> ] [ label>> word>> ] [ label>> id>> ] tri generate
|
||||
r> ;
|
||||
|
@ -115,7 +115,7 @@ M: node generate-node drop iterate-next ;
|
|||
: compiling-loop ( word -- )
|
||||
<label> dup resolve-label swap compiling-loops get set-at ;
|
||||
|
||||
: compile-loop ( node -- )
|
||||
: compile-loop ( node -- next )
|
||||
end-basic-block
|
||||
[ label>> id>> compiling-loop ] [ child>> generate-nodes ] bi
|
||||
iterate-next ;
|
||||
|
@ -232,7 +232,7 @@ M: #dispatch generate-node
|
|||
] if ;
|
||||
|
||||
M: #call generate-node
|
||||
dup node-input-infos [ class>> ] map set-operand-classes
|
||||
! dup node-input-infos [ class>> ] map set-operand-classes
|
||||
dup find-if-intrinsic [
|
||||
do-if-intrinsic
|
||||
] [
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
IN: compiler.tree.builder.tests
|
||||
USING: compiler.tree.builder tools.test ;
|
||||
USING: compiler.tree.builder tools.test sequences kernel
|
||||
compiler.tree ;
|
||||
|
||||
\ build-tree must-infer
|
||||
\ build-tree-with must-infer
|
||||
\ build-tree-from-word must-infer
|
||||
|
||||
: inline-recursive ( -- ) inline-recursive ; inline recursive
|
||||
|
||||
[ t ] [ \ inline-recursive build-tree-from-word [ #recursive? ] contains? nip ] unit-test
|
||||
|
|
|
@ -22,10 +22,15 @@ IN: compiler.tree.builder
|
|||
] with-tree-builder nip
|
||||
unclip-last in-d>> ;
|
||||
|
||||
: ends-with-terminate? ( nodes -- ? )
|
||||
dup empty? [ drop f ] [ peek #terminate? ] if ;
|
||||
|
||||
: build-sub-tree ( #call quot -- nodes )
|
||||
[ [ out-d>> ] [ in-d>> ] bi ] dip
|
||||
build-tree-with
|
||||
rot #copy suffix ;
|
||||
[ [ out-d>> ] [ in-d>> ] bi ] dip build-tree-with
|
||||
over ends-with-terminate?
|
||||
[ drop swap [ f swap #push ] map append ]
|
||||
[ rot #copy suffix ]
|
||||
if ;
|
||||
|
||||
: (make-specializer) ( class picker -- quot )
|
||||
swap "predicate" word-prop append ;
|
||||
|
@ -70,13 +75,31 @@ IN: compiler.tree.builder
|
|||
[ drop ]
|
||||
} cond ;
|
||||
|
||||
: (build-tree-from-word) ( word -- )
|
||||
dup
|
||||
[ "inline" word-prop ]
|
||||
[ "recursive" word-prop ] bi and [
|
||||
1quotation f infer-quot
|
||||
] [
|
||||
[ specialized-def ]
|
||||
[ dup 2array 1array ] bi infer-quot
|
||||
] if ;
|
||||
|
||||
: check-cannot-infer ( word -- )
|
||||
dup +cannot-infer+ word-prop [ cannot-infer-effect ] [ drop ] if ;
|
||||
|
||||
: check-no-compile ( word -- )
|
||||
dup "no-compile" word-prop [ cannot-infer-effect ] [ drop ] if ;
|
||||
|
||||
: build-tree-from-word ( word -- effect nodes )
|
||||
[
|
||||
[
|
||||
dup +cannot-infer+ word-prop [ cannot-infer-effect ] when
|
||||
dup "no-compile" word-prop [ cannot-infer-effect ] when
|
||||
dup specialized-def over dup 2array 1array infer-quot
|
||||
finish-word
|
||||
{
|
||||
[ check-cannot-infer ]
|
||||
[ check-no-compile ]
|
||||
[ (build-tree-from-word) ]
|
||||
[ finish-word ]
|
||||
} cleave
|
||||
] maybe-cannot-infer
|
||||
] with-tree-builder ;
|
||||
|
||||
|
|
|
@ -13,14 +13,30 @@ IN: compiler.tree.cleanup
|
|||
! A phase run after propagation to finish the job, so to speak.
|
||||
! Codifies speculative inlining decisions, deletes branches
|
||||
! marked as never taken, and flattens local recursive blocks
|
||||
! that do not call themselves.
|
||||
! that do not call themselves. Finally, if inlining inserts a
|
||||
! #terminate, we delete all nodes after that.
|
||||
|
||||
GENERIC: delete-node ( node -- )
|
||||
|
||||
M: #call-recursive delete-node
|
||||
dup label>> [ [ eq? not ] with filter ] change-calls drop ;
|
||||
|
||||
M: #return-recursive delete-node
|
||||
label>> f >>return drop ;
|
||||
|
||||
M: node delete-node drop ;
|
||||
|
||||
: delete-nodes ( nodes -- ) [ delete-node ] each-node ;
|
||||
|
||||
GENERIC: cleanup* ( node -- node/nodes )
|
||||
|
||||
: termination-cleanup ( nodes -- nodes' )
|
||||
dup [ #terminate? ] find drop [ 1+ cut delete-nodes ] when* ;
|
||||
|
||||
: cleanup ( nodes -- nodes' )
|
||||
#! We don't recurse into children here, instead the methods
|
||||
#! do it since the logic is a bit more involved
|
||||
[ cleanup* ] map flatten ;
|
||||
[ cleanup* ] map flatten ; ! termination-cleanup ;
|
||||
|
||||
: cleanup-folding? ( #call -- ? )
|
||||
node-output-infos dup empty?
|
||||
|
@ -74,18 +90,6 @@ M: #call cleanup*
|
|||
|
||||
M: #declare cleanup* drop f ;
|
||||
|
||||
GENERIC: delete-node ( node -- )
|
||||
|
||||
M: #call-recursive delete-node
|
||||
dup label>> [ [ eq? not ] with filter ] change-calls drop ;
|
||||
|
||||
M: #return-recursive delete-node
|
||||
label>> f >>return drop ;
|
||||
|
||||
M: node delete-node drop ;
|
||||
|
||||
: delete-nodes ( nodes -- ) [ delete-node ] each-node ;
|
||||
|
||||
: delete-unreachable-branches ( #branch -- )
|
||||
dup live-branches>> '[
|
||||
,
|
||||
|
|
|
@ -20,48 +20,47 @@ M: #phi compute-live-values*
|
|||
[ [ out-r>> ] [ phi-in-r>> ] bi look-at-phi ]
|
||||
2bi ;
|
||||
|
||||
SYMBOL: if-node
|
||||
|
||||
M: #if remove-dead-code*
|
||||
[ [ (remove-dead-code) ] map ] change-children
|
||||
dup if-node set ;
|
||||
M: #branch remove-dead-code*
|
||||
[ [ (remove-dead-code) ] map ] change-children ;
|
||||
|
||||
: remove-phi-inputs ( #phi -- )
|
||||
dup [ out-d>> ] [ phi-in-d>> ] bi filter-corresponding >>phi-in-d
|
||||
dup [ out-r>> ] [ phi-in-r>> ] bi filter-corresponding >>phi-in-r
|
||||
dup [ out-d>> ] [ phi-in-d>> flip ] bi filter-corresponding flip >>phi-in-d
|
||||
dup [ out-r>> ] [ phi-in-r>> flip ] bi filter-corresponding flip >>phi-in-r
|
||||
drop ;
|
||||
|
||||
: dead-value-indices ( values -- indices )
|
||||
[ length ] keep live-values get
|
||||
'[ , nth , key? not ] filter ; inline
|
||||
|
||||
: drop-d-values ( values indices -- node )
|
||||
[ drop filter-live ] [ nths filter-live ] 2bi
|
||||
[ make-values ] keep
|
||||
[ drop ] [ zip ] 2bi
|
||||
#shuffle ;
|
||||
|
||||
: drop-r-values ( values indices -- nodes )
|
||||
[ dup make-values [ #r> ] keep ] dip
|
||||
drop-d-values dup out-d>> dup make-values #>r
|
||||
3array ;
|
||||
|
||||
: insert-drops ( nodes d-values r-values d-indices r-indices -- nodes' )
|
||||
'[
|
||||
[ , drop-d-values 1array ]
|
||||
[ , drop-r-values ]
|
||||
bi* 3append
|
||||
] 3map ;
|
||||
|
||||
: hoist-drops ( #phi -- )
|
||||
if-node get swap
|
||||
{
|
||||
[ phi-in-d>> ]
|
||||
[ phi-in-r>> ]
|
||||
[ out-d>> dead-value-indices ]
|
||||
[ out-r>> dead-value-indices ]
|
||||
} cleave
|
||||
'[ , , , , insert-drops ] change-children drop ;
|
||||
! SYMBOL: if-node
|
||||
!
|
||||
! : dead-value-indices ( values -- indices )
|
||||
! [ length ] keep live-values get
|
||||
! '[ , nth , key? not ] filter ; inline
|
||||
!
|
||||
! : drop-d-values ( values indices -- node )
|
||||
! [ drop filter-live ] [ nths filter-live ] 2bi
|
||||
! [ make-values ] keep
|
||||
! [ drop ] [ zip ] 2bi
|
||||
! #shuffle ;
|
||||
!
|
||||
! : drop-r-values ( values indices -- nodes )
|
||||
! [ dup make-values [ #r> ] keep ] dip
|
||||
! drop-d-values dup out-d>> dup make-values #>r
|
||||
! 3array ;
|
||||
!
|
||||
! : insert-drops ( nodes d-values r-values d-indices r-indices -- nodes' )
|
||||
! '[
|
||||
! [ , drop-d-values 1array ]
|
||||
! [ , drop-r-values ]
|
||||
! bi* 3append
|
||||
! ] 3map ;
|
||||
!
|
||||
! : hoist-drops ( #phi -- )
|
||||
! if-node get swap
|
||||
! {
|
||||
! [ phi-in-d>> ]
|
||||
! [ phi-in-r>> ]
|
||||
! [ out-d>> dead-value-indices ]
|
||||
! [ out-r>> dead-value-indices ]
|
||||
! } cleave
|
||||
! '[ , , , , insert-drops ] change-children drop ;
|
||||
|
||||
: remove-phi-outputs ( #phi -- )
|
||||
[ filter-live ] change-out-d
|
||||
|
@ -70,7 +69,7 @@ M: #if remove-dead-code*
|
|||
|
||||
M: #phi remove-dead-code*
|
||||
{
|
||||
[ hoist-drops ]
|
||||
! [ hoist-drops ]
|
||||
[ remove-phi-inputs ]
|
||||
[ remove-phi-outputs ]
|
||||
[ ]
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
USING: namespaces assocs sequences compiler.tree.builder
|
||||
compiler.tree.dead-code compiler.tree.def-use compiler.tree
|
||||
compiler.tree.combinators compiler.tree.debugger
|
||||
compiler.tree.combinators compiler.tree.propagation
|
||||
compiler.tree.cleanup compiler.tree.escape-analysis
|
||||
compiler.tree.tuple-unboxing compiler.tree.debugger
|
||||
compiler.tree.normalization compiler.tree.checker tools.test
|
||||
kernel math stack-checker.state accessors combinators io ;
|
||||
IN: compiler.tree.dead-code.tests
|
||||
|
@ -10,6 +12,10 @@ IN: compiler.tree.dead-code.tests
|
|||
: count-live-values ( quot -- n )
|
||||
build-tree
|
||||
normalize
|
||||
propagate
|
||||
cleanup
|
||||
escape-analysis
|
||||
unbox-tuples
|
||||
compute-def-use
|
||||
remove-dead-code
|
||||
0 swap [
|
||||
|
@ -32,11 +38,11 @@ IN: compiler.tree.dead-code.tests
|
|||
|
||||
[ 2 ] [ [ [ 1 ] [ dup ] if drop ] count-live-values ] unit-test
|
||||
|
||||
[ 2 ] [ [ 1 2 + ] count-live-values ] unit-test
|
||||
[ 2 ] [ [ 1 + ] count-live-values ] unit-test
|
||||
|
||||
[ 0 ] [ [ 1 2 + drop ] count-live-values ] unit-test
|
||||
|
||||
[ 3 ] [ [ 1 2 + 3 + ] count-live-values ] unit-test
|
||||
[ 3 ] [ [ 1 + 3 + ] count-live-values ] unit-test
|
||||
|
||||
[ 0 ] [ [ 1 2 + 3 + drop ] count-live-values ] unit-test
|
||||
|
||||
|
@ -52,9 +58,18 @@ IN: compiler.tree.dead-code.tests
|
|||
|
||||
[ 0 ] [ [ [ 1 ] [ 2 ] compose call + drop ] count-live-values ] unit-test
|
||||
|
||||
[ 3 ] [ [ 10 [ ] times ] count-live-values ] unit-test
|
||||
|
||||
: optimize-quot ( quot -- quot' )
|
||||
build-tree normalize compute-def-use remove-dead-code
|
||||
dup check-nodes nodes>quot ;
|
||||
build-tree
|
||||
normalize
|
||||
propagate
|
||||
cleanup
|
||||
escape-analysis
|
||||
unbox-tuples
|
||||
compute-def-use
|
||||
remove-dead-code
|
||||
"no-check" get [ dup check-nodes ] unless nodes>quot ;
|
||||
|
||||
[ [ drop 1 ] ] [ [ >r 1 r> drop ] optimize-quot ] unit-test
|
||||
|
||||
|
@ -76,3 +91,14 @@ IN: compiler.tree.dead-code.tests
|
|||
[ [ [ drop drop ] [ non-flushable-3 drop ] if ] ] [
|
||||
[ [ flushable-1 ] [ non-flushable-3 ] if drop ] optimize-quot
|
||||
] unit-test
|
||||
|
||||
[ [ [ f ] [ f ] if ] ] [ [ [ f ] [ f ] if ] optimize-quot ] unit-test
|
||||
|
||||
[ ] [ [ dup [ 3 throw ] [ ] if ] optimize-quot drop ] unit-test
|
||||
|
||||
: non-flushable-4 ( a -- b ) drop f ;
|
||||
|
||||
: recursive-test-1 ( a b -- )
|
||||
dup 10 < [
|
||||
>r drop 5 non-flushable-4 r> 1 + recursive-test-1
|
||||
] [ 2drop ] if ; inline recursive
|
||||
|
|
|
@ -15,8 +15,14 @@ M: #enter-recursive compute-live-values*
|
|||
M: #return-recursive compute-live-values*
|
||||
[ out-d>> ] [ return-recursive-phi-in ] bi look-at-phi ;
|
||||
|
||||
M: #call-recursive compute-live-values*
|
||||
#! If the output of a copy is live, then the corresponding
|
||||
#! inputs to #return nodes are live also.
|
||||
[ out-d>> ] [ label>> return>> in-d>> ] bi look-at-mapping ;
|
||||
|
||||
M: #recursive remove-dead-code*
|
||||
[ filter-live ] change-in-d ;
|
||||
[ filter-live ] change-in-d
|
||||
[ (remove-dead-code) ] change-child ;
|
||||
|
||||
M: #call-recursive remove-dead-code*
|
||||
[ filter-live ] change-in-d
|
||||
|
|
|
@ -25,11 +25,6 @@ M: #copy compute-live-values*
|
|||
|
||||
M: #call compute-live-values* nip look-at-inputs ;
|
||||
|
||||
M: #call-recursive compute-live-values*
|
||||
#! If the output of a copy is live, then the corresponding
|
||||
#! inputs to #return nodes are live also.
|
||||
[ out-d>> ] [ label>> return>> ] bi look-at-mapping ;
|
||||
|
||||
M: #>r compute-live-values*
|
||||
[ out-r>> ] [ in-d>> ] bi look-at-mapping ;
|
||||
|
||||
|
@ -108,3 +103,7 @@ M: #copy remove-dead-code*
|
|||
[ in-d>> ] [ out-d>> ] bi
|
||||
2dup swap zip #shuffle
|
||||
remove-dead-code* ;
|
||||
|
||||
M: #terminate remove-dead-code*
|
||||
[ filter-live ] change-in-d
|
||||
[ filter-live ] change-in-r ;
|
||||
|
|
|
@ -21,7 +21,7 @@ MACRO: match-choose ( alist -- )
|
|||
MATCH-VARS: ?a ?b ?c ;
|
||||
|
||||
: pretty-shuffle ( effect -- word/f )
|
||||
[ in>> ] [ out>> ] bi drop-prefix [ >array ] bi@ 2array {
|
||||
[ in>> ] [ out>> ] bi 2array {
|
||||
{ { { } { } } [ ] }
|
||||
{ { { ?a } { ?a } } [ ] }
|
||||
{ { { ?a ?b } { ?a ?b } } [ ] }
|
||||
|
@ -84,6 +84,12 @@ M: #r> node>quot
|
|||
[ in-r>> length ] [ out-d>> empty? \ rdrop \ r> ? ] bi
|
||||
<repetition> % ;
|
||||
|
||||
M: #alien-invoke node>quot params>> , \ #alien-invoke , ;
|
||||
|
||||
M: #alien-indirect node>quot params>> , \ #alien-indirect , ;
|
||||
|
||||
M: #alien-callback node>quot params>> , \ #alien-callback , ;
|
||||
|
||||
M: node node>quot drop ;
|
||||
|
||||
: nodes>quot ( node -- quot )
|
||||
|
|
|
@ -43,6 +43,8 @@ M: #phi node-uses-values
|
|||
[ phi-in-d>> ] [ phi-in-r>> ] bi
|
||||
append concat remove-bottom prune ;
|
||||
M: #declare node-uses-values declaration>> keys ;
|
||||
M: #terminate node-uses-values [ in-d>> ] [ in-r>> ] bi append ;
|
||||
M: #alien-callback node-uses-values drop f ;
|
||||
M: node node-uses-values in-d>> ;
|
||||
|
||||
GENERIC: node-defs-values ( node -- values )
|
||||
|
@ -54,6 +56,7 @@ 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: #alien-callback node-defs-values drop f ;
|
||||
M: node node-defs-values out-d>> ;
|
||||
|
||||
: node-def-use ( node -- )
|
||||
|
|
|
@ -81,10 +81,10 @@ M: #return escape-analysis*
|
|||
|
||||
M: #alien-invoke escape-analysis*
|
||||
[ in-d>> add-escaping-values ]
|
||||
[ out-d>> unknown-allocation ]
|
||||
[ out-d>> unknown-allocations ]
|
||||
bi ;
|
||||
|
||||
M: #alien-indirect escape-analysis*
|
||||
[ in-d>> add-escaping-values ]
|
||||
[ out-d>> unknown-allocation ]
|
||||
[ out-d>> unknown-allocations ]
|
||||
bi ;
|
||||
|
|
|
@ -10,7 +10,8 @@ compiler.tree.dead-code
|
|||
compiler.tree.strength-reduction
|
||||
compiler.tree.loop.detection
|
||||
compiler.tree.loop.inversion
|
||||
compiler.tree.branch-fusion ;
|
||||
compiler.tree.branch-fusion
|
||||
compiler.tree.checker ;
|
||||
IN: compiler.tree.optimizer
|
||||
|
||||
: optimize-tree ( nodes -- nodes' )
|
||||
|
@ -18,10 +19,12 @@ IN: compiler.tree.optimizer
|
|||
propagate
|
||||
cleanup
|
||||
detect-loops
|
||||
invert-loops
|
||||
fuse-branches
|
||||
escape-analysis
|
||||
unbox-tuples
|
||||
compute-def-use
|
||||
remove-dead-code
|
||||
strength-reduce ;
|
||||
! invert-loops
|
||||
! fuse-branches
|
||||
! escape-analysis
|
||||
! unbox-tuples
|
||||
! compute-def-use
|
||||
! remove-dead-code
|
||||
! strength-reduce
|
||||
compute-def-use USE: kernel
|
||||
dup check-nodes ;
|
||||
|
|
|
@ -123,7 +123,7 @@ DEFER: (flat-length)
|
|||
SYMBOL: history
|
||||
|
||||
: remember-inlining ( word -- )
|
||||
history get [ swap suffix ] change ;
|
||||
history [ swap suffix ] change ;
|
||||
|
||||
: inline-word ( #call word -- )
|
||||
dup history get memq? [
|
||||
|
|
|
@ -253,7 +253,7 @@ generic-comparison-ops [
|
|||
|
||||
{ <tuple> <tuple-boa> } [
|
||||
[
|
||||
literal>> dup tuple-layout? [ class>> ] [ drop tuple ] if
|
||||
literal>> dup tuple-layout? [ class>> ] [ drop tuple ] if <class-info>
|
||||
[ clear ] dip
|
||||
] +outputs+ set-word-prop
|
||||
] each
|
||||
|
@ -273,10 +273,10 @@ generic-comparison-ops [
|
|||
\ instance? [
|
||||
[ value-info ] dip over literal>> class? [
|
||||
[ literal>> ] dip predicate-constraints
|
||||
] [ 2drop f ] if
|
||||
] [ 3drop f ] if
|
||||
] +constraints+ set-word-prop
|
||||
|
||||
\ instance? [
|
||||
dup literal>> class?
|
||||
[ literal>> predicate-output-infos ] [ 2drop f ] if
|
||||
[ literal>> predicate-output-infos ] [ 2drop object-info ] if
|
||||
] +outputs+ set-word-prop
|
||||
|
|
|
@ -557,3 +557,12 @@ M: fixnum bad-generic 1 fixnum+fast ;
|
|||
0 10 [ bad-generic dup 123 bitand drop bad-generic 1 + ] times
|
||||
] final-classes
|
||||
] unit-test
|
||||
|
||||
GENERIC: infinite-loop ( a -- b )
|
||||
M: integer infinite-loop infinite-loop ;
|
||||
|
||||
[ ] [ [ { integer } declare infinite-loop ] final-classes drop ] unit-test
|
||||
|
||||
[ V{ tuple } ] [ [ tuple-layout <tuple> ] final-classes ] unit-test
|
||||
|
||||
[ ] [ [ instance? ] final-classes drop ] unit-test
|
||||
|
|
|
@ -52,6 +52,7 @@ IN: compiler.tree.propagation.recursive
|
|||
3bi ;
|
||||
|
||||
M: #recursive propagate-around ( #recursive -- )
|
||||
"blah" USE: io print
|
||||
{ 0 } clone [ USE: math
|
||||
dup first 10 = [ "OOPS" throw ] [ dup first 1+ swap set-first ] if
|
||||
constraints [ clone ] change
|
||||
|
|
|
@ -66,10 +66,11 @@ TUPLE: #r> < #renaming in-r out-d ;
|
|||
swap >>out-d
|
||||
swap >>in-r ;
|
||||
|
||||
TUPLE: #terminate < node in-d ;
|
||||
TUPLE: #terminate < node in-d in-r ;
|
||||
|
||||
: #terminate ( stack -- node )
|
||||
: #terminate ( in-d in-r -- node )
|
||||
\ #terminate new
|
||||
swap >>in-r
|
||||
swap >>in-d ;
|
||||
|
||||
TUPLE: #branch < node in-d children live-branches ;
|
||||
|
|
|
@ -93,7 +93,8 @@ M: #shuffle unbox-tuples*
|
|||
[ unzip [ flatten-values ] bi@ zip ] change-mapping ;
|
||||
|
||||
M: #terminate unbox-tuples*
|
||||
[ flatten-values ] change-in-d ;
|
||||
[ flatten-values ] change-in-d
|
||||
[ flatten-values ] change-in-r ;
|
||||
|
||||
M: #phi unbox-tuples*
|
||||
[ [ flatten-values ] map pad-with-bottom ] change-phi-in-d
|
||||
|
|
|
@ -92,7 +92,7 @@ M:: disjoint-set equate ( a b disjoint-set -- )
|
|||
'[ , , equate ] each ;
|
||||
|
||||
: equate-all ( seq disjoint-set -- )
|
||||
over dup empty? [ 2drop ] [
|
||||
over empty? [ 2drop ] [
|
||||
[ unclip-slice ] dip equate-all-with
|
||||
] if ;
|
||||
|
||||
|
|
|
@ -288,7 +288,7 @@ M: wlet local-rewrite*
|
|||
CREATE-METHOD
|
||||
[ parse-locals-definition ] with-method-definition ;
|
||||
|
||||
: parsed-lambda ( form -- )
|
||||
: parsed-lambda ( accum form -- accum )
|
||||
in-lambda? get [ parsed ] [ lambda-rewrite over push-all ] if ;
|
||||
|
||||
PRIVATE>
|
||||
|
|
|
@ -85,7 +85,7 @@ M: wrapper apply-object
|
|||
M: object apply-object push-literal ;
|
||||
|
||||
: terminate ( -- )
|
||||
terminated? on meta-d get clone #terminate, ;
|
||||
terminated? on meta-d get clone meta-r get clone #terminate, ;
|
||||
|
||||
: infer-quot ( quot rstate -- )
|
||||
recursive-state get [
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
! Copyright (C) 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: fry namespaces assocs kernel sequences words accessors
|
||||
definitions math effects classes arrays combinators vectors
|
||||
arrays
|
||||
definitions math math.order effects classes arrays combinators
|
||||
vectors arrays
|
||||
stack-checker.state
|
||||
stack-checker.visitor
|
||||
stack-checker.backend
|
||||
|
@ -115,8 +115,8 @@ SYMBOL: enter-out
|
|||
|
||||
: adjust-stack-effect ( effect -- effect' )
|
||||
[ in>> ] [ out>> ] bi
|
||||
meta-d get length pick length - object <repetition>
|
||||
'[ , prepend ] bi@
|
||||
meta-d get length pick length - 0 max
|
||||
object <repetition> '[ , prepend ] bi@
|
||||
<effect> ;
|
||||
|
||||
: call-recursive-inline-word ( word -- )
|
||||
|
|
|
@ -563,3 +563,9 @@ M: object inference-invalidation-d inference-invalidation-c 2drop ;
|
|||
|
||||
{ 3 0 } [ [ 2drop "A" throw ] [ ] if 2drop ] must-infer-as
|
||||
{ 2 0 } [ drop f f [ 2drop "A" throw ] [ ] if 2drop ] must-infer-as
|
||||
|
||||
: unbalanced-retain-usage ( a b -- )
|
||||
dup 10 < [ 2drop 5 1 + unbalanced-retain-usage ] [ 2drop ] if ;
|
||||
inline recursive
|
||||
|
||||
[ unbalanced-retain-usage ] [ inference-error? ] must-fail-with
|
||||
|
|
|
@ -14,7 +14,7 @@ M: f #r>, 2drop ;
|
|||
M: f #return, drop ;
|
||||
M: f #enter-recursive, 3drop ;
|
||||
M: f #return-recursive, 3drop ;
|
||||
M: f #terminate, drop ;
|
||||
M: f #terminate, 2drop ;
|
||||
M: f #if, 3drop ;
|
||||
M: f #dispatch, 2drop ;
|
||||
M: f #phi, drop drop drop drop drop ;
|
||||
|
|
|
@ -17,7 +17,7 @@ HOOK: #shuffle, stack-visitor ( inputs outputs mapping -- )
|
|||
HOOK: #drop, stack-visitor ( values -- )
|
||||
HOOK: #>r, stack-visitor ( inputs outputs -- )
|
||||
HOOK: #r>, stack-visitor ( inputs outputs -- )
|
||||
HOOK: #terminate, stack-visitor ( stack -- )
|
||||
HOOK: #terminate, stack-visitor ( in-d in-r -- )
|
||||
HOOK: #if, stack-visitor ( ? true false -- )
|
||||
HOOK: #dispatch, stack-visitor ( n branches -- )
|
||||
HOOK: #phi, stack-visitor ( d-phi-in d-phi-out r-phi-in r-phi-out terminated -- )
|
||||
|
|
Loading…
Reference in New Issue