1 ! Copyright (C) 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs combinators deques dlists fry kernel
4 namespaces sequences sets compiler.cfg compiler.cfg.predecessors ;
5 IN: compiler.cfg.loop-detection
7 TUPLE: natural-loop header index ends blocks ;
13 : <natural-loop> ( header index -- loop )
14 H{ } clone H{ } clone natural-loop boa ;
16 : lookup-header ( header -- loop )
18 loops get assoc-size <natural-loop>
21 SYMBOLS: visited active ;
23 : record-back-edge ( from to -- )
24 lookup-header ends>> conjoin ;
26 DEFER: find-loop-headers
28 : visit-edge ( from to -- )
31 [ nip find-loop-headers ]
34 : find-loop-headers ( bb -- )
35 dup visited get key? [ drop ] [
37 [ visited get conjoin ]
38 [ active get conjoin ]
39 [ dup successors>> [ visit-edge ] with each ]
40 [ active get delete-at ]
46 : process-loop-block ( bb loop -- )
47 2dup blocks>> key? [ 2drop ] [
48 [ blocks>> conjoin ] [
49 2dup header>> eq? [ 2drop ] [
50 drop predecessors>> work-list get push-all-front
55 : process-loop-ends ( loop -- )
56 [ ends>> keys <dlist> [ push-all-front ] [ work-list set ] [ ] tri ] keep
57 '[ _ process-loop-block ] slurp-deque ;
59 : process-loop-headers ( -- )
60 loops get values [ process-loop-ends ] each ;
64 : compute-loop-nesting ( -- )
65 loops get H{ } clone [
66 [ values ] dip '[ blocks>> values [ _ inc-at ] each ] each
67 ] keep loop-nesting set ;
69 : detect-loops ( cfg -- cfg' )
72 H{ } clone visited set
74 H{ } clone loop-nesting set
75 dup entry>> find-loop-headers process-loop-headers compute-loop-nesting ;
79 : loop-nesting-at ( bb -- n ) loop-nesting get at 0 or ;
81 : needs-loops ( cfg -- cfg' )
83 dup loops-valid?>> [ detect-loops t >>loops-valid? ] unless ;