add mssing range.scm
authorStefan Israelsson Tampe <stefan.itampe@gmail.com>
Thu, 5 Oct 2017 21:14:54 +0000 (23:14 +0200)
committerStefan Israelsson Tampe <stefan.itampe@gmail.com>
Thu, 5 Oct 2017 21:14:54 +0000 (23:14 +0200)
modules/language/python/range.scm [new file with mode: 0644]

diff --git a/modules/language/python/range.scm b/modules/language/python/range.scm
new file mode 100644 (file)
index 0000000..675d45a
--- /dev/null
@@ -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))))
+
+  
+       
+      
+          
+