summaryrefslogtreecommitdiff
path: root/modules/language/python/range.scm
diff options
context:
space:
mode:
Diffstat (limited to 'modules/language/python/range.scm')
-rw-r--r--modules/language/python/range.scm196
1 files changed, 196 insertions, 0 deletions
diff --git a/modules/language/python/range.scm b/modules/language/python/range.scm
new file mode 100644
index 0000000..675d45a
--- /dev/null
+++ b/modules/language/python/range.scm
@@ -0,0 +1,196 @@
+(define-module (language python range)
+ #:use-module (oop pf-objects)
+ #:use-module (language python exceptions)
+ #:use-module (language python number)
+ #:use-module (language python list)
+ #:use-module (language python yield)
+ #:use-module (language python try)
+ #:export (range))
+
+(define-python-class range ()
+ (define _a 0)
+ (define _b 0)
+ (define _c 1)
+
+ (define __init__
+ (case-lambda
+ ((self n)
+ (let ((n (py-index n)))
+ (set self '_b (max 0 n))))
+ ((self n m)
+ (let ((n (py-index n))
+ (m (py-index m)))
+ (set self '_a m)
+ (set self '_b (max m n))))
+ ((self n m k)
+ (let ((n (py-index n))
+ (m (py-index m))
+ (k (py-index k)))
+ (cond
+ ((= k 0)
+ (raise TypeError "range does not allow 0 as a step"))
+ ((> k 0)
+ (set self '_a n)
+ (set self '_b (if (< m n) n m))
+ (set self '_c k))
+ ((< k 0)
+ (set self '_a n)
+ (set self '_b (if (> m n) n m))
+ (set self '_c k)))))))
+
+ (define __iter__
+ (make-generator range
+ (lambda (yield self)
+ (let* ((a (ref self '_a))
+ (b (ref self '_b))
+ (c (ref self '_c))
+ (op (if (> c 0) < >)))
+ (let lp ((i a))
+ (if (op i b)
+ (begin
+ (yield i)
+ (lp (+ i c)))))))))
+
+ (define __repr__
+ (lambda (self)
+ (format #f "range(~a,~a,~a)"
+ (ref self '_a)
+ (ref self '_b)
+ (ref self '_c))))
+
+ (define __contains__
+ (lambda (self x)
+ (let ((x (py-index x ))
+ (a (ref self '_a))
+ (b (ref self '_b))
+ (c (ref self '_c)))
+ (if (> c 0)
+ (and
+ (>= x a)
+ (< x b)
+ (= (modulo (- x a) c) 0))
+ (and
+ (<= x a)
+ (> x b)
+ (= (modulo (- x a) c) 0))))))
+
+ (define __getitem__
+ (lambda (self x)
+ (let* ((x (py-index x))
+ (a (ref self '_a))
+ (b (ref self '_b))
+ (c (ref self '_c))
+ (m (+ a (* c x))))
+ (if (> c 0)
+ (if (and (>= x 0)
+ (< m b))
+ m
+ (raise IndexError "getitem out of range"))
+ (if (and (<= x 0)
+ (> m b))
+ m
+ (raise IndexError "getitem out of range"))))))
+
+ (define __min__
+ (lambda (self)
+ (let* ((a (ref self '_a))
+ (b (ref self '_b))
+ (c (ref self '_c))
+ (n (abs (py-floordiv (- a b) c))))
+ (if (> c 0)
+ a
+ (+ a (* c (- n 1)))))))
+
+ (define __max__
+ (lambda (self)
+ (let* ((a (ref self '_a))
+ (b (ref self '_b))
+ (c (ref self '_c))
+ (n (abs (py-floordiv (- a b) c))))
+ (if (> c 0)
+ (+ a (* c (- n 1)))
+ n))))
+
+ (define __len__
+ (lambda (self)
+ (let* ((a (ref self '_a))
+ (b (ref self '_b))
+ (c (ref self '_c)))
+ (abs (py-floordiv (- a b) c)))))
+
+ (define __getslice__
+ (lambda (self x y z)
+ (let* ((a (ref self '_a))
+ (b (ref self '_b))
+ (c (ref self '_c))
+ (x (if (eq? x None) None (py-index x)))
+ (y (if (eq? y None) None (py-index y)))
+ (z (if (eq? z None) None (py-index z)))
+ (n (abs (py-floordiv (- a b) c))))
+ (if (or (eq? z None) (> (* z c) 0))
+ (begin
+ (if (eq? z 'None) (set! z 1))
+ (if (eq? y 'None) (set! y n))
+ (if (eq? x 'None) (set! x 0))
+ (if (< x 0) (set! x 0))
+ (if (> x n) (set! x n))
+ (if (< y 0) (set! y 0))
+ (if (> y n) (set! y n))
+ (let* ((cc (* c z))
+ (xx (+ a (* c x)))
+ (yy (+ a (* c y)))
+ (aa (min xx yy))
+ (bb (max xx yy)))
+ (range aa bb cc)))
+ (begin
+ (if (eq? y 'None) (set! y 0))
+ (if (eq? x 'None) (set! x n))
+ (if (< x 0) (set! x 0))
+ (if (> x n) (set! x n))
+ (if (< y 0) (set! y 0))
+ (if (> y n) (set! y n))
+ (let* ((cc (* c z))
+ (xx (+ a (* c x)))
+ (yy (+ a (* c y)))
+ (aa (max xx yy))
+ (bb (min xx yy)))
+ (range aa bb cc)))))))
+
+ (define __index__
+ (case-lambda
+ ((self x)
+ (let ((x (py-index x ))
+ (a (ref self '_a))
+ (b (ref self '_b))
+ (c (ref self '_c)))
+ (if (> c 0)
+ (if (and
+ (>= x a)
+ (< x b)
+ (= (modulo (- x a) c) 0))
+ (py-floordiv (- x a) c)
+ (raise IndexError))
+
+ (if (and
+ (<= x a)
+ (> x b)
+ (= (modulo (- x a) c) 0))
+ (py-floordiv (- x a) c)
+ (raise IndexError)))))
+
+ ((self x i)
+ (py-index (pylist-slice None i 1) x))
+ ((self x i j)
+ (py-index (pylist-slice i j 1) x))))
+
+ (define __count__
+ (lambda (self i)
+ (if (__contains__ self i)
+ 1
+ 0))))
+
+
+
+
+
+