| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | ! Based on Clojure's PersistentVector by Rich Hickey. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | USING: math accessors kernel sequences.private sequences arrays | 
					
						
							| 
									
										
										
										
											2008-12-08 15:58:00 -05:00
										 |  |  | combinators combinators.short-circuit parser prettyprint.custom | 
					
						
							| 
									
										
										
										
											2008-08-06 02:06:14 -04:00
										 |  |  | persistent.sequences ;
 | 
					
						
							|  |  |  | IN: persistent.vectors | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: node { children array } { level fixnum } ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | ERROR: empty-error pvec ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  | TUPLE: persistent-vector | 
					
						
							|  |  |  | { count fixnum } | 
					
						
							|  |  |  | { root node initial: T{ node f { } 1 } } | 
					
						
							|  |  |  | { tail node initial: T{ node f { } 0 } } ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: persistent-vector length count>> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-22 20:13:08 -05:00
										 |  |  | CONSTANT: node-size 32
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-15 21:31:55 -05:00
										 |  |  | : node-mask ( m -- n ) node-size mod ; inline
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-15 21:31:55 -05:00
										 |  |  | : node-shift ( m n -- x ) -5 * shift ; inline
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : node-nth ( i node -- obj )
 | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  |     [ node-mask ] [ children>> ] bi* nth ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  | : body-nth ( i node -- i node' )
 | 
					
						
							|  |  |  |     dup level>> [ | 
					
						
							|  |  |  |         dupd [ level>> node-shift ] keep node-nth | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  |     ] times ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : tail-offset ( pvec -- n )
 | 
					
						
							|  |  |  |     [ count>> ] [ tail>> children>> length ] bi - ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: persistent-vector nth-unsafe | 
					
						
							|  |  |  |     2dup tail-offset >=
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  |     [ tail>> ] [ root>> body-nth ] if
 | 
					
						
							|  |  |  |     node-nth ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  | : node-add ( val node -- node' )
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  |     clone [ ppush ] change-children ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  | : ppush-tail ( val pvec -- pvec' )
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  |     [ node-add ] change-tail ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : full? ( node -- ? )
 | 
					
						
							|  |  |  |     children>> length node-size = ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  | : 1node ( val level -- node )
 | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  |     [ 1array ] dip node boa ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : 2node ( first second -- node )
 | 
					
						
							|  |  |  |     [ 2array ] [ drop level>> 1+ ] 2bi node boa ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : new-child ( new-child node -- node' expansion/f )
 | 
					
						
							|  |  |  |     dup full? [ tuck level>> 1node ] [ node-add f ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  | : new-last ( val seq -- seq' )
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  |     [ length 1- ] keep new-nth ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : node-set-last ( child node -- node' )
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  |     clone [ new-last ] change-children ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : (ppush-new-tail) ( tail node -- node' expansion/f )
 | 
					
						
							|  |  |  |     dup level>> 1 = [ | 
					
						
							|  |  |  |         new-child | 
					
						
							|  |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2009-05-25 17:38:33 -04:00
										 |  |  |         tuck children>> last (ppush-new-tail) | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  |         [ swap new-child ] [ swap node-set-last f ] ?if
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : do-expansion ( pvec root expansion/f -- pvec )
 | 
					
						
							|  |  |  |     [ 2node ] when* >>root ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  | : ppush-new-tail ( val pvec -- pvec' )
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  |     [ ] [ tail>> ] [ root>> ] tri
 | 
					
						
							|  |  |  |     (ppush-new-tail) do-expansion | 
					
						
							|  |  |  |     swap 0 1node >>tail ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 04:40:29 -04:00
										 |  |  | M: persistent-vector ppush ( val pvec -- pvec' )
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  |     clone
 | 
					
						
							|  |  |  |     dup tail>> full? | 
					
						
							|  |  |  |     [ ppush-new-tail ] [ ppush-tail ] if
 | 
					
						
							|  |  |  |     [ 1+ ] change-count ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : node-set-nth ( val i node -- node' )
 | 
					
						
							|  |  |  |     clone [ new-nth ] change-children ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : node-change-nth ( i node quot -- node' )
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:56:40 -04:00
										 |  |  |     [ clone ] dip [ | 
					
						
							|  |  |  |         [ clone ] dip [ change-nth ] 2keep drop
 | 
					
						
							|  |  |  |     ] curry change-children ; inline
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : (new-nth) ( val i node -- node' )
 | 
					
						
							|  |  |  |     dup level>> 0 = [ | 
					
						
							|  |  |  |         [ node-mask ] dip node-set-nth | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         [ dupd level>> node-shift node-mask ] keep
 | 
					
						
							|  |  |  |         [ (new-nth) ] node-change-nth | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: persistent-vector new-nth ( obj i pvec -- pvec' )
 | 
					
						
							|  |  |  |     2dup count>> = [ nip ppush ] [ | 
					
						
							|  |  |  |         clone
 | 
					
						
							|  |  |  |         2dup tail-offset >= [ | 
					
						
							|  |  |  |             [ node-mask ] dip
 | 
					
						
							|  |  |  |             [ node-set-nth ] change-tail | 
					
						
							|  |  |  |         ] [ | 
					
						
							|  |  |  |             [ (new-nth) ] change-root | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  | ! The pop code is really convoluted. I don't understand Rich Hickey's | 
					
						
							|  |  |  | ! original code. It uses a 'Box' out parameter which is passed around | 
					
						
							|  |  |  | ! inside a recursive function, and gets mutated along the way to boot. | 
					
						
							|  |  |  | ! Super-confusing. | 
					
						
							| 
									
										
										
										
											2008-06-18 20:46:37 -04:00
										 |  |  | : ppop-tail ( pvec -- pvec' )
 | 
					
						
							|  |  |  |     [ clone [ ppop ] change-children ] change-tail ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | : (ppop-contraction) ( node -- node' tail' )
 | 
					
						
							|  |  |  |     clone [ unclip-last swap ] change-children swap ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ppop-contraction ( node -- node' tail' )
 | 
					
						
							| 
									
										
										
										
											2008-06-18 20:46:37 -04:00
										 |  |  |     dup children>> length 1 =
 | 
					
						
							| 
									
										
										
										
											2009-05-25 17:38:33 -04:00
										 |  |  |     [ children>> last f swap ] | 
					
						
							| 
									
										
										
										
											2008-06-18 20:46:37 -04:00
										 |  |  |     [ (ppop-contraction) ] | 
					
						
							|  |  |  |     if ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : (ppop-new-tail) ( root -- root' tail' )
 | 
					
						
							|  |  |  |     dup level>> 1 > [ | 
					
						
							| 
									
										
										
										
											2009-05-25 17:38:33 -04:00
										 |  |  |         dup children>> last (ppop-new-tail) [ | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  |             dup
 | 
					
						
							|  |  |  |             [ swap node-set-last ] | 
					
						
							|  |  |  |             [ drop ppop-contraction drop ] | 
					
						
							|  |  |  |             if
 | 
					
						
							|  |  |  |         ] dip
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         ppop-contraction | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-18 20:46:37 -04:00
										 |  |  | : trivial? ( node -- ? )
 | 
					
						
							|  |  |  |     { [ level>> 1 > ] [ children>> length 1 = ] } 1&& ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : ppop-new-tail ( pvec -- pvec' )
 | 
					
						
							| 
									
										
										
										
											2008-06-18 20:46:37 -04:00
										 |  |  |     dup root>> (ppop-new-tail) [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             { [ dup not ] [ drop T{ node f { } 1 } ] } | 
					
						
							|  |  |  |             { [ dup trivial? ] [ children>> first ] } | 
					
						
							|  |  |  |             [ ] | 
					
						
							|  |  |  |         } cond
 | 
					
						
							|  |  |  |     ] dip [ >>root ] [ >>tail ] bi* ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | PRIVATE>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: persistent-vector ppop ( pvec -- pvec' )
 | 
					
						
							|  |  |  |     dup count>> { | 
					
						
							|  |  |  |         { 0 [ empty-error ] } | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  |         { 1 [ drop T{ persistent-vector } ] } | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  |         [ | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 clone
 | 
					
						
							|  |  |  |                 dup tail>> children>> length 1 >
 | 
					
						
							|  |  |  |                 [ ppop-tail ] [ ppop-new-tail ] if
 | 
					
						
							|  |  |  |             ] dip 1- >>count | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     } case ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: persistent-vector like | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  |     drop T{ persistent-vector } [ swap ppush ] reduce ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: persistent-vector equal? | 
					
						
							|  |  |  |     over persistent-vector? [ sequence= ] [ 2drop f ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-06 07:09:21 -04:00
										 |  |  | : >persistent-vector ( seq -- pvec )
 | 
					
						
							|  |  |  |     T{ persistent-vector } like ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-21 02:27:50 -04:00
										 |  |  | SYNTAX: PV{ \ } [ >persistent-vector ] parse-literal ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: persistent-vector pprint-delims drop \ PV{ \ } ;
 | 
					
						
							|  |  |  | M: persistent-vector >pprint-sequence ;
 | 
					
						
							| 
									
										
										
										
											2008-09-06 04:23:54 -04:00
										 |  |  | M: persistent-vector pprint* pprint-object ;
 | 
					
						
							| 
									
										
										
										
											2008-06-06 02:53:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | INSTANCE: persistent-vector immutable-sequence |