1 ! Copyright (C) 2009 Slava Pestov, Eduardo Cavazos, Joe Groff.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators kernel locals.backend math
4 quotations sequences sets splitting vectors words ;
11 ERROR: >r/r>-in-fry-error ;
13 GENERIC: fry ( object -- quot )
17 : check-fry ( quot -- quot )
18 dup { load-local load-locals get-local drop-locals } intersect
19 [ >r/r>-in-fry-error ] unless-empty ;
21 PREDICATE: fry-specifier < word { POSTPONE: _ POSTPONE: @ } member-eq? ;
23 GENERIC: count-inputs ( quot -- n )
25 M: sequence count-inputs [ count-inputs ] map-sum ;
26 M: fry-specifier count-inputs drop 1 ;
27 M: object count-inputs drop 0 ;
30 PREDICATE: fried-sequence < sequence count-inputs 0 > ;
31 INSTANCE: fried-sequence fried
33 : (ncurry) ( accum n -- accum )
36 { 1 [ \ curry suffix! ] }
37 { 2 [ \ 2curry suffix! ] }
38 { 3 [ \ 3curry suffix! ] }
39 [ [ \ 3curry suffix! ] dip 3 - (ncurry) ]
42 : wrap-non-callable ( obj -- quot )
43 dup callable? [ ] [ [ call ] curry ] if ; inline
45 : [ncurry] ( n -- quot )
46 [ V{ } clone ] dip (ncurry) >quotation ;
48 : [ndip] ( quot n -- quot' )
50 { 0 [ wrap-non-callable ] }
51 { 1 [ \ dip [ ] 2sequence ] }
52 { 2 [ \ 2dip [ ] 2sequence ] }
53 { 3 [ \ 3dip [ ] 2sequence ] }
54 [ [ \ 3dip [ ] 2sequence ] dip 3 - [ndip] ]
57 : (make-curry) ( tail quot -- quot' )
58 swap [ncurry] curry [ compose ] compose ;
60 : make-compose ( consecutive quot -- consecutive' quot' )
61 [ [ [ ] ] [ [ncurry] ] if-zero ]
62 [ [ [ compose ] ] [ [ compose compose ] curry ] if-empty ]
65 : make-curry ( consecutive quot -- consecutive' quot' )
66 [ 1 + ] dip [ [ ] ] [ (make-curry) 0 swap ] if-empty ;
68 : convert-curry ( consecutive quot -- consecutive' quot' )
71 [ rest >quotation make-compose ]
72 [ >quotation make-curry ] if
75 : prune-curries ( seq -- seq' )
76 dup [ empty? not ] find
77 [ [ 1 + tail ] dip but-last prefix ] [ 2drop { } ] if* ;
79 : convert-curries ( seq -- tail seq' )
80 unclip-slice [ 0 swap [ convert-curry ] map ] dip
81 [ prune-curries ] [ >quotation 1quotation prefix ] if-empty ;
83 : mark-composes ( quot -- quot' )
86 drop [ POSTPONE: _ POSTPONE: @ ]
92 : shallow-fry ( quot -- quot' )
93 check-fry mark-composes
94 { POSTPONE: _ } split convert-curries
95 [ [ [ ] ] [ [ ] (make-curry) but-last ] if-zero ]
96 [ shallow-spread>quot swap [ [ ] (make-curry) compose ] unless-zero ] if-empty ;
98 TUPLE: dredge-fry-state
99 { input sequence read-only }
100 { prequot vector read-only }
101 { quot vector read-only } ;
103 : <dredge-fry> ( quot -- dredge-fry )
104 V{ } clone V{ } clone dredge-fry-state boa ; inline
106 : input-slices ( n i state -- head tail )
107 input>> [ <slice> ] [ spin drop 1 + tail-slice ] 3bi ; inline
109 : push-head-slice ( head state -- )
110 quot>> [ push-all ] [ \ _ swap push ] bi ; inline
112 : push-subquot ( tail elt state -- )
113 [ fry swap count-inputs [ndip] ] dip prequot>> push-all ; inline
117 : dredge-fry-subquot ( n state i elt -- )
119 [ nip input-slices ] ! head tail i elt state
120 [ [ 2drop swap ] dip push-head-slice ]
121 [ nipd push-subquot ]
122 [ [ drop 1 + ] dip dredge-fry ]
123 } 3cleave ; inline recursive
125 : dredge-fry-simple ( n state -- )
126 [ input>> swap tail-slice ] [ quot>> ] bi push-all ; inline recursive
128 : dredge-fry ( n dredge-fry -- )
129 2dup input>> [ fried? ] find-from
130 [ dredge-fry-subquot ]
131 [ drop dredge-fry-simple ] if* ; inline recursive
133 : (fry) ( sequence -- quot )
135 [ 0 swap dredge-fry ]
136 [ prequot>> >quotation ]
137 [ quot>> >quotation shallow-fry ] tri append ;
142 [ [ [ ] ] ] [ (fry) ] if-empty ;
145 [ 0 swap new-sequence ] keep
146 [ 1quotation ] [ (fry) swap [ like ] curry append ] if-empty ;