(define-library (csc hash-map) (export alist->hash-map hash-bytevector hash-map->alist hash-map-foreach hash-map-insert hash-map-lookup hash-map? make-hash-map) (import (scheme base) (only (csc format) sprintf)) (begin (define-record-type (make-key-hash hash k) key-hash? (hash key-hash-hash) (k key-hash-value)) (define (key-hash (key-hash-hash k1) (key-hash-hash k2)) #f) ((key (make-node color key-hash val left right) node? (color node-color) (key-hash node-key) (val node-value) (left node-left) (right node-right)) (define (red? n) (if (null? n) #f (eq? 'red (node-color n)))) (define (black? n) (if (null? n) #t (eq? 'black (node-color n)))) (define (rebalance-left m) (let ((p (node-left m)) (u (node-right m))) (cond ((or (and (red? p) (red? (node-left p)) (red? u)) (and (red? p) (red? (node-right p)) (red? u))) ; b r ; / \ / \ ; r r => b b ; / / ; r r ; b r ; / \ / \ ; r r => b b ; \ \ ; r r (make-node 'red (node-key m) (node-value m) (make-node 'black (node-key p) (node-value p) (node-left p) (node-right p)) (make-node 'black (node-key u) (node-value u) (node-left u) (node-right u)))) ((and (red? p) (red? (node-right p)) (black? u)) ; b b ; / \ / \ ; r b => r r ; \ \ ; r b (let ((n (node-right p))) (make-node 'black (node-key n) (node-value n) (make-node 'red (node-key p) (node-value p) (node-left p) (node-left n)) (make-node 'red (node-key m) (node-value m) (node-right n) u)))) ((and (red? p) (red? (node-left p)) (black? u)) ; b b ; / \ / \ ; r b => r r ; / \ ; r b (make-node 'black (node-key p) (node-value p) (node-left p) (make-node 'red (node-key m) (node-value m) (node-right p) u))) (else m)))) (define (rebalance-right m) (let ((u (node-left m)) (p (node-right m))) (cond ((or (and (red? u) (red? p) (red? (node-left p))) (and (red? u) (red? p) (red? (node-right p)))) ; b r ; / \ / \ ; r r => b b ; \ \ ; r r ; b r ; / \ / \ ; r r => b b ; / / ; r r (make-node 'red (node-key m) (node-value m) (make-node 'black (node-key u) (node-value u) (node-left u) (node-right u)) (make-node 'black (node-key p) (node-value p) (node-left p) (node-right p)))) ((and (black? u) (red? p) (red? (node-left p))) ; b b ; / \ / \ ; b r => r r ; / / ; r b (let ((n (node-left p))) (make-node 'black (node-key n) (node-value n) (make-node 'red (node-key m) (node-value m) u (node-left n)) (make-node 'red (node-key p) (node-value p) (node-right n) (node-right p))))) ((and (black? u) (red? p) (red? (node-right p))) ; b b ; / \ / \ ; b r => r r ; \ / ; r b (make-node 'black (node-key p) (node-value p) (make-node 'red (node-key m) (node-value m) u (node-left p)) (node-right p))) (else m)))) (define (insert m k v key (construct-hash-map hash key (make-key-not-found-error) key-not-found-error?) (define (hash-map-lookup m k) (letrec ((lookup (lambda (n) (cond ((null? n) (raise (make-key-not-found-error))) ((key-hashalist m) (let ((alist '())) (hash-map-foreach (lambda (k v) (set! alist (cons (cons k v) alist))) m) alist)) (define (alist->hash-map hash key= i (bytevector-length b)) hash (loop (+ 1 i) (+ (* hash #x100) (bytevector-u8-ref b i))))))))