From 68986fe0410584c6934c835bb0ee784655f5f8c5 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Tue, 11 Jan 2022 22:01:23 -0800 Subject: Move scheme compiler into a separate directory. --- csc/hash-map.csc | 259 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 csc/hash-map.csc (limited to 'csc/hash-map.csc') diff --git a/csc/hash-map.csc b/csc/hash-map.csc new file mode 100644 index 0000000..01d4158 --- /dev/null +++ b/csc/hash-map.csc @@ -0,0 +1,259 @@ +(define-library (csc hash-map) + (export + alist->map + hash-bytevector + map->alist + for-each + insert + lookup + map? + key-not-found-error? + make-map) + (import (scheme base) + (only (csc format) sprintf)) + (begin + + + (define-record-type + (make-key-hash k hash) + key-hash? + (k key-hash-value) + (hash key-hash-hash)) + + + (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-node m k v key + (construct-hash-map hash key + (make-key-not-found-error) + key-not-found-error?) + + + (define (lookup m k) + (letrec ((k* (make-key-hash k ((hash-map-hash m) k))) + (lookup + (lambda (n) + (cond ((null? n) (raise (make-key-not-found-error))) + ((key-hashalist m) + (let ((alist '())) + (for-each + (lambda (k v) + (set! alist (cons (cons k v) alist))) + m) + alist)) + + + (define (alist->map hash key= i (bytevector-length b)) + hash + (loop (+ 1 i) (+ (* hash #x100) (bytevector-u8-ref b i)))))))) -- cgit v1.3.1