1 ! Copyright (C) 2009 Slava Pestov, Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays generalizations kernel math sequences
4 sequences.private fry ;
7 GENERIC: cursor-done? ( cursor -- ? )
8 GENERIC: cursor-get-unsafe ( cursor -- obj )
9 GENERIC: cursor-advance ( cursor -- )
10 GENERIC: cursor-valid? ( cursor -- ? )
11 GENERIC: cursor-write ( obj cursor -- )
13 ERROR: cursor-ended cursor ;
15 : cursor-get ( cursor -- obj )
17 [ cursor-ended ] [ cursor-get-unsafe ] if ; inline
19 : find-done? ( cursor quot -- ? )
21 [ 2drop t ] [ [ cursor-get-unsafe ] dip call ] if ; inline
23 : cursor-until ( cursor quot -- )
25 [ drop cursor-advance ] bi-curry bi-curry while ; inline
27 : cursor-each ( cursor quot -- )
28 [ f ] compose cursor-until ; inline
30 : cursor-find ( cursor quot -- obj ? )
31 [ cursor-until ] [ drop ] 2bi
32 dup cursor-done? [ drop f f ] [ cursor-get t ] if ; inline
34 : cursor-any? ( cursor quot -- ? )
35 cursor-find nip ; inline
37 : cursor-all? ( cursor quot -- ? )
38 [ not ] compose cursor-any? not ; inline
40 : cursor-map-quot ( quot to -- quot' )
41 [ [ call ] dip cursor-write ] 2curry ; inline
43 : cursor-map ( from to quot -- )
44 swap cursor-map-quot cursor-each ; inline
46 : cursor-write-if ( obj quot to -- )
47 [ over [ call ] dip ] dip
48 [ cursor-write ] 2curry when ; inline
50 : cursor-filter-quot ( quot to -- quot' )
51 [ cursor-write-if ] 2curry ; inline
53 : cursor-filter ( from to quot -- )
54 swap cursor-filter-quot cursor-each ; inline
56 TUPLE: from-sequence { seq sequence } { n integer } ;
58 : >from-sequence< ( from-sequence -- n seq )
59 [ n>> ] [ seq>> ] bi ; inline
61 M: from-sequence cursor-done? ( cursor -- ? )
62 >from-sequence< length >= ;
64 M: from-sequence cursor-valid?
65 >from-sequence< bounds-check? not ;
67 M: from-sequence cursor-get-unsafe
68 >from-sequence< nth-unsafe ;
70 M: from-sequence cursor-advance
71 [ 1 + ] change-n drop ;
73 : >input ( seq -- cursor )
74 0 from-sequence boa ; inline
76 : iterate ( seq quot iterator -- )
77 [ >input ] 2dip call ; inline
79 : each ( seq quot -- ) [ cursor-each ] iterate ; inline
80 : find ( seq quot -- ? ) [ cursor-find ] iterate ; inline
81 : any? ( seq quot -- ? ) [ cursor-any? ] iterate ; inline
82 : all? ( seq quot -- ? ) [ cursor-all? ] iterate ; inline
84 TUPLE: to-sequence { seq sequence } { exemplar sequence } ;
86 M: to-sequence cursor-write
89 : freeze ( cursor -- seq )
90 [ seq>> ] [ exemplar>> ] bi like ; inline
92 : >output ( seq -- cursor )
93 [ [ length ] keep new-resizable ] keep
94 to-sequence boa ; inline
96 : transform ( seq quot transformer -- newseq )
97 [ [ >input ] [ >output ] bi ] 2dip
99 [ 2drop freeze ] 3bi ; inline
101 : map ( seq quot -- ) [ cursor-map ] transform ; inline
102 : filter ( seq quot -- newseq ) [ cursor-filter ] transform ; inline
104 : find-done2? ( cursor cursor quot -- ? )
105 2over [ cursor-done? ] either?
106 [ 3drop t ] [ [ [ cursor-get-unsafe ] bi@ ] dip call ] if ; inline
108 : cursor-until2 ( cursor cursor quot -- )
110 [ drop [ cursor-advance ] bi@ ] bi-curry bi-curry bi-curry while ; inline
112 : cursor-each2 ( cursor cursor quot -- )
113 [ f ] compose cursor-until2 ; inline
115 : cursor-map2 ( from to quot -- )
116 swap cursor-map-quot cursor-each2 ; inline
118 : iterate2 ( seq1 seq2 quot iterator -- )
119 [ [ >input ] bi@ ] 2dip call ; inline
121 : transform2 ( seq1 seq2 quot transformer -- newseq )
122 [ over >output [ [ >input ] [ >input ] bi* ] dip ] 2dip
124 [ 2drop nip freeze ] 4 nbi ; inline
126 : 2each ( seq1 seq2 quot -- ) [ cursor-each2 ] iterate2 ; inline
127 : 2map ( seq1 seq2 quot -- ) [ cursor-map2 ] transform2 ; inline
129 : find-done3? ( cursor1 cursor2 cursor3 quot -- ? )
130 [ 3 ndrop t ] swap '[ [ cursor-get-unsafe ] tri@ @ ]
131 [ 3 ndup 3 narray [ cursor-done? ] any? ] 2dip if ; inline
133 : cursor-until3 ( cursor cursor quot -- )
135 [ drop [ cursor-advance ] tri@ ]
136 bi-curry bi-curry bi-curry bi-curry while ; inline
138 : cursor-each3 ( cursor cursor quot -- )
139 [ f ] compose cursor-until3 ; inline
141 : cursor-map3 ( from to quot -- )
142 swap cursor-map-quot cursor-each3 ; inline
144 : iterate3 ( seq1 seq2 seq3 quot iterator -- )
145 [ [ >input ] tri@ ] 2dip call ; inline
147 : transform3 ( seq1 seq2 seq3 quot transformer -- newseq )
148 [ pick >output [ [ >input ] [ >input ] [ >input ] tri* ] dip ] 2dip
150 [ 2drop 2nip freeze ] 5 nbi ; inline
152 : 3each ( seq1 seq2 seq3 quot -- ) [ cursor-each3 ] iterate3 ; inline
153 : 3map ( seq1 seq2 seq3 quot -- ) [ cursor-map3 ] transform3 ; inline