add mssing range.scm
[software/python-on-guile.git] / modules / language / python / range.scm
1 (define-module (language python range)
2 #:use-module (oop pf-objects)
3 #:use-module (language python exceptions)
4 #:use-module (language python number)
5 #:use-module (language python list)
6 #:use-module (language python yield)
7 #:use-module (language python try)
8 #:export (range))
9
10 (define-python-class range ()
11 (define _a 0)
12 (define _b 0)
13 (define _c 1)
14
15 (define __init__
16 (case-lambda
17 ((self n)
18 (let ((n (py-index n)))
19 (set self '_b (max 0 n))))
20 ((self n m)
21 (let ((n (py-index n))
22 (m (py-index m)))
23 (set self '_a m)
24 (set self '_b (max m n))))
25 ((self n m k)
26 (let ((n (py-index n))
27 (m (py-index m))
28 (k (py-index k)))
29 (cond
30 ((= k 0)
31 (raise TypeError "range does not allow 0 as a step"))
32 ((> k 0)
33 (set self '_a n)
34 (set self '_b (if (< m n) n m))
35 (set self '_c k))
36 ((< k 0)
37 (set self '_a n)
38 (set self '_b (if (> m n) n m))
39 (set self '_c k)))))))
40
41 (define __iter__
42 (make-generator range
43 (lambda (yield self)
44 (let* ((a (ref self '_a))
45 (b (ref self '_b))
46 (c (ref self '_c))
47 (op (if (> c 0) < >)))
48 (let lp ((i a))
49 (if (op i b)
50 (begin
51 (yield i)
52 (lp (+ i c)))))))))
53
54 (define __repr__
55 (lambda (self)
56 (format #f "range(~a,~a,~a)"
57 (ref self '_a)
58 (ref self '_b)
59 (ref self '_c))))
60
61 (define __contains__
62 (lambda (self x)
63 (let ((x (py-index x ))
64 (a (ref self '_a))
65 (b (ref self '_b))
66 (c (ref self '_c)))
67 (if (> c 0)
68 (and
69 (>= x a)
70 (< x b)
71 (= (modulo (- x a) c) 0))
72 (and
73 (<= x a)
74 (> x b)
75 (= (modulo (- x a) c) 0))))))
76
77 (define __getitem__
78 (lambda (self x)
79 (let* ((x (py-index x))
80 (a (ref self '_a))
81 (b (ref self '_b))
82 (c (ref self '_c))
83 (m (+ a (* c x))))
84 (if (> c 0)
85 (if (and (>= x 0)
86 (< m b))
87 m
88 (raise IndexError "getitem out of range"))
89 (if (and (<= x 0)
90 (> m b))
91 m
92 (raise IndexError "getitem out of range"))))))
93
94 (define __min__
95 (lambda (self)
96 (let* ((a (ref self '_a))
97 (b (ref self '_b))
98 (c (ref self '_c))
99 (n (abs (py-floordiv (- a b) c))))
100 (if (> c 0)
101 a
102 (+ a (* c (- n 1)))))))
103
104 (define __max__
105 (lambda (self)
106 (let* ((a (ref self '_a))
107 (b (ref self '_b))
108 (c (ref self '_c))
109 (n (abs (py-floordiv (- a b) c))))
110 (if (> c 0)
111 (+ a (* c (- n 1)))
112 n))))
113
114 (define __len__
115 (lambda (self)
116 (let* ((a (ref self '_a))
117 (b (ref self '_b))
118 (c (ref self '_c)))
119 (abs (py-floordiv (- a b) c)))))
120
121 (define __getslice__
122 (lambda (self x y z)
123 (let* ((a (ref self '_a))
124 (b (ref self '_b))
125 (c (ref self '_c))
126 (x (if (eq? x None) None (py-index x)))
127 (y (if (eq? y None) None (py-index y)))
128 (z (if (eq? z None) None (py-index z)))
129 (n (abs (py-floordiv (- a b) c))))
130 (if (or (eq? z None) (> (* z c) 0))
131 (begin
132 (if (eq? z 'None) (set! z 1))
133 (if (eq? y 'None) (set! y n))
134 (if (eq? x 'None) (set! x 0))
135 (if (< x 0) (set! x 0))
136 (if (> x n) (set! x n))
137 (if (< y 0) (set! y 0))
138 (if (> y n) (set! y n))
139 (let* ((cc (* c z))
140 (xx (+ a (* c x)))
141 (yy (+ a (* c y)))
142 (aa (min xx yy))
143 (bb (max xx yy)))
144 (range aa bb cc)))
145 (begin
146 (if (eq? y 'None) (set! y 0))
147 (if (eq? x 'None) (set! x n))
148 (if (< x 0) (set! x 0))
149 (if (> x n) (set! x n))
150 (if (< y 0) (set! y 0))
151 (if (> y n) (set! y n))
152 (let* ((cc (* c z))
153 (xx (+ a (* c x)))
154 (yy (+ a (* c y)))
155 (aa (max xx yy))
156 (bb (min xx yy)))
157 (range aa bb cc)))))))
158
159 (define __index__
160 (case-lambda
161 ((self x)
162 (let ((x (py-index x ))
163 (a (ref self '_a))
164 (b (ref self '_b))
165 (c (ref self '_c)))
166 (if (> c 0)
167 (if (and
168 (>= x a)
169 (< x b)
170 (= (modulo (- x a) c) 0))
171 (py-floordiv (- x a) c)
172 (raise IndexError))
173
174 (if (and
175 (<= x a)
176 (> x b)
177 (= (modulo (- x a) c) 0))
178 (py-floordiv (- x a) c)
179 (raise IndexError)))))
180
181 ((self x i)
182 (py-index (pylist-slice None i 1) x))
183 ((self x i j)
184 (py-index (pylist-slice i j 1) x))))
185
186 (define __count__
187 (lambda (self i)
188 (if (__contains__ self i)
189 1
190 0))))
191
192
193
194
195
196