(define-module (language python dict) #:use-module (language python list) #:use-module (language python try) #:use-module (language python hash) #:use-module (language python yield) #:use-module (language python def) #:use-module (language python for) #:use-module (language python exceptions) #:use-module (language python persist) #:use-module (ice-9 match) #:use-module (ice-9 control) #:use-module (oop goops) #:use-module (oop pf-objects) #:export (make-py-hashtable py-copy py-fromkeys py-get py-has_key py-items py-iteritems py-iterkeys py-itervalues py-keys py-values py-popitem py-setdefault py-update py-clear py-hash-ref dict pyhash-listing weak-key-dict weak-value-dict )) (define-syntax-rule (aif it p x y) (let ((it p)) (if it x y))) (define (h x n) (modulo (py-hash x) n)) (define (py-assoc k l) (if (pair? l) (if (equal? (caar l) k) (car l) (py-assoc k (cdr l))) #f)) (define (py-hash-ref . l) (apply hashx-ref h py-assoc l)) (define (py-hash-set! . l) (apply hashx-set! h py-assoc l)) (define (py-hash-remove! . l) (apply hashx-remove! h py-assoc l)) (set! (@@ (language python def) hset!) py-hash-set!) (define H (hash 1333674836 complexity)) (define-class () t h n) (name-object ) (cpit (o (lambda (o h n a) (slot-set! o 'h h) (slot-set! o 'n n) (slot-set! o 't (let ((t (make-hash-table))) (let lp ((a a)) (if (pair? a) (begin (py-hash-set! t (caar a) (cdar a)) (lp (cdr a))))) t))) (let ((t (slot-ref o 't))) (list (slot-ref o 'h) (slot-ref o 'n) (hash-fold (lambda (k v s) (cons (cons k v) s)) '() t))))) (define (make-py-hashtable) (let* ((o (make )) (t (make-hash-table)) (h H)) (slot-set! o 't t) (slot-set! o 'h h) (slot-set! o 'n 0) o)) (define (make-py-weak-key-hashtable) (let* ((o (make )) (t (make-weak-key-hash-table)) (h H)) (slot-set! o 't t) (slot-set! o 'h h) (slot-set! o 'n 0) o)) (define (make-py-weak-value-hashtable) (let* ((o (make )) (t (make-weak-value-hash-table)) (h H)) (slot-set! o 't t) (slot-set! o 'h h) (slot-set! o 'n 0) o)) (define miss (list 'miss)) (define-method (pylist-ref (o ) x) (let ((r (py-hash-ref o x miss))) (if (eq? r miss) (raise KeyError x) r))) (define-method (pylist-ref (o ) x) (let ((r (py-hash-ref (slot-ref o 't) x miss))) (if (eq? r miss) (aif it (ref o '__missing__) (it x) (raise KeyError x)) r))) (define-method (pylist-delete! (o ) k) (pyhash-rem! o k)) (define-method (pylist-delete! (o ) k) (pyhash-rem! o k)) (define-method (py-hash (o )) (hash-fold (lambda (k v s) (logxor (xy (py-hash k) (py-hash v)) s)) 0 o)) (define-method (py-hash (o )) (slot-ref o 'h)) (define-method (len (o )) (hash-fold (lambda (k v s) (+ s 1)) 0 o)) (define-method (len (o )) (slot-ref o 'n)) (define-method (pylist-pop! (o ) k . l) (match l ((v) (let ((ret (py-hash-ref o k v))) (py-hash-remove! o k) ret)) (() (let ((ret (hash-ref o k miss))) (if (eq? ret miss) (raise KeyError k) (begin (hash-remove! o k) ret)))))) (define-method (pyhash-rem! (o ) k) (py-hash-remove! o k) (values)) (define-method (pyhash-rem! (o ) k) (let ((t (slot-ref o 't)) (n (slot-ref o 'n)) (h (slot-ref o 'h))) (let ((ret (py-hash-ref t k miss))) (if (eq? ret miss) (values) (begin (py-hash-remove! t k) (slot-set! o 'n (- n 1)) (slot-set! o 'h (logxor h (xy (py-hash k) (py-hash ret)))) (values)))))) (define-method (pylist-pop! (o ) k . l) (let ((t (slot-ref o 't))) (match l ((v) (let ((ret (py-hash-ref t k miss))) (if (eq? ret miss) v (begin (pyhash-rem! o k) ret)))) (() (let ((ret (hash-ref o k miss))) (if (eq? ret miss) (raise KeyError k) (begin (pyhash-rem! o k) ret))))))) (define-method (pylist-set! (o ) key val) (py-hash-set! o key val) (values)) (define-method (pylist-set! (o ) key val) (let ((t (slot-ref o 't)) (n (slot-ref o 'n)) (h (slot-ref o 'h))) (let ((ret (py-hash-ref t key miss))) (if (eq? ret miss) (begin (py-hash-set! t key val) (slot-set! o 'n (+ n 1)) (slot-set! o 'h (logxor (xy (py-hash key) (py-hash val)) h))) (begin (py-hash-set! t key val) (slot-set! o 'h (logxor (xy (py-hash key) (py-hash val)) (logxor (xy (py-hash key) (py-hash ret)) h))))))) (values)) (define-syntax define-py (syntax-rules () ((_ (nm n o l ...) (class code ...) ...) (begin (define-method (nm (o class) l ...) code ...) ... (define-method (nm (o

) l ...) (aif it (ref o 'n) (it l ...) (next-method))))) ((_ (nm n o l ... . u) (class code ...) ...) (begin (define-method (nm (o class) l ... . u) code ...) ... (define-method (nm (o

) l ... . u) (aif it (ref o 'n) (apply it l ... u) (next-method))))))) (define-py (py-copy copy o) ( (hash-fold (lambda (k v h) (py-hash-set! h k v) h) (make-hash-table) o)) ( (let ((r (make ))) (slot-set! r 'h (slot-ref o 'h)) (slot-set! r 'n (slot-ref o 'n)) (slot-set! r 't (py-copy (slot-ref o 't))) r))) (define-py (py-fromkeys fromkeys o . l) ( (let ((newval (match l (() None) ((v) v)))) (hash-fold (lambda (k v h) (py-hash-set! h k newval) h) (make-hash-table) o))) ( (let ((newval (match l (() None) ((v) v)))) (hash-fold (lambda (k v h) (pylist-set! h k newval) h) (make-py-hashtable) (slot-ref o 't))))) (define-py (py-get get o k . l) ( (let ((elseval (match l (() None) ((v) v)))) (let ((ret (py-hash-ref o k miss))) (if (eq? ret miss) elseval ret)))) ( (let ((elseval (match l (() None) ((v) v)))) (let ((ret (py-hash-ref (slot-ref o 't) k miss))) (if (eq? ret miss) elseval ret))))) (define-py (py-has_key has_key o k . l) ( (let ((elseval (match l (() None) ((v) v)))) (let ((ret (py-hash-ref o k miss))) (if (eq? ret miss) #f #t)))) ( (let ((elseval (match l (() None) ((v) v)))) (let ((ret (py-hash-ref (slot-ref o 't) k miss))) (if (eq? ret miss) #f #t))))) (define-py (py-items items o) ( (to-pylist (hash-fold (lambda (k v l) (cons (list k v) l)) '() o))) ( (to-pylist (hash-fold (lambda (k v l) (cons (list k v) l)) '() (slot-ref o 't))))) (define-generator (hash-item-gen yield hash-table) (let lp ((l (hash-fold cons* '() hash-table))) (match l ((k v . l) (yield k v) (lp l)) (() #t)))) (define-generator (hash-values-gen yield hash-table) (let lp ((l (hash-fold cons* '() hash-table))) (match l ((k v . l) (yield v) (lp l)) (() #t)))) (define-generator (hash-keys-gen yield hash-table) (let lp ((l (hash-fold cons* '() hash-table))) (match l ((k v . l) (yield k) (lp l)) (() #t)))) (define-py (py-iteritems iteritems o) ( (hash-item-gen o)) ( (hash-item-gen (slot-ref o 't)))) (define-py (py-iterkeys iterkeys o) ( (hash-keys-gen o)) ( (hash-keys-gen (slot-ref o 't)))) (define-py (py-itervalues itervalues o) ( (hash-values-gen o)) ( (hash-values-gen (slot-ref o 't)))) (define-py (py-keys keys o) ( (to-pylist (hash-fold (lambda (k v l) (cons k l)) '() o))) ( (to-pylist (hash-fold (lambda (k v l) (cons k l)) '() (slot-ref o 't))))) (define-py (py-values values o) ( (to-pylist (hash-fold (lambda (k v l) (cons v l)) '() o))) ( (to-pylist (hash-fold (lambda (k v l) (cons v l)) '() (slot-ref o 't))))) (define-py (py-popitem popitem o) ( (let ((k.v (let/ec ret (hash-for-each (lambda (k v) (ret (cons k v))) o) #f))) (if k.v (begin (pyhash-rem! o (car k.v)) k.v) (raise KeyError "No elements in hash")))) ( (let ((k.v (let/ec ret (hash-for-each (lambda (k v) (ret (cons k v))) (slot-ref o 't)) #f))) (if k.v (begin (pyhash-rem! o (car k.v)) k.v) (raise KeyError "No elements in hash"))))) (define-py (py-setdefault setdefault o k . l) ( (pylist-set! o k (apply py-get o k l))) ( (pylist-set! o k (apply py-get o k l)))) (define update (lam (o (* L) (** K)) (match L ((L) (for ((k v : L)) () (pylist-set! o k v))) (_ #f)) (for ((k v : K)) () (pylist-set! o k v)))) (define-py (py-update update o . l) ( (apply update o l)) ( (apply update o l))) (define-py (py-clear clear o) ( (hash-clear! o)) ( (let ((t (slot-ref o 't))) (hash-clear! t) (slot-set! o 'n 0) (slot-set! o 'h H) (values)))) #| 'viewitems' 'viewkeys' 'viewvalues' |# (define-syntax-rule (top <) (begin (define-method (< (o1 ) (o2 )) (< (len o1) (len o2))) (define-method (< (o1 ) (o2 )) (< (len o1) (len o2))) (define-method (< (o1 ) (o2 )) (< (len o1) (len o2))) (define-method (< (o1 ) (o2 )) (< (len o1) (len o2))))) (top <) (top >) (top <=) (top >=) (define (fold f s l) (if (pair? l) (f (car l) (fold f s (cdr l))) s)) (define-method (write (o ) . l) (define port (match l (() #f) ((p) p))) (define li (hash-fold cons* '() (slot-ref o 't))) (if (null? li) (format port "{}") (format port "{~a: ~a~{, ~a: ~a~}}" (car li) (cadr li) (cddr li)))) (define-method (py-equal? (o1 ) (o2 )) (and (equal? (slot-ref o1 'n) (slot-ref o2 'n)) (equal? (slot-ref o1 'h) (slot-ref o2 'h)) (e? (slot-ref o1 't) (slot-ref o2 't)))) (define (e? t1 t2) (let/ec ret (hash-fold (lambda (k v s) (let ((r (py-hash-ref t2 k miss))) (if (eq? r miss) (ret #f) (if (equal? r v) #t (ret #f))))) #t t1))) (define-class () l) (name-object ) (cpit (o (lambda (o l) (slot-set! o 'l l)) (list (slot-ref o 'l)))) (define-method (wrap-in (t )) (let ((o (make ))) (slot-set! o 'l (to-list (py-items t))) o)) (define-method (wrap-in (t )) (let ((o (make ))) (slot-set! o 'l (to-list (py-items t))) o)) (define-method (next (o )) (let ((l (slot-ref o 'l))) (if (pair? l) (let ((k (caar l)) (v (cadar l)) (l (cdr l))) (slot-set! o 'l l) (values k v)) (throw StopIteration)))) (define-method (in key (o )) (py-has_key o key)) (define-method (in key (o )) (py-has_key o key)) (define-python-class dict () (define __init__ (letrec ((__init__ (case-lambda ((self) (let ((r (make-py-hashtable))) (slot-set! self 't (slot-ref r 't)) (slot-set! self 'h (slot-ref r 'h)) (slot-set! self 'n (slot-ref r 'n)))) ((self x) (__init__ self) (if (is-a? x ) (hash-for-each (lambda (k v) (pylist-set! self k v)) (slot-ref x 't))))))) __init__))) (name-object dict) (define-python-class weak-key-dict () (define __init__ (letrec ((__init__ (case-lambda ((self) (let ((r (make-py-weak-key-hashtable))) (slot-set! self 't (slot-ref r 't)) (slot-set! self 'h (slot-ref r 'h)) (slot-set! self 'n (slot-ref r 'n)))) ((self x) (__init__ self) (if (is-a? x ) (hash-for-each (lambda (k v) (pylist-set! self k v)) (slot-ref x 't))))))) __init__))) (name-object weak-key-dict) (define-python-class weak-value-dict () (define __init__ (letrec ((__init__ (case-lambda ((self) (let ((r (make-py-weak-value-hashtable))) (slot-set! self 't (slot-ref r 't)) (slot-set! self 'h (slot-ref r 'h)) (slot-set! self 'n (slot-ref r 'n)))) ((self x) (__init__ self) (if (is-a? x ) (hash-for-each (lambda (k v) (pylist-set! self k v)) (slot-ref x 't))))))) __init__))) (name-object weak-value-dict) (define (pyhash-listing) (let ((l (to-pylist (map symbol->string '(__class__ __cmp__ __contains__ __delattr__ __delitem__ __doc__ __eq__ __format__ __ge__ __getattribute__ __getitem__ __gt__ __hash__ __init__ __iter__ __le__ __len__ __lt__ __ne__ __new__ __reduce__ __reduce_ex__ __repr__ __setattr__ __setitem__ __sizeof__ __str__ __subclasshook__ clear copy fromkeys get has_key items iteritems iterkeys itervalues keys pop popitem setdefault update values viewitems viewkeys viewvalues))))) (pylist-sort! l) l)) (define-method (py-class (o )) dict) (define-method (py-class (o )) dict)