2005-04-02 02:39:33 -05:00
|
|
|
! Copyright (C) 2005 Slava Pestov.
|
|
|
|
|
! See http://factor.sf.net/license.txt for BSD license.
|
2005-09-10 18:27:31 -04:00
|
|
|
IN: sequences-internals
|
|
|
|
|
USING: errors generic kernel kernel-internals lists math
|
|
|
|
|
sequences strings vectors words ;
|
|
|
|
|
|
|
|
|
|
: (lexi) ( seq seq i limit -- n )
|
|
|
|
|
2dup >= [
|
2005-09-16 20:49:24 -04:00
|
|
|
2drop [ length ] 2apply -
|
2005-09-10 18:27:31 -04:00
|
|
|
] [
|
|
|
|
|
>r 3dup 2nth-unsafe 2dup = [
|
2005-09-16 22:47:28 -04:00
|
|
|
2drop 1+ r> (lexi)
|
2005-09-10 18:27:31 -04:00
|
|
|
] [
|
|
|
|
|
r> drop - >r 3drop r>
|
2005-09-24 15:21:17 -04:00
|
|
|
] if
|
|
|
|
|
] if ; flushable
|
2005-09-10 18:27:31 -04:00
|
|
|
|
2005-04-02 02:39:33 -05:00
|
|
|
IN: sequences
|
|
|
|
|
|
2005-10-29 23:25:38 -04:00
|
|
|
: first2 ( { x y } -- x y )
|
2005-10-28 15:37:28 -04:00
|
|
|
1 swap bounds-check nip first2-unsafe ; inline
|
|
|
|
|
|
2005-10-29 23:25:38 -04:00
|
|
|
: first3 ( { x y z } -- x y z )
|
2005-10-28 15:37:28 -04:00
|
|
|
2 swap bounds-check nip first3-unsafe ; inline
|
|
|
|
|
|
2005-10-29 23:25:38 -04:00
|
|
|
: first4 ( { x y z w } -- x y z w )
|
2005-10-28 15:37:28 -04:00
|
|
|
3 swap bounds-check nip first4-unsafe ; inline
|
|
|
|
|
|
2005-07-16 22:16:18 -04:00
|
|
|
M: object like drop ;
|
|
|
|
|
|
|
|
|
|
M: object empty? ( seq -- ? ) length 0 = ;
|
|
|
|
|
|
|
|
|
|
: (>list) ( n i seq -- list )
|
|
|
|
|
pick pick <= [
|
|
|
|
|
3drop [ ]
|
2005-05-05 16:51:38 -04:00
|
|
|
] [
|
2005-09-16 22:47:28 -04:00
|
|
|
2dup nth >r >r 1+ r> (>list) r> swons
|
2005-09-24 15:21:17 -04:00
|
|
|
] if ;
|
2005-04-06 21:41:49 -04:00
|
|
|
|
2005-07-16 22:16:18 -04:00
|
|
|
M: object >list ( seq -- list ) dup length 0 rot (>list) ;
|
|
|
|
|
|
2005-08-19 22:22:15 -04:00
|
|
|
: index ( obj seq -- n ) [ = ] find-with drop ; flushable
|
|
|
|
|
: index* ( obj i seq -- n ) [ = ] find-with* drop ; flushable
|
|
|
|
|
: member? ( obj seq -- ? ) [ = ] contains-with? ; flushable
|
|
|
|
|
: memq? ( obj seq -- ? ) [ eq? ] contains-with? ; flushable
|
|
|
|
|
: remove ( obj list -- list ) [ = not ] subset-with ; flushable
|
2005-04-06 21:41:49 -04:00
|
|
|
|
2005-09-17 04:15:05 -04:00
|
|
|
: (subst) ( newseq oldseq elt -- new/elt )
|
|
|
|
|
[ swap index ] keep
|
2005-09-24 15:21:17 -04:00
|
|
|
over -1 > [ drop swap nth ] [ 2nip ] if ;
|
2005-09-17 04:15:05 -04:00
|
|
|
|
|
|
|
|
: subst ( newseq oldseq seq -- )
|
|
|
|
|
#! Mutates seq. If an element of seq occurs in oldseq,
|
|
|
|
|
#! replace it with the corresponding element in newseq.
|
|
|
|
|
[ >r 2dup r> (subst) ] inject 2drop ;
|
|
|
|
|
|
2005-09-14 00:37:50 -04:00
|
|
|
: move ( to from seq -- )
|
|
|
|
|
pick pick number=
|
2005-09-24 15:21:17 -04:00
|
|
|
[ 3drop ] [ [ nth swap ] keep set-nth ] if ; inline
|
2005-09-14 00:37:50 -04:00
|
|
|
|
|
|
|
|
: (delete) ( elt store scan seq -- )
|
|
|
|
|
2dup length < [
|
|
|
|
|
3dup move
|
|
|
|
|
>r pick over r> dup >r nth = r> swap
|
2005-09-16 22:47:28 -04:00
|
|
|
[ >r >r 1+ r> r> ] unless >r 1+ r> (delete)
|
2005-09-14 00:37:50 -04:00
|
|
|
] when ;
|
|
|
|
|
|
|
|
|
|
: delete ( elt seq -- )
|
2005-09-16 02:39:33 -04:00
|
|
|
#! Delete all occurrences of elt from seq.
|
2005-09-14 00:37:50 -04:00
|
|
|
0 0 rot (delete) nip set-length drop ;
|
|
|
|
|
|
2005-09-10 18:27:31 -04:00
|
|
|
: copy-into-check ( start to from -- )
|
|
|
|
|
rot rot length + swap length < [
|
|
|
|
|
"Cannot copy beyond end of sequence" throw
|
|
|
|
|
] when ;
|
|
|
|
|
|
2005-08-04 12:58:07 -04:00
|
|
|
: copy-into ( start to from -- )
|
2005-09-16 02:39:33 -04:00
|
|
|
#! Copy all elements in 'from' to 'to', storing at
|
|
|
|
|
#! consecutive indices numbered from 'start'.
|
2005-09-10 18:27:31 -04:00
|
|
|
3dup copy-into-check
|
|
|
|
|
dup length [ >r pick r> + pick set-nth-unsafe ] 2each 2drop ;
|
2005-11-22 21:41:41 -05:00
|
|
|
inline
|
2005-08-04 12:58:07 -04:00
|
|
|
|
|
|
|
|
: nappend ( to from -- )
|
2005-09-16 02:39:33 -04:00
|
|
|
#! Add all elements of 'from' at the end of 'to'.
|
2005-08-04 12:58:07 -04:00
|
|
|
>r dup length swap r>
|
|
|
|
|
over length over length + pick set-length
|
2005-11-22 21:41:41 -05:00
|
|
|
copy-into ; inline
|
2005-04-06 21:41:49 -04:00
|
|
|
|
2005-04-25 19:54:21 -04:00
|
|
|
: append ( s1 s2 -- s1+s2 )
|
2005-06-23 15:53:54 -04:00
|
|
|
#! Outputs a new sequence of the same type as s1.
|
2005-08-19 22:22:15 -04:00
|
|
|
swap [ swap nappend ] immutable ; flushable
|
2005-06-23 15:53:54 -04:00
|
|
|
|
|
|
|
|
: add ( seq elt -- seq )
|
|
|
|
|
#! Outputs a new sequence of the same type as seq.
|
2005-08-19 22:22:15 -04:00
|
|
|
swap [ push ] immutable ; flushable
|
2005-04-17 21:59:11 -04:00
|
|
|
|
2005-10-03 19:53:32 -04:00
|
|
|
: adjoin ( elt seq -- )
|
|
|
|
|
#! Push the element if its not already there.
|
|
|
|
|
2dup member? [ 2drop ] [ push ] if ;
|
|
|
|
|
|
|
|
|
|
: prune ( seq -- seq )
|
|
|
|
|
#! Remove duplicates.
|
|
|
|
|
dup dup length <vector> swap [ over adjoin ] each swap like ;
|
|
|
|
|
|
2005-12-04 22:06:12 -05:00
|
|
|
: diff ( seq1 seq2 -- seq2-seq1 )
|
|
|
|
|
[ swap member? not ] subset-with ; flushable
|
|
|
|
|
|
2005-04-25 19:54:21 -04:00
|
|
|
: append3 ( s1 s2 s3 -- s1+s2+s3 )
|
2005-04-17 21:59:11 -04:00
|
|
|
#! Return a new sequence of the same type as s1.
|
2005-08-19 22:22:15 -04:00
|
|
|
rot [ [ rot nappend ] keep swap nappend ] immutable ; flushable
|
2005-04-17 21:59:11 -04:00
|
|
|
|
2005-07-22 23:21:50 -04:00
|
|
|
: concat ( seq -- seq )
|
|
|
|
|
#! Append a sequence of sequences together. The new sequence
|
|
|
|
|
#! has the same type as the first sequence.
|
|
|
|
|
dup empty? [
|
|
|
|
|
[ 1024 <vector> swap [ dupd nappend ] each ] keep
|
|
|
|
|
first like
|
2005-08-19 22:22:15 -04:00
|
|
|
] unless ; flushable
|
2005-04-25 19:54:21 -04:00
|
|
|
|
2005-04-26 00:35:55 -04:00
|
|
|
M: object peek ( sequence -- element )
|
2005-04-06 21:41:49 -04:00
|
|
|
#! Get value at end of sequence.
|
2005-09-16 22:47:28 -04:00
|
|
|
dup length 1- swap nth ;
|
2005-04-06 21:41:49 -04:00
|
|
|
|
2005-09-14 00:37:50 -04:00
|
|
|
: pop* ( sequence -- )
|
|
|
|
|
#! Shorten the sequence by one element.
|
2005-11-12 00:37:24 -05:00
|
|
|
[ length 1- ] keep
|
2005-11-19 04:09:30 -05:00
|
|
|
[ 0 -rot set-nth ] 2keep
|
2005-11-22 21:41:41 -05:00
|
|
|
set-length ; inline
|
2005-09-14 00:37:50 -04:00
|
|
|
|
2005-04-06 21:41:49 -04:00
|
|
|
: pop ( sequence -- element )
|
|
|
|
|
#! Get value at end of sequence and remove it.
|
2005-11-22 21:41:41 -05:00
|
|
|
dup peek swap pop* ; inline
|
2005-04-06 21:41:49 -04:00
|
|
|
|
2005-07-24 22:44:33 -04:00
|
|
|
: join ( seq glue -- seq )
|
|
|
|
|
#! The new sequence is of the same type as glue.
|
2005-07-27 01:46:06 -04:00
|
|
|
swap dup empty? [
|
|
|
|
|
swap like
|
|
|
|
|
] [
|
|
|
|
|
dup length <vector> swap
|
2005-09-14 00:37:50 -04:00
|
|
|
[ over push 2dup push ] each nip dup pop*
|
2005-07-27 01:46:06 -04:00
|
|
|
concat
|
2005-09-24 15:21:17 -04:00
|
|
|
] if ; flushable
|
2005-07-24 22:44:33 -04:00
|
|
|
|
2005-07-17 00:21:10 -04:00
|
|
|
M: object reverse-slice ( seq -- seq ) <reversed> ;
|
2005-07-16 23:01:51 -04:00
|
|
|
|
2005-07-16 22:16:18 -04:00
|
|
|
M: object reverse ( seq -- seq ) [ <reversed> ] keep like ;
|
2005-04-11 23:05:05 -04:00
|
|
|
|
2005-09-18 01:37:28 -04:00
|
|
|
: all-equal? ( seq -- ? ) [ = ] monotonic? ;
|
|
|
|
|
|
|
|
|
|
: all-eq? ( seq -- ? ) [ eq? ] monotonic? ;
|
|
|
|
|
|
2005-10-09 21:27:14 -04:00
|
|
|
: mismatch ( seq1 seq2 -- i )
|
|
|
|
|
#! Return the first index where the two sequences differ.
|
|
|
|
|
2dup min-length
|
|
|
|
|
[ >r 2dup r> 2nth-unsafe = not ] find
|
|
|
|
|
swap >r 3drop r> ; flushable
|
|
|
|
|
|
2005-07-19 04:23:33 -04:00
|
|
|
! Lexicographic comparison
|
|
|
|
|
: lexi ( s1 s2 -- n )
|
|
|
|
|
#! Lexicographically compare two sequences of numbers
|
|
|
|
|
#! (usually strings). Negative if s1<s2, zero if s1=s2,
|
|
|
|
|
#! positive if s1>s2.
|
2005-10-12 00:14:46 -04:00
|
|
|
2dup mismatch dup -1 =
|
|
|
|
|
[ drop [ length ] 2apply - ] [ 2nth-unsafe - ] if ;
|
2005-10-09 21:27:14 -04:00
|
|
|
flushable
|
2005-07-19 04:23:33 -04:00
|
|
|
|
2005-07-30 02:08:59 -04:00
|
|
|
: flip ( seq -- seq )
|
2005-07-25 17:13:35 -04:00
|
|
|
#! An example illustrates this word best:
|
2005-10-29 23:25:38 -04:00
|
|
|
#! { { 1 2 3 } { 4 5 6 } } ==> { { 1 4 } { 2 5 } { 3 6 } }
|
2005-07-31 23:38:33 -04:00
|
|
|
dup empty? [
|
2005-09-11 20:46:55 -04:00
|
|
|
dup first [ length ] keep like
|
|
|
|
|
[ swap [ nth ] map-with ] map-with
|
2005-08-19 22:22:15 -04:00
|
|
|
] unless ; flushable
|
2005-07-25 17:13:35 -04:00
|
|
|
|
2005-04-06 21:41:49 -04:00
|
|
|
IN: kernel
|
|
|
|
|
|
|
|
|
|
: depth ( -- n )
|
|
|
|
|
#! Push the number of elements on the datastack.
|
|
|
|
|
datastack length ;
|
2005-08-08 15:21:14 -04:00
|
|
|
|
2005-09-17 22:25:18 -04:00
|
|
|
: no-cond "cond fall-through" throw ;
|
2005-08-30 18:12:21 -04:00
|
|
|
|
2005-08-08 15:21:14 -04:00
|
|
|
: cond ( conditions -- )
|
|
|
|
|
#! Conditions is a sequence of quotation pairs.
|
2005-10-29 23:25:38 -04:00
|
|
|
#! { { [ X ] [ Y ] } { [ Z ] [ T ] } }
|
2005-09-24 15:21:17 -04:00
|
|
|
#! => X [ Y ] [ Z [ T ] [ ] if ] if
|
2005-08-08 15:21:14 -04:00
|
|
|
#! The last condition should be a catch-all 't'.
|
2005-08-30 18:24:53 -04:00
|
|
|
[ first call ] find nip dup
|
2005-09-24 15:21:17 -04:00
|
|
|
[ second call ] [ no-cond ] if ;
|
2005-08-08 15:21:14 -04:00
|
|
|
|
|
|
|
|
: with-datastack ( stack word -- stack )
|
|
|
|
|
datastack >r >r set-datastack r> execute
|
|
|
|
|
datastack r> [ push ] keep set-datastack 2nip ;
|
2005-12-28 20:25:17 -05:00
|
|
|
|
|
|
|
|
: win32? ( -- ? ) os "win32" = ;
|
|
|
|
|
|
|
|
|
|
: unix? ( -- ? ) os { "freebsd" "linux" "macosx" } member? ;
|