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