From 40bdb5e60820bd559eaed121d77bbb6972a68ea2 Mon Sep 17 00:00:00 2001 From: Stefan Israelsson Tampe Date: Thu, 5 Oct 2017 23:14:54 +0200 Subject: add mssing range.scm --- modules/language/python/range.scm | 196 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 modules/language/python/range.scm (limited to 'modules') 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)))) + + + + + + -- cgit v1.2.3