Merge branch 'row-polymorphism' of git://factorcode.org/git/factor into row-polymorphism
commit
a926576993
|
@ -42,7 +42,7 @@ M: ##branch linearize-insn
|
|||
|
||||
: successors ( bb -- first second ) successors>> first2 ; inline
|
||||
|
||||
:: conditional ( bb insn n conditional-quot negate-cc-quot -- bb successor label ... )
|
||||
:: conditional ( bb insn n conditional-quot negate-cc-quot -- bb successor label etc... )
|
||||
bb insn
|
||||
conditional-quot
|
||||
[ drop dup successors>> second useless-branch? ] 2bi
|
||||
|
|
|
@ -48,7 +48,7 @@ M: +unknown+ curry-effect ;
|
|||
M: effect curry-effect
|
||||
[ in>> length ] [ out>> length ] [ terminated?>> ] tri
|
||||
pick 0 = [ [ 1 + ] dip ] [ [ 1 - ] 2dip ] if
|
||||
[ [ "x" <array> ] bi@ ] dip effect boa ;
|
||||
[ [ "x" <array> ] bi@ ] dip <terminated-effect> ;
|
||||
|
||||
M: curry cached-effect
|
||||
quot>> cached-effect curry-effect ;
|
||||
|
|
|
@ -252,17 +252,17 @@ HELP: spread*
|
|||
{ $notes "This word can be used with " { $link apply-curry } " to generalize the " { $snippet "bi-curry@ bi*" } " or " { $snippet "tri-curry@ tri*" } " dataflow patterns." } ;
|
||||
|
||||
HELP: apply-curry
|
||||
{ $values { "...a" { $snippet "n" } " values on the datastack" } { "quot" quotation } { "n" integer } }
|
||||
{ $values { "a..." { $snippet "n" } " values on the datastack" } { "quot" quotation } { "n" integer } }
|
||||
{ $description "Curries each of the top " { $snippet "n" } " items of the datastack onto " { $snippet "quot" } ", leaving " { $snippet "n" } " quotations on the datastack. A generalization of " { $link bi-curry@ } " and " { $link tri-curry@ } "." }
|
||||
{ $notes "This word can be used with " { $link cleave* } " and " { $link spread* } " to generalize dataflow patterns such as " { $snippet "bi-curry@ bi" } ", " { $snippet "tri-curry@ tri" } ", " { $snippet "bi-curry@ bi*" } ", and " { $snippet "tri-curry@ tri*" } "." } ;
|
||||
|
||||
HELP: cleave-curry
|
||||
{ $values { "a" object } { "...quot" { $snippet "n" } " quotations on the datastack" } { "n" integer } }
|
||||
{ $values { "a" object } { "quot..." { $snippet "n" } " quotations on the datastack" } { "n" integer } }
|
||||
{ $description "Curries " { $snippet "a" } " onto the " { $snippet "n" } " quotations on the top of the datastack. A generalization of " { $link bi-curry } " and " { $link tri-curry } "." }
|
||||
{ $notes "This word can be used with " { $link cleave* } " and " { $link spread* } " to generalize dataflow patterns such as " { $snippet "bi-curry bi" } ", " { $snippet "tri-curry tri" } ", " { $snippet "bi-curry bi*" } ", and " { $snippet "tri-curry tri*" } "." } ;
|
||||
|
||||
HELP: spread-curry
|
||||
{ $values { "...a" { $snippet "n" } " objects on the datastack" } { "...quot" { $snippet "n" } " quotations on the datastack" } { "n" integer } }
|
||||
{ $values { "a..." { $snippet "n" } " objects on the datastack" } { "quot..." { $snippet "n" } " quotations on the datastack" } { "n" integer } }
|
||||
{ $description "Curries the " { $snippet "n" } " quotations on the top of the datastack with the " { $snippet "n" } " values just below them. A generalization of " { $link bi-curry* } " and " { $link tri-curry* } "." }
|
||||
{ $notes "This word can be used with " { $link cleave* } " and " { $link spread* } " to generalize dataflow patterns such as " { $snippet "bi-curry* bi" } ", " { $snippet "tri-curry* tri" } ", " { $snippet "bi-curry* bi*" } ", and " { $snippet "tri-curry* tri*" } "." } ;
|
||||
|
||||
|
|
|
@ -125,13 +125,13 @@ MACRO: cleave* ( n -- )
|
|||
: mnapply ( quot m n -- )
|
||||
[ nip dupn ] [ nspread* ] 2bi ; inline
|
||||
|
||||
: apply-curry ( ...a quot n -- )
|
||||
: apply-curry ( a... quot n -- )
|
||||
[ [curry] ] dip napply ; inline
|
||||
|
||||
: cleave-curry ( a ...quot n -- )
|
||||
: cleave-curry ( a quot... n -- )
|
||||
[ [curry] ] swap [ napply ] [ cleave* ] bi ; inline
|
||||
|
||||
: spread-curry ( ...a ...quot n -- )
|
||||
: spread-curry ( a... quot... n -- )
|
||||
[ [curry] ] swap [ napply ] [ spread* ] bi ; inline
|
||||
|
||||
MACRO: mnswap ( m n -- )
|
||||
|
|
|
@ -4,15 +4,15 @@ math arrays combinators ;
|
|||
IN: sequences.generalizations
|
||||
|
||||
HELP: neach
|
||||
{ $values { "...seq" { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- )" } } { "n" integer } }
|
||||
{ $values { "seq..." { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( element... -- )" } } { "n" integer } }
|
||||
{ $description "A generalization of " { $link each } ", " { $link 2each } ", and " { $link 3each } " that can iterate over any number of sequences in parallel." } ;
|
||||
|
||||
HELP: nmap
|
||||
{ $values { "...seq" { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- result )" } } { "n" integer } { "result" "a sequence of the same type as the first " { $snippet "seq" } } }
|
||||
{ $values { "seq..." { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( element... -- result )" } } { "n" integer } { "result" "a sequence of the same type as the first " { $snippet "seq" } } }
|
||||
{ $description "A generalization of " { $link map } ", " { $link 2map } ", and " { $link 3map } " that can map over any number of sequences in parallel." } ;
|
||||
|
||||
HELP: nmap-as
|
||||
{ $values { "...seq" { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( ...element -- result )" } } { "exemplar" sequence } { "n" integer } { "result" "a sequence of the same type as " { $snippet "exemplar" } } }
|
||||
{ $values { "seq..." { $snippet "n" } " sequences on the datastack" } { "quot" "a quotation with stack effect " { $snippet "( element... -- result )" } } { "exemplar" sequence } { "n" integer } { "result" "a sequence of the same type as " { $snippet "exemplar" } } }
|
||||
{ $description "A generalization of " { $link map-as } ", " { $link 2map-as } ", and " { $link 3map-as } " that can map over any number of sequences in parallel." } ;
|
||||
|
||||
HELP: mnmap
|
||||
|
@ -28,7 +28,7 @@ HELP: nproduce
|
|||
{ $description "A generalization of " { $link produce } " that generates " { $snippet "n" } " arrays in parallel by calling " { $snippet "quot" } " repeatedly until " { $snippet "pred" } " outputs false." } ;
|
||||
|
||||
HELP: nproduce-as
|
||||
{ $values { "pred" { $quotation "( -- ? )" } } { "quot" { $quotation "( -- obj1 obj2 ... objn )" } } { "...exemplar" { $snippet "n" } " sequences on the datastack" } { "n" integer } { "seq..." { $snippet "n" } " sequences on the datastack of the same types as the " { $snippet "exemplar" } "s" } }
|
||||
{ $values { "pred" { $quotation "( -- ? )" } } { "quot" { $quotation "( -- obj1 obj2 ... objn )" } } { "exemplar..." { $snippet "n" } " sequences on the datastack" } { "n" integer } { "seq..." { $snippet "n" } " sequences on the datastack of the same types as the " { $snippet "exemplar" } "s" } }
|
||||
{ $description "A generalization of " { $link produce-as } " that generates " { $snippet "n" } " sequences in parallel by calling " { $snippet "quot" } " repeatedly until " { $snippet "pred" } " outputs false." } ;
|
||||
|
||||
ARTICLE: "sequences.generalizations" "Generalized sequence iteration combinators"
|
||||
|
|
|
@ -8,31 +8,31 @@ MACRO: nmin-length ( n -- )
|
|||
dup 1 - [ min ] n*quot
|
||||
'[ [ length ] _ napply @ ] ;
|
||||
|
||||
: nnth-unsafe ( n ...seq n -- )
|
||||
: nnth-unsafe ( n seq... n -- )
|
||||
[ nth-unsafe ] swap [ apply-curry ] [ cleave* ] bi ; inline
|
||||
MACRO: nset-nth-unsafe ( n -- )
|
||||
[ [ drop ] ]
|
||||
[ '[ [ set-nth-unsafe ] _ [ apply-curry ] [ cleave-curry ] [ spread* ] tri ] ]
|
||||
if-zero ;
|
||||
|
||||
: (neach) ( ...seq quot n -- len quot' )
|
||||
: (neach) ( seq... quot n -- len quot' )
|
||||
dup dup dup
|
||||
'[ [ _ nmin-length ] _ nkeep [ _ nnth-unsafe ] _ ncurry ] dip compose ; inline
|
||||
|
||||
: neach ( ...seq quot n -- )
|
||||
: neach ( seq... quot n -- )
|
||||
(neach) each-integer ; inline
|
||||
|
||||
: nmap-as ( ...seq quot exemplar n -- result )
|
||||
: nmap-as ( seq... quot exemplar n -- result )
|
||||
'[ _ (neach) ] dip map-integers ; inline
|
||||
|
||||
: nmap ( ...seq quot n -- result )
|
||||
: nmap ( seq... quot n -- result )
|
||||
dup '[ [ _ npick ] dip swap ] dip nmap-as ; inline
|
||||
|
||||
MACRO: nnew-sequence ( n -- )
|
||||
[ [ drop ] ]
|
||||
[ dup '[ [ new-sequence ] _ apply-curry _ cleave* ] ] if-zero ;
|
||||
|
||||
: nnew-like ( len ...exemplar quot n -- result... )
|
||||
: nnew-like ( len exemplar... quot n -- result... )
|
||||
5 dupn '[
|
||||
_ nover
|
||||
[ [ _ nnew-sequence ] dip call ]
|
||||
|
@ -45,10 +45,10 @@ MACRO: (ncollect) ( n -- )
|
|||
3 dupn 1 +
|
||||
'[ [ [ keep ] _ ndip _ nset-nth-unsafe ] _ ncurry ] ;
|
||||
|
||||
: ncollect ( len quot ...into n -- )
|
||||
: ncollect ( len quot into... n -- )
|
||||
(ncollect) each-integer ; inline
|
||||
|
||||
: nmap-integers ( len quot ...exemplar n -- result... )
|
||||
: nmap-integers ( len quot exemplar... n -- result... )
|
||||
4 dupn
|
||||
'[ [ over ] _ ndip [ [ _ ncollect ] _ nkeep ] _ nnew-like ] call ; inline
|
||||
|
||||
|
@ -58,7 +58,7 @@ MACRO: (ncollect) ( n -- )
|
|||
: mnmap ( m*seq quot m n -- result*n )
|
||||
2dup '[ [ _ npick ] dip swap _ dupn ] 2dip mnmap-as ; inline
|
||||
|
||||
: ncollector-for ( quot ...exemplar n -- quot' vec... )
|
||||
: ncollector-for ( quot exemplar... n -- quot' vec... )
|
||||
5 dupn '[
|
||||
[ [ length ] keep new-resizable ] _ napply
|
||||
[ [ [ push ] _ apply-curry _ spread* ] _ ncurry compose ] _ nkeep
|
||||
|
@ -67,7 +67,7 @@ MACRO: (ncollect) ( n -- )
|
|||
: ncollector ( quot n -- quot' vec... )
|
||||
[ V{ } swap dupn ] keep ncollector-for ; inline
|
||||
|
||||
: nproduce-as ( pred quot ...exemplar n -- seq... )
|
||||
: nproduce-as ( pred quot exemplar... n -- seq... )
|
||||
7 dupn '[
|
||||
_ ndup
|
||||
[ _ ncollector-for [ while ] _ ndip ]
|
||||
|
|
|
@ -157,3 +157,6 @@ M: bad-call summary
|
|||
current-effect
|
||||
stack-visitor get
|
||||
] with-scope ; inline
|
||||
|
||||
: (infer) ( quot -- effect )
|
||||
[ infer-quot-here ] with-infer drop ;
|
||||
|
|
|
@ -32,4 +32,11 @@ ERROR: inconsistent-recursive-call-error < inference-error word ;
|
|||
|
||||
ERROR: transform-expansion-error < inference-error error continuation word ;
|
||||
|
||||
ERROR: bad-declaration-error < inference-error declaration ;
|
||||
ERROR: bad-declaration-error < inference-error declaration ;
|
||||
|
||||
ERROR: invalid-quotation-input < inference-error word branches quots ;
|
||||
|
||||
ERROR: invalid-effect-variable < inference-error effect ;
|
||||
|
||||
ERROR: effect-variable-can't-have-type < inference-error effect ;
|
||||
|
||||
|
|
|
@ -13,10 +13,13 @@ M: bad-macro-input summary
|
|||
M: unbalanced-branches-error summary
|
||||
drop "Unbalanced branches" ;
|
||||
|
||||
: quots-and-branches. ( quots branches -- )
|
||||
zip [ [ first pprint-short bl ] [ second effect>string print ] bi ] each ;
|
||||
|
||||
M: unbalanced-branches-error error.
|
||||
dup summary print
|
||||
[ quots>> ] [ branches>> [ length [ "x" <array> ] bi@ <effect> ] { } assoc>map ] bi zip
|
||||
[ [ first pprint-short bl ] [ second effect>string print ] bi ] each ;
|
||||
[ quots>> ] [ branches>> [ length [ "x" <array> ] bi@ <effect> ] { } assoc>map ] bi
|
||||
quots-and-branches. ;
|
||||
|
||||
M: too-many->r summary
|
||||
drop "Quotation pushes elements on retain stack without popping them" ;
|
||||
|
@ -60,4 +63,18 @@ M: transform-expansion-error error.
|
|||
tri ;
|
||||
|
||||
M: do-not-compile summary
|
||||
word>> name>> "Cannot compile call to " prepend ;
|
||||
word>> name>> "Cannot compile call to " prepend ;
|
||||
|
||||
M: invalid-quotation-input summary
|
||||
word>> name>>
|
||||
"The input quotations to " " don't match their expected effects" surround ;
|
||||
|
||||
M: invalid-quotation-input error.
|
||||
dup summary print
|
||||
[ quots>> ] [ branches>> ] bi quots-and-branches. ;
|
||||
|
||||
M: invalid-effect-variable summary
|
||||
drop "Stack effect variables can only occur as the first input or output" ;
|
||||
M: effect-variable-can't-have-type summary
|
||||
drop "Stack effect variables cannot have a declared type" ;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ stack-checker.backend
|
|||
stack-checker.branches
|
||||
stack-checker.known-words
|
||||
stack-checker.dependencies
|
||||
stack-checker.row-polymorphism
|
||||
stack-checker.recursive-state ;
|
||||
IN: stack-checker.inlining
|
||||
|
||||
|
@ -141,6 +142,7 @@ SYMBOL: enter-out
|
|||
: inline-word ( word -- )
|
||||
commit-literals
|
||||
[ depends-on-definition ]
|
||||
[ infer-polymorphic? get [ check-polymorphic-effect ] [ drop ] if ]
|
||||
[
|
||||
dup inline-recursive-label [
|
||||
call-recursive-inline-word
|
||||
|
@ -150,7 +152,7 @@ SYMBOL: enter-out
|
|||
[ dup infer-inline-word-def ]
|
||||
if
|
||||
] if*
|
||||
] bi ;
|
||||
] tri ;
|
||||
|
||||
M: word apply-object
|
||||
dup inline? [ inline-word ] [ non-inline-word ] if ;
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
! (c)2010 Joe Groff bsd license
|
||||
USING: effects fry io kernel math namespaces sequences
|
||||
system tools.test
|
||||
stack-checker.backend
|
||||
stack-checker.errors
|
||||
stack-checker.row-polymorphism
|
||||
stack-checker.state
|
||||
stack-checker.values ;
|
||||
IN: stack-checker.row-polymorphism.tests
|
||||
|
||||
: infer-polymorphic-quot ( quot -- vars )
|
||||
t infer-polymorphic? [
|
||||
unclip-last [
|
||||
dup current-word set
|
||||
init-inference
|
||||
init-known-values
|
||||
[ [ <literal> <value> [ set-known ] [ push-d ] bi ] each ]
|
||||
[ stack-effect ] bi*
|
||||
infer-polymorphic-vars
|
||||
] with-scope
|
||||
] with-variable ;
|
||||
|
||||
: test-poly-infer ( effect quot -- )
|
||||
[ '[ _ ] ] [ '[ _ infer-polymorphic-quot ] ] bi* unit-test ; inline
|
||||
|
||||
: poly-infer-must-fail ( quot -- )
|
||||
'[ _ infer-polymorphic-quot ] [ invalid-quotation-input? ] must-fail-with ; inline
|
||||
: poly-infer-must-fail-unknown ( quot -- )
|
||||
'[ _ infer-polymorphic-quot ] [ unknown-macro-input? ] must-fail-with ; inline
|
||||
|
||||
H{ { "." 0 } } [ [ write ] each ] test-poly-infer
|
||||
H{ { "." 1 } } [ [ append ] each ] test-poly-infer
|
||||
H{ { "." 0 } } [ [ ] map ] test-poly-infer
|
||||
H{ { "." 0 } } [ [ reverse ] map ] test-poly-infer
|
||||
H{ { "." 1 } } [ [ append dup ] map ] test-poly-infer
|
||||
H{ { "." 1 } } [ [ swap nth suffix dup ] map-index ] test-poly-infer
|
||||
|
||||
H{ { "a" 3 } { "b" 1 } } [ [ 2drop ] [ 2nip ] if ] test-poly-infer
|
||||
H{ { "a" 2 } { "b" 3 } } [ [ dup ] [ over ] if ] test-poly-infer
|
||||
H{ { "a" 0 } { "b" 1 } } [ [ os ] [ cpu ] if ] test-poly-infer
|
||||
H{ { "a" 1 } { "b" 2 } } [ [ os ] [ 1 + cpu ] if ] test-poly-infer
|
||||
|
||||
H{ { "a" 0 } { "b" 0 } } [ [ write ] [ "(f)" write ] if* ] test-poly-infer
|
||||
H{ { "a" 0 } { "b" 1 } } [ [ ] [ f ] if* ] test-poly-infer
|
||||
H{ { "a" 1 } { "b" 1 } } [ [ nip ] [ drop f ] if* ] test-poly-infer
|
||||
H{ { "a" 1 } { "b" 1 } } [ [ nip ] [ ] if* ] test-poly-infer
|
||||
H{ { "a" 2 } { "b" 2 } } [ [ 3append f ] [ ] if* ] test-poly-infer
|
||||
H{ { "a" 0 } { "b" 0 } } [ [ drop ] [ ] if* ] test-poly-infer
|
||||
|
||||
[ [ write write ] each ] poly-infer-must-fail
|
||||
[ [ ] each ] poly-infer-must-fail
|
||||
[ [ dup ] map ] poly-infer-must-fail
|
||||
[ [ drop ] map ] poly-infer-must-fail
|
||||
[ [ 1 + ] map-index ] poly-infer-must-fail
|
||||
|
||||
[ [ dup ] [ ] if ] poly-infer-must-fail
|
||||
[ [ 2dup ] [ over ] if ] poly-infer-must-fail
|
||||
[ [ drop ] [ ] if ] poly-infer-must-fail
|
||||
|
||||
[ [ ] [ ] if* ] poly-infer-must-fail
|
||||
[ [ dup ] [ ] if* ] poly-infer-must-fail
|
||||
[ [ drop ] [ drop ] if* ] poly-infer-must-fail
|
||||
[ [ ] [ drop ] if* ] poly-infer-must-fail
|
||||
[ [ ] [ 2dup ] if* ] poly-infer-must-fail
|
||||
|
||||
[ "derp" each ] poly-infer-must-fail
|
||||
[ each ] poly-infer-must-fail-unknown
|
||||
[ "derp" [ "derp" ] if ] poly-infer-must-fail
|
||||
[ [ "derp" ] "derp" if ] poly-infer-must-fail
|
||||
[ [ "derp" ] if ] poly-infer-must-fail-unknown
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
! (c)2010 Joe Groff bsd license
|
||||
USING: accessors arrays assocs combinators combinators.short-circuit
|
||||
continuations effects fry kernel locals math namespaces
|
||||
quotations sequences splitting
|
||||
stack-checker.backend
|
||||
stack-checker.errors
|
||||
stack-checker.known-words
|
||||
stack-checker.state
|
||||
stack-checker.values
|
||||
stack-checker.visitor ;
|
||||
IN: stack-checker.row-polymorphism
|
||||
|
||||
<PRIVATE
|
||||
SYMBOLS: current-effect-variables current-word-effect current-meta-d ;
|
||||
|
||||
: quotation-effect? ( in -- ? )
|
||||
dup pair? [ second effect? ] [ drop f ] if ;
|
||||
|
||||
SYMBOL: (unknown)
|
||||
|
||||
GENERIC: >error-quot ( known -- quot )
|
||||
|
||||
M: object >error-quot drop (unknown) ;
|
||||
M: literal >error-quot value>> ;
|
||||
M: composed >error-quot
|
||||
[ quot1>> known >error-quot ] [ quot2>> known >error-quot ] bi
|
||||
\ compose [ ] 3sequence ;
|
||||
M: curried >error-quot
|
||||
[ obj>> known >error-quot ] [ quot>> known >error-quot ] bi
|
||||
\ curry [ ] 3sequence ;
|
||||
|
||||
: >error-branches-and-quots ( branch/values -- branches quots )
|
||||
[ [ second ] [ known >error-quot ] bi* ] assoc-map unzip ;
|
||||
|
||||
: abandon-check ( -- * )
|
||||
current-word get
|
||||
current-word-effect get in>> current-meta-d get zip
|
||||
[ first quotation-effect? ] filter
|
||||
>error-branches-and-quots
|
||||
invalid-quotation-input ;
|
||||
|
||||
:: check-variable ( actual-count declared-count variable -- difference )
|
||||
actual-count declared-count -
|
||||
variable [
|
||||
variable current-effect-variables get at* nip
|
||||
[ variable current-effect-variables get at - ]
|
||||
[ variable current-effect-variables get set-at 0 ] if
|
||||
] [
|
||||
dup [ abandon-check ] unless-zero
|
||||
] if ;
|
||||
|
||||
: adjust-variable ( diff var -- )
|
||||
over 0 >=
|
||||
[ current-effect-variables get at+ ]
|
||||
[ 2drop ] if ; inline
|
||||
|
||||
:: (check-input) ( declared actual -- )
|
||||
actual declared [ in>> length ] bi@ declared in-var>>
|
||||
[ check-variable ] keep :> ( in-diff in-var )
|
||||
actual declared [ out>> length ] bi@ declared out-var>>
|
||||
[ check-variable ] keep :> ( out-diff out-var )
|
||||
{ [ in-var not ] [ out-var not ] [ in-diff out-diff = ] } 0||
|
||||
[
|
||||
in-var [ in-diff swap adjust-variable ] when*
|
||||
out-var [ out-diff swap adjust-variable ] when*
|
||||
] [
|
||||
abandon-check
|
||||
] if ;
|
||||
|
||||
: infer-value ( value -- effect )
|
||||
dup known [ nest-visitor init-inference infer-call* current-effect ] with-scope ; inline
|
||||
|
||||
: check-input ( in value -- )
|
||||
over quotation-effect? [
|
||||
[ second ] dip infer-value (check-input)
|
||||
] [ 2drop ] if ;
|
||||
|
||||
: normalize-variables ( -- variables' )
|
||||
current-effect-variables get dup values [
|
||||
infimum dup 0 <
|
||||
[ '[ _ - ] assoc-map ] [ drop ] if
|
||||
] unless-empty ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: infer-polymorphic-vars ( effect -- variables )
|
||||
H{ } clone current-effect-variables set
|
||||
dup current-word-effect set
|
||||
in>> dup length ensure-d dup current-meta-d set
|
||||
[ check-input ] 2each
|
||||
normalize-variables ;
|
||||
|
||||
: check-polymorphic-effect ( word -- )
|
||||
current-word get [
|
||||
dup current-word set stack-effect
|
||||
dup { [ in-var>> ] [ out-var>> ] } 1||
|
||||
[ infer-polymorphic-vars ] when drop
|
||||
] dip current-word set ;
|
||||
|
||||
SYMBOL: infer-polymorphic?
|
|
@ -11,7 +11,7 @@ IN: stack-checker
|
|||
GENERIC: infer ( quot -- effect )
|
||||
|
||||
M: callable infer ( quot -- effect )
|
||||
[ infer-quot-here ] with-infer drop ;
|
||||
(infer) ;
|
||||
|
||||
: infer. ( quot -- )
|
||||
#! Safe to call from inference transforms.
|
||||
|
|
|
@ -40,7 +40,7 @@ SYMBOL: literals
|
|||
: current-effect ( -- effect )
|
||||
input-count get "x" <array>
|
||||
meta-d length "x" <array>
|
||||
terminated? get effect boa ;
|
||||
terminated? get <terminated-effect> ;
|
||||
|
||||
: init-inference ( -- )
|
||||
terminated? off
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
USING: effects kernel tools.test prettyprint accessors
|
||||
USING: effects effects.parser eval kernel tools.test prettyprint accessors
|
||||
quotations sequences ;
|
||||
IN: effects.tests
|
||||
|
||||
|
@ -27,3 +27,18 @@ IN: effects.tests
|
|||
|
||||
[ { object object } ] [ (( a b -- )) effect-in-types ] unit-test
|
||||
[ { object sequence } ] [ (( a b: sequence -- )) effect-in-types ] unit-test
|
||||
|
||||
[ f ] [ (( a b c -- d )) in-var>> ] unit-test
|
||||
[ f ] [ (( -- d )) in-var>> ] unit-test
|
||||
[ "a" ] [ (( ..a b c -- d )) in-var>> ] unit-test
|
||||
[ { "b" "c" } ] [ (( ..a b c -- d )) in>> ] unit-test
|
||||
|
||||
[ f ] [ (( ..a b c -- e )) out-var>> ] unit-test
|
||||
[ "d" ] [ (( ..a b c -- ..d e )) out-var>> ] unit-test
|
||||
[ { "e" } ] [ (( ..a b c -- ..d e )) out>> ] unit-test
|
||||
|
||||
[ "(( a ..b c -- d ))" eval( -- effect ) ]
|
||||
[ error>> invalid-effect-variable? ] must-fail-with
|
||||
|
||||
[ "(( ..a: integer b c -- d ))" eval( -- effect ) ]
|
||||
[ error>> effect-variable-can't-have-type? ] must-fail-with
|
||||
|
|
|
@ -8,11 +8,21 @@ IN: effects
|
|||
TUPLE: effect
|
||||
{ in array read-only }
|
||||
{ out array read-only }
|
||||
{ terminated? read-only } ;
|
||||
{ terminated? read-only }
|
||||
{ in-var read-only }
|
||||
{ out-var read-only } ;
|
||||
|
||||
: ?terminated ( out -- out terminated? )
|
||||
dup { "*" } = [ drop { } t ] [ f ] if ;
|
||||
|
||||
: <effect> ( in out -- effect )
|
||||
dup { "*" } = [ drop { } t ] [ f ] if
|
||||
effect boa ;
|
||||
?terminated f f effect boa ;
|
||||
|
||||
: <terminated-effect> ( in out terminated? -- effect )
|
||||
f f effect boa ; inline
|
||||
|
||||
: <variable-effect> ( in-var in out-var out -- effect )
|
||||
swap [ rot ] dip [ ?terminated ] 2dip effect boa ;
|
||||
|
||||
: effect-height ( effect -- n )
|
||||
[ out>> length ] [ in>> length ] bi - ; inline
|
||||
|
@ -42,13 +52,19 @@ M: pair effect>string first2 [ effect>string ] bi@ ": " glue ;
|
|||
: stack-picture ( seq -- string )
|
||||
[ [ effect>string % CHAR: \s , ] each ] "" make ;
|
||||
|
||||
: var-picture ( var -- string )
|
||||
[ ".." " " surround ]
|
||||
[ "" ] if* ;
|
||||
|
||||
M: effect effect>string ( effect -- string )
|
||||
[
|
||||
"( " %
|
||||
[ in>> stack-picture % "-- " % ]
|
||||
[ out>> stack-picture % ]
|
||||
[ terminated?>> [ "* " % ] when ]
|
||||
tri
|
||||
dup in-var>> var-picture %
|
||||
dup in>> stack-picture % "-- " %
|
||||
dup out-var>> var-picture %
|
||||
dup out>> stack-picture %
|
||||
dup terminated?>> [ "* " % ] when
|
||||
drop
|
||||
")" %
|
||||
] "" make ;
|
||||
|
||||
|
@ -87,7 +103,7 @@ M: effect clone
|
|||
shuffle-mapping swap nths ;
|
||||
|
||||
: add-effect-input ( effect -- effect' )
|
||||
[ in>> "obj" suffix ] [ out>> ] [ terminated?>> ] tri effect boa ;
|
||||
[ in>> "obj" suffix ] [ out>> ] [ terminated?>> ] tri <terminated-effect> ;
|
||||
|
||||
: compose-effects ( effect1 effect2 -- effect' )
|
||||
over terminated?>> [
|
||||
|
@ -97,5 +113,5 @@ M: effect clone
|
|||
[ [ out>> length ] [ [ in>> length ] [ out>> length ] bi ] bi* [ [-] ] dip + ]
|
||||
[ nip terminated?>> ] 2tri
|
||||
[ [ "x" <array> ] bi@ ] dip
|
||||
effect boa
|
||||
<terminated-effect>
|
||||
] if ; inline
|
||||
|
|
|
@ -1,34 +1,49 @@
|
|||
! Copyright (C) 2008, 2010 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: lexer sets sequences kernel splitting effects
|
||||
combinators arrays vocabs.parser classes parser ;
|
||||
combinators arrays make vocabs.parser classes parser ;
|
||||
IN: effects.parser
|
||||
|
||||
DEFER: parse-effect
|
||||
|
||||
ERROR: bad-effect ;
|
||||
ERROR: invalid-effect-variable ;
|
||||
ERROR: effect-variable-can't-have-type ;
|
||||
ERROR: stack-effect-omits-dashes ;
|
||||
|
||||
: parse-effect-token ( end -- token/f )
|
||||
scan [ nip ] [ = ] 2bi [ drop f ] [
|
||||
dup { f "(" "((" } member? [ bad-effect ] [
|
||||
":" ?tail [
|
||||
scan {
|
||||
{ [ dup "(" = ] [ drop ")" parse-effect ] }
|
||||
{ [ dup f = ] [ ")" unexpected-eof ] }
|
||||
[ parse-word dup class? [ bad-effect ] unless ]
|
||||
} cond 2array
|
||||
] when
|
||||
SYMBOL: effect-var
|
||||
|
||||
: parse-var ( first? var name -- var )
|
||||
nip
|
||||
[ ":" ?tail [ effect-variable-can't-have-type ] when ] curry
|
||||
[ invalid-effect-variable ] if ;
|
||||
|
||||
: parse-effect-token ( first? var end -- var more? )
|
||||
scan [ nip ] [ = ] 2bi [ drop nip f ] [
|
||||
dup { f "(" "((" "--" } member? [ bad-effect ] [
|
||||
dup { ")" "))" } member? [ stack-effect-omits-dashes ] [
|
||||
".." ?head [ parse-var t ] [
|
||||
[ drop ] 2dip
|
||||
":" ?tail [
|
||||
scan {
|
||||
{ [ dup "(" = ] [ drop ")" parse-effect ] }
|
||||
{ [ dup f = ] [ ")" unexpected-eof ] }
|
||||
[ parse-word dup class? [ bad-effect ] unless ]
|
||||
} cond 2array
|
||||
] when , t
|
||||
] if
|
||||
] if
|
||||
] if
|
||||
] if ;
|
||||
|
||||
: parse-effect-tokens ( end -- tokens )
|
||||
[ parse-effect-token dup ] curry [ ] produce nip ;
|
||||
|
||||
ERROR: stack-effect-omits-dashes tokens ;
|
||||
: parse-effect-tokens ( end -- var tokens )
|
||||
[
|
||||
[ t f ] dip [ parse-effect-token [ f ] 2dip ] curry [ ] while nip
|
||||
] { } make ;
|
||||
|
||||
: parse-effect ( end -- effect )
|
||||
parse-effect-tokens { "--" } split1 dup
|
||||
[ <effect> ] [ drop stack-effect-omits-dashes ] if ;
|
||||
[ "--" parse-effect-tokens ] dip parse-effect-tokens
|
||||
<variable-effect> ;
|
||||
|
||||
: complete-effect ( -- effect )
|
||||
"(" expect ")" parse-effect ;
|
||||
|
|
|
@ -29,7 +29,7 @@ DEFER: if
|
|||
#! two literal quotations.
|
||||
rot [ drop ] [ nip ] if ; inline
|
||||
|
||||
: if ( ? true false -- ) ? call ;
|
||||
: if ( ..a ? true: ( ..a -- ..b ) false: ( ..a -- ..b ) -- ..b ) ? call ;
|
||||
|
||||
! Single branch
|
||||
: unless ( ? false -- )
|
||||
|
@ -39,7 +39,7 @@ DEFER: if
|
|||
swap [ call ] [ drop ] if ; inline
|
||||
|
||||
! Anaphoric
|
||||
: if* ( ? true false -- )
|
||||
: if* ( ..a ? true: ( ..a ? -- ..b ) false: ( ..a -- ..b ) -- ..b )
|
||||
pick [ drop call ] [ 2nip call ] if ; inline
|
||||
|
||||
: when* ( ? true -- )
|
||||
|
@ -49,7 +49,7 @@ DEFER: if
|
|||
over [ drop ] [ nip call ] if ; inline
|
||||
|
||||
! Default
|
||||
: ?if ( default cond true false -- )
|
||||
: ?if ( ..a default cond true: ( ..a cond -- ..b ) false: ( ..a default -- ..b ) -- ..b )
|
||||
pick [ drop [ drop ] 2dip call ] [ 2nip call ] if ; inline
|
||||
|
||||
! Dippers.
|
||||
|
@ -171,16 +171,16 @@ UNION: boolean POSTPONE: t POSTPONE: f ;
|
|||
: most ( x y quot -- z ) 2keep ? ; inline
|
||||
|
||||
! Loops
|
||||
: loop ( pred: ( -- ? ) -- )
|
||||
: loop ( ... pred: ( ... -- ... ? ) -- ... )
|
||||
[ call ] keep [ loop ] curry when ; inline recursive
|
||||
|
||||
: do ( pred body -- pred body )
|
||||
dup 2dip ; inline
|
||||
|
||||
: while ( pred: ( -- ? ) body: ( -- ) -- )
|
||||
: while ( ... pred: ( ... -- ... ? ) body: ( ... -- ... ) -- ... )
|
||||
swap do compose [ loop ] curry when ; inline
|
||||
|
||||
: until ( pred: ( -- ? ) body: ( -- ) -- )
|
||||
: until ( ... pred: ( ... -- ... ? ) body: ( ... -- ... ) -- )
|
||||
[ [ not ] compose ] dip while ; inline
|
||||
|
||||
! Object protocol
|
||||
|
|
|
@ -77,7 +77,7 @@ ERROR: log2-expects-positive x ;
|
|||
: even? ( n -- ? ) 1 bitand zero? ;
|
||||
: odd? ( n -- ? ) 1 bitand 1 number= ;
|
||||
|
||||
: if-zero ( n quot1 quot2 -- )
|
||||
: if-zero ( ..a n quot1: ( ..a -- ..b ) quot2: ( ..a n -- ..b ) -- ..b )
|
||||
[ dup zero? ] [ [ drop ] prepose ] [ ] tri* if ; inline
|
||||
|
||||
: when-zero ( n quot -- ) [ ] if-zero ; inline
|
||||
|
@ -141,18 +141,18 @@ GENERIC: prev-float ( m -- n )
|
|||
|
||||
PRIVATE>
|
||||
|
||||
: (each-integer) ( i n quot: ( i -- ) -- )
|
||||
: (each-integer) ( ... i n quot: ( ... i -- ... ) -- ... )
|
||||
[ iterate-step iterate-next (each-integer) ]
|
||||
[ 3drop ] if-iterate? ; inline recursive
|
||||
|
||||
: (find-integer) ( i n quot: ( i -- ? ) -- i )
|
||||
: (find-integer) ( ... i n quot: ( ... i -- ... ? ) -- ... i )
|
||||
[
|
||||
iterate-step
|
||||
[ [ ] ] 2dip
|
||||
[ iterate-next (find-integer) ] 2curry bi-curry if
|
||||
] [ 3drop f ] if-iterate? ; inline recursive
|
||||
|
||||
: (all-integers?) ( i n quot: ( i -- ? ) -- ? )
|
||||
: (all-integers?) ( ... i n quot: ( ... i -- ... ? ) -- ... ? )
|
||||
[
|
||||
iterate-step
|
||||
[ iterate-next (all-integers?) ] 3curry
|
||||
|
@ -171,7 +171,7 @@ PRIVATE>
|
|||
: all-integers? ( n quot -- ? )
|
||||
iterate-prep (all-integers?) ; inline
|
||||
|
||||
: find-last-integer ( n quot: ( i -- ? ) -- i )
|
||||
: find-last-integer ( ... n quot: ( ... i -- ... ? ) -- ... i )
|
||||
over 0 < [
|
||||
2drop f
|
||||
] [
|
||||
|
|
|
@ -29,7 +29,7 @@ M: sequence shorten 2dup length < [ set-length ] [ 2drop ] if ; inline
|
|||
|
||||
: empty? ( seq -- ? ) length 0 = ; inline
|
||||
|
||||
: if-empty ( seq quot1 quot2 -- )
|
||||
: if-empty ( ..a seq quot1: ( ..a -- ..b ) quot2: ( ..a seq -- ..b ) -- ..b )
|
||||
[ dup empty? ] [ [ drop ] prepose ] [ ] tri* if ; inline
|
||||
|
||||
: when-empty ( seq quot -- ) [ ] if-empty ; inline
|
||||
|
@ -408,82 +408,82 @@ PRIVATE>
|
|||
|
||||
PRIVATE>
|
||||
|
||||
: each ( seq quot -- )
|
||||
: each ( ... seq quot: ( ... x -- ... ) -- ... )
|
||||
(each) each-integer ; inline
|
||||
|
||||
: reduce ( seq identity quot -- result )
|
||||
: reduce ( ... seq identity quot: ( ... prev elt -- ... next ) -- ... result )
|
||||
swapd each ; inline
|
||||
|
||||
: map-integers ( len quot exemplar -- newseq )
|
||||
[ over ] dip [ [ collect ] keep ] new-like ; inline
|
||||
|
||||
: map-as ( seq quot exemplar -- newseq )
|
||||
: map-as ( ... seq quot: ( ... x -- ... newx ) exemplar -- ... newseq )
|
||||
[ (each) ] dip map-integers ; inline
|
||||
|
||||
: map ( seq quot -- newseq )
|
||||
: map ( ... seq quot: ( ... x -- ... newx ) -- ... newseq )
|
||||
over map-as ; inline
|
||||
|
||||
: replicate-as ( len quot exemplar -- newseq )
|
||||
: replicate-as ( ... len quot: ( ... -- ... newx ) exemplar -- ... newseq )
|
||||
[ [ drop ] prepose ] dip map-integers ; inline
|
||||
|
||||
: replicate ( len quot -- newseq )
|
||||
: replicate ( ... len quot: ( ... -- ... newx ) -- ... newseq )
|
||||
{ } replicate-as ; inline
|
||||
|
||||
: map! ( seq quot -- seq )
|
||||
: map! ( ... seq quot: ( ... x -- ... x' ) -- ... seq )
|
||||
over [ map-into ] keep ; inline
|
||||
|
||||
: accumulate-as ( seq identity quot exemplar -- final newseq )
|
||||
: accumulate-as ( ... seq identity quot: ( ... prev elt -- ... next ) exemplar -- ... final newseq )
|
||||
[ (accumulate) ] dip map-as ; inline
|
||||
|
||||
: accumulate ( seq identity quot -- final newseq )
|
||||
: accumulate ( ... seq identity quot: ( ... prev elt -- ... next ) -- ... final newseq )
|
||||
{ } accumulate-as ; inline
|
||||
|
||||
: accumulate! ( seq identity quot -- final seq )
|
||||
: accumulate! ( ... seq identity quot: ( ... prev elt -- ... next ) -- ... final seq )
|
||||
(accumulate) map! ; inline
|
||||
|
||||
: 2each ( seq1 seq2 quot -- )
|
||||
: 2each ( ... seq1 seq2 quot: ( ... x1 x2 -- ... ) -- ... )
|
||||
(2each) each-integer ; inline
|
||||
|
||||
: 2reverse-each ( seq1 seq2 quot -- )
|
||||
: 2reverse-each ( ... seq1 seq2 quot: ( ... x1 x2 -- ... ) -- ... )
|
||||
[ [ <reversed> ] bi@ ] dip 2each ; inline
|
||||
|
||||
: 2reduce ( seq1 seq2 identity quot -- result )
|
||||
: 2reduce ( ... seq1 seq2 identity quot: ( ... prev elt1 elt2 -- ... next ) -- ... result )
|
||||
[ -rot ] dip 2each ; inline
|
||||
|
||||
: 2map-as ( seq1 seq2 quot exemplar -- newseq )
|
||||
: 2map-as ( ... seq1 seq2 quot: ( ... x1 x2 -- ... newx ) exemplar -- ... newseq )
|
||||
[ (2each) ] dip map-integers ; inline
|
||||
|
||||
: 2map ( seq1 seq2 quot -- newseq )
|
||||
: 2map ( ... seq1 seq2 quot: ( ... x1 x2 -- ... newx ) -- ... newseq )
|
||||
pick 2map-as ; inline
|
||||
|
||||
: 2all? ( seq1 seq2 quot -- ? )
|
||||
: 2all? ( ... seq1 seq2 quot: ( ... elt1 elt2 -- ... ? ) -- ... ? )
|
||||
(2each) all-integers? ; inline
|
||||
|
||||
: 3each ( seq1 seq2 seq3 quot -- )
|
||||
: 3each ( ... seq1 seq2 seq3 quot: ( ... x1 x2 x3 -- ... ) -- ... )
|
||||
(3each) each-integer ; inline
|
||||
|
||||
: 3map-as ( seq1 seq2 seq3 quot exemplar -- newseq )
|
||||
: 3map-as ( ... seq1 seq2 seq3 quot: ( ... x1 x2 x3 -- ... newx ) exemplar -- ... newseq )
|
||||
[ (3each) ] dip map-integers ; inline
|
||||
|
||||
: 3map ( seq1 seq2 seq3 quot -- newseq )
|
||||
: 3map ( ... seq1 seq2 seq3 quot: ( ... x1 x2 x3 -- ... newx ) -- ... newseq )
|
||||
[ pick ] dip swap 3map-as ; inline
|
||||
|
||||
: find-from ( n seq quot -- i elt )
|
||||
: find-from ( ... n seq quot: ( ... elt -- ... ? ) -- ... i elt )
|
||||
[ (find-integer) ] (find-from) ; inline
|
||||
|
||||
: find ( seq quot -- i elt )
|
||||
: find ( ... seq quot: ( ... elt -- ... ? ) -- ... i elt )
|
||||
[ find-integer ] (find) ; inline
|
||||
|
||||
: find-last-from ( n seq quot -- i elt )
|
||||
: find-last-from ( ... n seq quot: ( ... elt -- ... ? ) -- ... i elt )
|
||||
[ nip find-last-integer ] (find-from) ; inline
|
||||
|
||||
: find-last ( seq quot -- i elt )
|
||||
: find-last ( ... seq quot: ( ... elt -- ... ? ) -- ... i elt )
|
||||
[ [ 1 - ] dip find-last-integer ] (find) ; inline
|
||||
|
||||
: all? ( seq quot -- ? )
|
||||
: all? ( ... seq quot: ( ... elt -- ... ? ) -- ... ? )
|
||||
(each) all-integers? ; inline
|
||||
|
||||
: push-if ( elt quot accum -- )
|
||||
: push-if ( ... elt quot: ( ... elt -- ... ? ) accum -- ... )
|
||||
[ keep ] dip rot [ push ] [ 2drop ] if ; inline
|
||||
|
||||
: selector-for ( quot exemplar -- selector accum )
|
||||
|
@ -492,19 +492,19 @@ PRIVATE>
|
|||
: selector ( quot -- selector accum )
|
||||
V{ } selector-for ; inline
|
||||
|
||||
: filter-as ( seq quot exemplar -- subseq )
|
||||
: filter-as ( ... seq quot: ( ... elt -- ... ? ) exemplar -- ... subseq )
|
||||
dup [ selector-for [ each ] dip ] curry dip like ; inline
|
||||
|
||||
: filter ( seq quot -- subseq )
|
||||
: filter ( ... seq quot: ( ... elt -- ... ? ) -- ... subseq )
|
||||
over filter-as ; inline
|
||||
|
||||
: push-either ( elt quot accum1 accum2 -- )
|
||||
: push-either ( ... elt quot: ( ... elt -- ... ? ) accum1 accum2 -- ... )
|
||||
[ keep swap ] 2dip ? push ; inline
|
||||
|
||||
: 2selector ( quot -- selector accum1 accum2 )
|
||||
V{ } clone V{ } clone [ [ push-either ] 3curry ] 2keep ; inline
|
||||
|
||||
: partition ( seq quot -- trueseq falseseq )
|
||||
: partition ( ... seq quot: ( ... elt -- ... ? ) -- ... trueseq falseseq )
|
||||
over [ 2selector [ each ] 2dip ] dip [ like ] curry bi@ ; inline
|
||||
|
||||
: collector-for ( quot exemplar -- quot' vec )
|
||||
|
@ -513,16 +513,16 @@ PRIVATE>
|
|||
: collector ( quot -- quot' vec )
|
||||
V{ } collector-for ; inline
|
||||
|
||||
: produce-as ( pred quot exemplar -- seq )
|
||||
: produce-as ( ... pred: ( ... -- ... ? ) quot: ( ... -- ... obj ) exemplar -- ... seq )
|
||||
dup [ collector-for [ while ] dip ] curry dip like ; inline
|
||||
|
||||
: produce ( pred quot -- seq )
|
||||
: produce ( ... pred: ( ... -- ... ? ) quot: ( ... -- ... obj ) -- ... seq )
|
||||
{ } produce-as ; inline
|
||||
|
||||
: follow ( obj quot -- seq )
|
||||
: follow ( ... obj quot: ( ... prev -- ... result/f ) -- ... seq )
|
||||
[ dup ] swap [ keep ] curry produce nip ; inline
|
||||
|
||||
: each-index ( seq quot -- )
|
||||
: each-index ( ... seq quot: ( ... x i -- ... ) -- ... )
|
||||
(each-index) each-integer ; inline
|
||||
|
||||
: interleave ( seq between quot -- )
|
||||
|
@ -532,10 +532,10 @@ PRIVATE>
|
|||
3bi
|
||||
] if ; inline
|
||||
|
||||
: map-index ( seq quot -- newseq )
|
||||
: map-index ( ... seq quot: ( ... x i -- ... newx ) -- ... newseq )
|
||||
[ dup length iota ] dip 2map ; inline
|
||||
|
||||
: reduce-index ( seq identity quot -- )
|
||||
: reduce-index ( ... seq identity quot: ( ... prev x i -- ... next ) -- ... result )
|
||||
swapd each-index ; inline
|
||||
|
||||
: index ( obj seq -- n )
|
||||
|
@ -564,7 +564,7 @@ PRIVATE>
|
|||
: nths ( indices seq -- seq' )
|
||||
[ nth ] curry map ;
|
||||
|
||||
: any? ( seq quot -- ? )
|
||||
: any? ( ... seq quot: ( ... elt -- ... ? ) -- ... ? )
|
||||
find drop >boolean ; inline
|
||||
|
||||
: member? ( elt seq -- ? )
|
||||
|
@ -626,7 +626,7 @@ M: slice equal? over slice? [ sequence= ] [ 2drop f ] if ;
|
|||
|
||||
<PRIVATE
|
||||
|
||||
: (filter!) ( quot: ( elt -- ? ) store scan seq -- )
|
||||
: (filter!) ( ... quot: ( ... elt -- ... ? ) store scan seq -- ... )
|
||||
2dup length < [
|
||||
[ move ] 3keep
|
||||
[ nth-unsafe pick call [ 1 + ] when ] 2keep
|
||||
|
@ -636,7 +636,7 @@ M: slice equal? over slice? [ sequence= ] [ 2drop f ] if ;
|
|||
|
||||
PRIVATE>
|
||||
|
||||
: filter! ( seq quot -- seq )
|
||||
: filter! ( ... seq quot: ( ... elt -- ... ? ) -- ... seq )
|
||||
swap [ [ 0 0 ] dip (filter!) ] keep ; inline
|
||||
|
||||
: remove! ( elt seq -- seq )
|
||||
|
@ -771,7 +771,7 @@ PRIVATE>
|
|||
] keep like
|
||||
] if ;
|
||||
|
||||
: padding ( seq n elt quot -- newseq )
|
||||
: padding ( ... seq n elt quot: ( ... seq1 seq2 -- ... newseq ) -- ... newseq )
|
||||
[
|
||||
[ over length [-] dup 0 = [ drop ] ] dip
|
||||
[ <repetition> ] curry
|
||||
|
@ -810,7 +810,7 @@ PRIVATE>
|
|||
: halves ( seq -- first-slice second-slice )
|
||||
dup midpoint@ cut-slice ;
|
||||
|
||||
: binary-reduce ( seq start quot: ( elt1 elt2 -- newelt ) -- value )
|
||||
: binary-reduce ( ... seq start quot: ( ... elt1 elt2 -- ... newelt ) -- ... value )
|
||||
#! We can't use case here since combinators depends on
|
||||
#! sequences
|
||||
pick length dup 0 3 between? [
|
||||
|
@ -873,11 +873,11 @@ PRIVATE>
|
|||
: 2unclip-slice ( seq1 seq2 -- rest-slice1 rest-slice2 first1 first2 )
|
||||
[ unclip-slice ] bi@ swapd ; inline
|
||||
|
||||
: map-reduce ( seq map-quot reduce-quot -- result )
|
||||
: map-reduce ( ..a seq map-quot: ( ..a x -- ..b elt ) reduce-quot: ( ..b prev elt -- ..a next ) -- ..a result )
|
||||
[ [ unclip-slice ] dip [ call ] keep ] dip
|
||||
compose reduce ; inline
|
||||
|
||||
: 2map-reduce ( seq1 seq2 map-quot reduce-quot -- result )
|
||||
: 2map-reduce ( ..a seq1 seq2 map-quot: ( ..a x1 x2 -- ..b elt ) reduce-quot: ( ..b prev elt -- ..a next ) -- ..a result )
|
||||
[ [ prepare-2map-reduce ] keep ] dip
|
||||
compose compose each-integer ; inline
|
||||
|
||||
|
@ -889,10 +889,10 @@ PRIVATE>
|
|||
|
||||
PRIVATE>
|
||||
|
||||
: map-find ( seq quot -- result elt )
|
||||
: map-find ( ... seq quot: ( ... elt -- ... ? ) -- ... result elt )
|
||||
[ find ] (map-find) ; inline
|
||||
|
||||
: map-find-last ( seq quot -- result elt )
|
||||
: map-find-last ( ... seq quot: ( ... elt -- ... ? ) -- ... result elt )
|
||||
[ find-last ] (map-find) ; inline
|
||||
|
||||
: unclip-last-slice ( seq -- butlast-slice last )
|
||||
|
@ -915,22 +915,22 @@ PRIVATE>
|
|||
|
||||
PRIVATE>
|
||||
|
||||
: trim-head-slice ( seq quot -- slice )
|
||||
: trim-head-slice ( ... seq quot: ( ... elt -- ... ? ) -- ... slice )
|
||||
(trim-head) tail-slice ; inline
|
||||
|
||||
: trim-head ( seq quot -- newseq )
|
||||
: trim-head ( ... seq quot: ( ... elt -- ... ? ) -- ... newseq )
|
||||
(trim-head) tail ; inline
|
||||
|
||||
: trim-tail-slice ( seq quot -- slice )
|
||||
: trim-tail-slice ( ... seq quot: ( ... elt -- ... ? ) -- ... slice )
|
||||
(trim-tail) head-slice ; inline
|
||||
|
||||
: trim-tail ( seq quot -- newseq )
|
||||
: trim-tail ( ... seq quot: ( ... elt -- ... ? ) -- ... newseq )
|
||||
(trim-tail) head ; inline
|
||||
|
||||
: trim-slice ( seq quot -- slice )
|
||||
: trim-slice ( ... seq quot: ( ... elt -- ... ? ) -- ... slice )
|
||||
[ trim-head-slice ] [ trim-tail-slice ] bi ; inline
|
||||
|
||||
: trim ( seq quot -- newseq )
|
||||
: trim ( ... seq quot: ( ... elt -- ... ? ) -- ... newseq )
|
||||
[ trim-slice ] [ drop ] 2bi like ; inline
|
||||
|
||||
GENERIC: sum ( seq -- n )
|
||||
|
@ -942,15 +942,15 @@ M: object sum 0 [ + ] binary-reduce ; inline
|
|||
|
||||
: supremum ( seq -- n ) [ ] [ max ] map-reduce ;
|
||||
|
||||
: map-sum ( seq quot -- n )
|
||||
: map-sum ( ... seq quot: ( ... elt -- ... n ) -- ... n )
|
||||
[ 0 ] 2dip [ dip + ] curry [ swap ] prepose each ; inline
|
||||
|
||||
: count ( seq quot -- n ) [ 1 0 ? ] compose map-sum ; inline
|
||||
: count ( ... seq quot: ( ... elt -- ... ? ) -- ... n ) [ 1 0 ? ] compose map-sum ; inline
|
||||
|
||||
: cartesian-each ( seq1 seq2 quot -- )
|
||||
: cartesian-each ( ... seq1 seq2 quot: ( ... elt1 elt2 -- ... ) -- ... )
|
||||
[ with each ] 2curry each ; inline
|
||||
|
||||
: cartesian-map ( seq1 seq2 quot -- newseq )
|
||||
: cartesian-map ( ... seq1 seq2 quot: ( ... elt1 elt2 -- ... newelt ) -- ... newseq )
|
||||
[ with map ] 2curry map ; inline
|
||||
|
||||
: cartesian-product ( seq1 seq2 -- newseq )
|
||||
|
|
Loading…
Reference in New Issue