1 (define-module (language python dict
)
2 #:use-module
(language python list
)
3 #:use-module
(language python try
)
4 #:use-module
(language python hash
)
5 #:use-module
(language python yield
)
6 #:use-module
(language python def
)
7 #:use-module
(language python for
)
8 #:use-module
(language python bool
)
9 #:use-module
(language python exceptions
)
10 #:use-module
(language python persist
)
11 #:use-module
(ice-9 match
)
12 #:use-module
(ice-9 control
)
13 #:use-module
(oop goops
)
14 #:use-module
(oop pf-objects
)
15 #:export
(make-py-hashtable <py-hashtable
>
16 py-copy py-fromkeys py-get py-has_key py-items py-iteritems
17 py-iterkeys py-itervalues py-keys py-values
18 py-popitem py-setdefault py-update py-clear
19 py-hash-ref dict pyhash-listing
20 weak-key-dict weak-value-dict
21 py-hash-ref py-hash-set
!
22 make-py-weak-key-hashtable
23 make-py-weak-value-hashtable
26 (define-syntax-rule (aif it p x y
) (let ((it p
)) (if it x y
)))
28 (define (h x n
) (modulo (py-hash x
) n
))
29 (define (py-assoc k l
)
31 (if (equal?
(caar l
) k
)
36 (define (py-hash-ref . l
)
37 (apply hashx-ref h py-assoc l
))
38 (define (py-hash-set! . l
)
39 (apply hashx-set
! h py-assoc l
))
40 (define (py-hash-remove! . l
)
41 (apply hashx-remove
! h py-assoc l
))
43 (set! (@@ (language python def
) hset
!) py-hash-set
!)
45 (define H
(hash 1333674836 complexity
))
47 (define-class <py-hashtable
> () t hash n
)
49 (name-object <py-hashtable
>)
56 (let ((t (make-hash-table)))
60 (py-hash-set! t
(caar a
) (cdar a
))
63 (let ((t (slot-ref o
't
)))
67 (hash-fold (lambda (k v s
) (cons (cons k v
) s
)) '() t
)))))
69 (define (make-py-hashtable)
70 (let* ((o (make <py-hashtable
>))
78 (define (make-py-weak-key-hashtable)
79 (let* ((o (make <py-hashtable
>))
80 (t (make-weak-key-hash-table))
87 (define (make-py-weak-value-hashtable)
88 (let* ((o (make <py-hashtable
>))
89 (t (make-weak-value-hash-table))
96 (define miss
(list 'miss
))
97 (define-method (pylist-ref (o <hashtable
>) x
)
98 (let ((r (py-hash-ref o x miss
)))
103 (define-method (pylist-ref (o <py-hashtable
>) x
)
104 (let ((r (py-hash-ref (slot-ref o
't
) x miss
)))
106 (aif it
(ref o
'__missing__
)
111 (define-method (pylist-delete! (o <hashtable
>) k
)
114 (define-method (pylist-delete! (o <py-hashtable
>) k
)
117 (define-method (py-hash (o <hashtable
>))
121 (xy (py-hash k
) (py-hash v
))
125 (define-method (py-hash (o <py-hashtable
>))
128 (define-method (len (o <hashtable
>))
129 (hash-fold (lambda (k v s
) (+ s
1)) 0 o
))
131 (define-method (len (o <py-hashtable
>))
134 (define-method (pylist-pop! (o <hashtable
>) k . l
)
137 (let ((ret (py-hash-ref o k v
)))
138 (py-hash-remove! o k
)
141 (let ((ret (hash-ref o k miss
)))
148 (define-method (pyhash-rem! (o <hashtable
>) k
)
149 (py-hash-remove! o k
)
152 (define-method (pyhash-rem! (o <py-hashtable
>) k
)
153 (let ((t (slot-ref o
't
))
155 (h (slot-ref o
'hash
)))
156 (let ((ret (py-hash-ref t k miss
)))
160 (py-hash-remove! t k
)
161 (slot-set! o
'n
(- n
1))
162 (slot-set! o
'hash
(logxor h
(xy (py-hash k
) (py-hash ret
))))
165 (define-method (pylist-pop! (o <py-hashtable
>) k . l
)
166 (let ((t (slot-ref o
't
)))
169 (let ((ret (py-hash-ref t k miss
)))
176 (let ((ret (hash-ref o k miss
)))
183 (define-method (pylist-set! (o <hashtable
>) key val
)
184 (py-hash-set! o key val
)
187 (define-method (pylist-set! (o <py-hashtable
>) key val
)
188 (let ((t (slot-ref o
't
))
190 (h (slot-ref o
'hash
)))
191 (let ((ret (py-hash-ref t key miss
)))
194 (py-hash-set! t key val
)
195 (slot-set! o
'n
(+ n
1))
196 (slot-set! o
'hash
(logxor (xy (py-hash key
) (py-hash val
)) h
)))
198 (py-hash-set! t key val
)
200 (logxor (xy (py-hash key
) (py-hash val
))
202 (xy (py-hash key
) (py-hash ret
))
206 (define-syntax define-py
208 ((_ (nm n o l ...
) (class code ...
) ...
)
210 (define-method (nm (o class
) l ...
) code ...
)
212 (define-method (nm (o <p
>) l ...
)
216 ((_ (nm n o l ... . u
) (class code ...
) ...
)
218 (define-method (nm (o class
) l ... . u
) code ...
)
220 (define-method (nm (o <p
>) l ... . u
)
226 (define-method (bool (o <hashtable
>))
231 (define-method (bool (o <py-hashtable
>))
234 (define-py (py-copy copy o
)
244 (let ((r (make <py-hashtable
>)))
245 (slot-set! r
'hash
(slot-ref o
'hash
))
246 (slot-set! r
'n
(slot-ref o
'n
))
247 (slot-set! r
't
(py-copy (slot-ref o
't
)))
250 (define-py (py-fromkeys fromkeys o . l
)
252 (let ((newval (match l
257 (py-hash-set! h k newval
)
263 (let ((newval (match l
268 (pylist-set! h k newval
)
273 (define-py (py-get get o k . l
)
275 (let ((elseval (match l
278 (let ((ret (ref o k miss
)))
284 (let ((elseval (match l
287 (let ((ret (ref (slot-ref o
't
) k miss
)))
292 (define-py (py-has_key has_key o k . l
)
294 (let ((elseval (match l
297 (let ((ret (py-hash-ref o k miss
)))
303 (let ((elseval (match l
306 (let ((ret (py-hash-ref (slot-ref o
't
) k miss
)))
311 (define-py (py-items items o
)
324 '() (slot-ref o
't
)))))
326 (define-generator (hash-item-gen yield hash-table
)
327 (let lp
((l (hash-fold cons
* '() hash-table
)))
335 (define-generator (hash-values-gen yield hash-table
)
336 (let lp
((l (hash-fold cons
* '() hash-table
)))
344 (define-generator (hash-keys-gen yield hash-table
)
345 (let lp
((l (hash-fold cons
* '() hash-table
)))
353 (define-py (py-iteritems iteritems o
)
358 (hash-item-gen (slot-ref o
't
))))
360 (define-py (py-iterkeys iterkeys o
)
365 (hash-keys-gen (slot-ref o
't
))))
367 (define-py (py-itervalues itervalues o
)
372 (hash-values-gen (slot-ref o
't
))))
374 (define-py (py-keys keys o
)
378 (lambda (k v l
) (cons k l
))
385 (lambda (k v l
) (cons k l
))
389 (define-py (py-values values o
)
393 (lambda (k v l
) (cons v l
))
400 (lambda (k v l
) (cons v l
))
404 (define-py (py-popitem popitem o
)
406 (let ((k.v
(let/ec ret
413 (begin (pyhash-rem! o
(car k.v
)) k.v
)
414 (raise KeyError
"No elements in hash"))))
417 (let ((k.v
(let/ec ret
424 (begin (pyhash-rem! o
(car k.v
)) k.v
)
425 (raise KeyError
"No elements in hash")))))
427 (define-py (py-setdefault setdefault o k . l
)
429 (pylist-set! o k
(apply py-get o k l
)))
431 (pylist-set! o k
(apply py-get o k l
))))
434 (lam (o (* L
) (** K
))
438 (pylist-set! o k v
)))
441 (pylist-set! o k v
))))
443 (define-py (py-update update o . l
)
449 (define-py (py-clear clear o
)
453 (let ((t (slot-ref o
't
)))
456 (slot-set! o
'hash H
)
465 (define-syntax-rule (top <)
467 (define-method (< (o1 <hashtable
>) (o2 <hashtable
>))
468 (< (len o1
) (len o2
)))
469 (define-method (< (o1 <hashtable
>) (o2 <py-hashtable
>))
470 (< (len o1
) (len o2
)))
471 (define-method (< (o1 <py-hashtable
>) (o2 <hashtable
>))
472 (< (len o1
) (len o2
)))
473 (define-method (< (o1 <py-hashtable
>) (o2 <py-hashtable
>))
474 (< (len o1
) (len o2
)))))
483 (f (car l
) (fold f s
(cdr l
)))
486 (define-method (write (o <py-hashtable
>) . l
)
487 (define port
(match l
(() #f
) ((p) p
)))
488 (define li
(hash-fold cons
* '() (slot-ref o
't
)))
491 (format port
"{~a: ~a~{, ~a: ~a~}}" (car li
) (cadr li
) (cddr li
))))
493 (define-method (py-equal?
(o1 <py-hashtable
>) (o2 <py-hashtable
>))
495 (equal?
(slot-ref o1
'n
) (slot-ref o2
'n
))
496 (equal?
(slot-ref o1
'hash
) (slot-ref o2
'hash
))
497 (e?
(slot-ref o1
't
) (slot-ref o2
't
))))
503 (let ((r (py-hash-ref t2 k miss
)))
513 (define-class <hashiter
> () l
)
514 (name-object <hashiter
>)
515 (cpit <hashiter
> (o (lambda (o l
) (slot-set! o
'l l
))
516 (list (slot-ref o
'l
))))
519 (define-method (wrap-in (t <hashtable
>))
520 (let ((o (make <hashiter
>)))
521 (slot-set! o
'l
(to-list (py-items t
)))
524 (define-method (wrap-in (t <py-hashtable
>))
525 (let ((o (make <hashiter
>)))
526 (slot-set! o
'l
(to-list (py-items t
)))
529 (define-method (next (o <hashiter
>))
530 (let ((l (slot-ref o
'l
)))
537 (throw StopIteration
))))
540 (define-method (in key
(o <hashtable
>))
543 (define-method (in key
(o <py-hashtable
>))
546 (define-python-class dict
(<py-hashtable
>)
551 (let ((r (make-hash-table)))
552 (slot-set! self
't r
)
553 (slot-set! self
'hash H
)
554 (slot-set! self
'n
0)))
560 (pylist-set! self k v
)))
564 (pylist-set! self
(car k
) (cdr k
))
566 "wrong type of argument to dict" k
)))))))))
570 (define-python-class weak-key-dict
(<py-hashtable
>)
575 (let ((r (make-hash-table)))
576 (slot-set! self
't r
)
577 (slot-set! self
'hash H
)
578 (slot-set! self
'n
0)))
582 (if (is-a? x
<py-hashtable
>)
585 (pylist-set! self k v
))
586 (slot-ref x
't
)))))))
589 (define-python-class weak-value-dict
(<py-hashtable
>)
594 (let ((r (make-hash-table)))
595 (slot-set! self
't r
)
596 (slot-set! self
'hash H
)
597 (slot-set! self
'n
0)))
601 (if (is-a? x
<py-hashtable
>)
604 (pylist-set! self k v
))
605 (slot-ref x
't
)))))))
608 (define (pyhash-listing)
611 '(__class__ __cmp__ __contains__ __delattr__
612 __delitem__ __doc__ __eq__ __format__
613 __ge__ __getattribute__ __getitem__
614 __gt__ __hash__ __init__ __iter__
615 __le__ __len__ __lt__ __ne__ __new__
616 __reduce__ __reduce_ex__ __repr__
617 __setattr__ __setitem__ __sizeof__
618 __str__ __subclasshook__
619 clear copy fromkeys get has_key
620 items iteritems iterkeys itervalues
621 keys pop popitem setdefault update
622 values viewitems viewkeys viewvalues
)))))
627 (define-method (py-class (o <hashtable
>)) dict
)
628 (define-method (py-class (o <py-hashtable
>)) dict
)