65 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			65 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Factor
		
	
	
! Based on Clojure's PersistentHashMap by Rich Hickey.
 | 
						|
 | 
						|
USING: math arrays kernel sequences
 | 
						|
accessors locals persistent.hashtables.config ;
 | 
						|
IN: persistent.hashtables.nodes
 | 
						|
 | 
						|
SINGLETON: empty-node
 | 
						|
 | 
						|
TUPLE: leaf-node
 | 
						|
{ value read-only }
 | 
						|
{ key read-only }
 | 
						|
{ hashcode fixnum read-only } ;
 | 
						|
 | 
						|
C: <leaf-node> leaf-node
 | 
						|
 | 
						|
TUPLE: collision-node
 | 
						|
{ hashcode fixnum read-only }
 | 
						|
{ leaves array read-only } ;
 | 
						|
 | 
						|
C: <collision-node> collision-node
 | 
						|
 | 
						|
TUPLE: full-node
 | 
						|
{ nodes array read-only }
 | 
						|
{ shift fixnum read-only }
 | 
						|
{ hashcode fixnum read-only } ;
 | 
						|
 | 
						|
: <full-node> ( nodes shift -- node )
 | 
						|
    over first hashcode>> full-node boa ;
 | 
						|
 | 
						|
TUPLE: bitmap-node
 | 
						|
{ bitmap fixnum read-only }
 | 
						|
{ nodes array read-only }
 | 
						|
{ shift fixnum read-only }
 | 
						|
{ hashcode fixnum read-only } ;
 | 
						|
 | 
						|
: <bitmap-node> ( bitmap nodes shift -- node )
 | 
						|
    pick full-bitmap-mask =
 | 
						|
    [ <full-node> nip ]
 | 
						|
    [ over first hashcode>> bitmap-node boa ] if ;
 | 
						|
 | 
						|
GENERIC: (entry-at) ( key hashcode node -- entry )
 | 
						|
 | 
						|
GENERIC: (new-at) ( shift value key hashcode node -- node' added-leaf )
 | 
						|
 | 
						|
GENERIC: (pluck-at) ( key hashcode node -- node' )
 | 
						|
 | 
						|
GENERIC: >alist% ( node -- )
 | 
						|
 | 
						|
: >alist-each% ( nodes -- ) [ >alist% ] each ;
 | 
						|
 | 
						|
: mask ( hash shift -- n ) neg shift radix-mask bitand ; inline
 | 
						|
 | 
						|
: bitpos ( hash shift -- n ) mask 2^ ; inline
 | 
						|
 | 
						|
: smash ( idx seq -- seq/elt ? )
 | 
						|
    dup length 2 = [ [ 1 = ] dip first2 ? f ] [ remove-nth t ] if ; inline
 | 
						|
 | 
						|
:: make-bitmap-node ( shift branch value key hashcode -- node' added-leaf )
 | 
						|
    shift value key hashcode
 | 
						|
    branch hashcode>> shift bitpos
 | 
						|
    branch 1array
 | 
						|
    shift
 | 
						|
    <bitmap-node>
 | 
						|
    (new-at) ; inline
 |