small steps
[software/python-on-guile.git] / modules / language / python / hash.scm
1 (define-module (language python hash)
2 #:use-module (oop goops)
3 #:use-module (oop pf-objects)
4 #:export (py-hash complexity xy pyhash-N))
5
6 (define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
7
8 (define N #xefffffffffffffff)
9 (define pyhash-N N)
10
11 (define-inlinable (xy v seed)
12 (modulo
13 (logxor seed
14 (+ v
15 #x9e3779b9
16 (ash seed 6)
17 (ash seed -2)))
18 N))
19
20 (define complexity 10)
21
22 ;; The default is to use guile's hash function
23 (define-method (py-hash x) (hash x N))
24
25 (define-method (py-hash (x <pair>))
26 (define i 0)
27 (let lp ((x x))
28 (if (< i complexity)
29 (begin
30 (set! i (+ i 1))
31 (if (pair? x)
32 (xy (lp (car x)) (lp (cdr x)))
33 (py-hash x)))
34 0)))
35
36 (define-method (py-hash (x <vector>))
37 (let ((n (min complexity (vector-length x))))
38 (let lp ((i 0) (s 0))
39 (if (< i n)
40 (lp (+ i 1)
41 (xy (py-hash (vector-ref x i)) s))
42 s))))
43
44 (define-method (py-hash (x <p>))
45 (aif it (ref x '__hash__)
46 (pk 'hash (it))
47 (next-method)))
48