(define-module (language python module collections abc) #:use-module (oop pf-objects) #:use-module (language python for) #:use-module (language python try) #:use-module (language python exceptions) #:use-module (language python def) #:use-module (language python set) #:use-module (language python list) #:use-module (language python range) #:use-module (language python yield) #:use-module (language python persist) #:export (Container Hashable Iterable Iterator Reversable Generator Sized Callable Collection Sequence MutableSequence ByteString Set MutableSet Mapping MutableMapping MappingView ItemsView KeysView ValuesView)) (define s:set (@@ (language python set) set)) (define-syntax-rule (aif it p x y) (let ((it p)) (if it x y))) (define-python-class Container () (define __containes__ (lambda x (error "not implemented")))) (define-python-class Hashable () (define __hash__ (lambda x (error "not implemented")))) (define-python-class Iterable () (define __iter__ (lambda x (error "not implemented")))) (define-python-class Iterator (Iterable) ;; Mixin (define __iter__ (lambda (self) self)) ;; Abstract (define __next__ (lambda x (error "not implemented")))) (define-python-class Reversable (Iterable) (define __reversed__ (lambda x (error "not implemented")))) (define-python-class Generator (Iterator) ;; Mixin (define __next__ (lambda (self) ((ref self 'send)))) (define close (lambda (self) ((ref self 'throw) GeneratorExit))) ;; Abstract (define send (lambda x (error "not implemented"))) (define throw (lambda x (error "not implemented")))) (define-python-class Sized () (define __len__ (lambda x (error "not implemented")))) (define-python-class Callable () (define __call__ (lambda x (error "not implemented")))) (define-python-class Collection (Sized Iterable Container)) (define-python-class Sequence (Reversable Collection) ;; Mixin (define __contains__ (lambda (self x) (let ((get (ref self '__getitem))) (for ((i : (range (len self)))) () (if (equal? x (get i)) (break #t)) #:final #f)))) (define __iter__ (lambda (self) ((make-generator (lambda (yield) (let ((f (ref self '__getitem))) (for ((i : (range (len self)))) () (yield (f i))))))))) (define __reversed__ (lambda (self) ((make-generator (lambda (yield) (let ((f (ref self '__getitem))) (for ((i : (range (len self) 0 -1))) () (yield (f i))))))))) (define index (lambda (self x) (let ((f (ref self '__getitem__))) (for ((i : (range (len self)))) () (if (equal? x (f i)) (break i)) (raise IndexError))))) (define count (lambda (self x) (let ((f (ref self '__getitem__))) (for ((i : (range (len self)))) ((n 0)) (if (equal? x (f i)) (+ n 1) n) #:final n)))) ;; Abstract (define __getitem__ (lambda x (error "not implemented")))) (define-python-class MutableSequence (Sequence) ;; Mixin (define append (lambda (self x) ((ref self 'insert) (len self) x))) (define extend (lambda (self it) (let ((f (ref self 'insert))) (for ((x : it)) ((i (len self))) (f i x) (+ i 1))) (values))) (define pop (lambda (self) (let* ((i (- (len self) 1)) (x ((ref self '__getitem__) i))) ((ref self '__delitem__) i) x))) (define remove (lambda (self x) (let ((f (ref self '__getitem__))) (for ((i : (range (len self)))) () (if (equal? x (f i)) (begin ((ref self '__delitem__) i) (break))))) (values))) (define __iadd__ (lambda (self seq) (let ((f (ref self 'insert))) (for ((x : seq)) ((i (len self))) (f i x) (+ i 1))) (values))) ;; Abstract (define __setitem__ (lambda x (error "not implemented"))) (define __delitem__ (lambda x (error "not implemented"))) (define insert (lambda x (error "not implemented")))) (define-python-class ByteString (Sequence)) (define-python-class Set (Collection) ;; Mixins (define __le__ (lambda (self o) (let ((f (aif it (ref o '__contains__) it (lambda (x) (in x o))))) (for ((x : self)) () (if (not (f x)) (break #f)))))) (define __lt__ (lambda (self o) (if (equal? (len self) (len o)) #f (let ((f (aif it (ref o '__contains__) it (lambda (x) (in x o))))) (for ((x : self)) () (if (not (f x)) (break #f))))))) (define __eq__ (lambda (self o) (if (not (equal? (len self) (len o))) #f (let ((f (aif it (ref o '__contains__) it (lambda (x) (in x o))))) (for ((x : self)) () (if (not (f x)) (break #f))))))) (define __ne__ (lambda (self o) (not ((ref self '__eq__) o)))) (define __gt__ (lambda (self o) (if (equal? (len self) (len o)) #f (let ((f (ref self '__contains__))) (for ((x : o)) () (if (not (f x)) (break #f))))))) (define __ge__ (lambda (self o) (let ((f (ref self '__contains__))) (for ((x : o)) () (if (not (f x)) (break #f)))))) (define __and__ (lambda (self o) (let* ((f (aif it (ref o '__contains__) it (lambda (x) (in x o)))) (s (s:set)) (a (ref s 'add))) (for ((x : self)) () (if (f x) (a x))) s))) (define __or__ (lambda (self o) (let* ((s (s:set)) (a (ref s 'add))) (for ((x : self)) () (a x)) (for ((x : o)) () (a x)) s))) (define __sub__ (lambda (self o) (let* ((f (ref o '__contains__)) (s (s:set)) (a (ref s 'add))) (for ((x : self)) () (if (not (f x)) (a x))) s))) (define __xor__ (lambda (self o) (let* ((fo (aif it (ref o '__contains__) it (lambda (x) (in x o)))) (fs (ref self '__contains__)) (s (s:set)) (a (ref s 'add))) (for ((x : self)) () (if (not (fo x)) (a x))) (for ((x : o)) () (if (not (fs x)) (a x))) s))) (define disjoint (lambda (self o) (let ((f (aif it (ref o '__contains__) it (lambda (x) (in x o))))) (for ((x : self)) () (if (f x) (break #f)) #:final #t))))) (define-python-class MutableSet (Set) ;; Abstract methods (define add (lambda x (error "not implemented"))) (define discard (lambda x (error "not implemented"))) ;; Mixins (define clear (lambda (self) (define discard (ref self 'discard)) (for ((x : (for ((x : self)) ((l '())) (cons x l) #:final l))) () (discard x)))) (define pop (lambda (self) (let ((x (for ((x : self)) () (break x) #:final (raise KeyError)))) ((ref self 'discard) x) x))) (define remove (lambda (self x) (if (in x self) ((ref self 'discard) x) (raise KeyError)))) (define __ior__ (lambda (self o) (let ((add (ref self 'add))) (for ((x : o)) () (add x))))) (define __iand__ (lambda (self o) (define o-contains (aif it (ref o '__contains__) it (lambda (x) (in o x)))) (define s-discard (ref self 'discard)) (for ((x : (for ((x : self)) ((l '())) (if (o-contains x) l (cons x l))))) () (s-discard x)))) (define __ixor__ (lambda (self o) (define o-contains (aif it (ref o '__contains__) it (lambda (x) (in o x)))) (define s-contains (ref self '__contains__)) (define s-add (ref self 'add)) (define s-discard (ref self 'discard)) (let ((rems (for ((x : self)) ((l '())) (if (o-contains x) (cons x l) l) #:final l)) (adds (for ((x : o)) ((l '())) (if (s-contains x) l (cons x l))))) (let lp ((rems rems)) (if (pair? rems) (begin (s-discard (car rems)) (lp (cdr rems))))) (let lp ((adds adds)) (if (pair? adds) (begin (s-add (car adds)) (lp (cdr adds)))))))) (define __isub__ (lambda (self o) (define o-contains (aif it (ref o '__contains__) it (lambda (x) (in o x)))) (define s-discard (ref self 'discard)) (let ((rems (for ((x : self)) ((l '())) (if (o-contains x) (cons x l) l) #:final l))) (let lp ((rems rems)) (if (pair? rems) (begin (s-discard (car rems)) (lp (cdr rems))))))))) (define-python-class Mapping (Collection) ;; Abstract (define __getitem__ (lambda x (error "not implemented"))) ;; Mixins (define __contains__ (lambda (self x) (try (lambda () (ref self '__getitem__ x) #t) (#:except KeyError => (lambda x #f))))) (define keys (lambda (self) (for ((k v : self)) ((l '())) (cons k l) #:final (reverse l)))) (define items (lambda (self) (for ((k v : self)) ((l '())) (cons (cons k v) l) #:final (reverse l)))) (define values (lambda (self) (for ((k v : self)) ((l '())) (cons v l) #:final (reverse l)))) (define get (lambda* (self x #:optional (d None)) (try (lambda () (ref self '__getitem__ x)) (#:except KeyError => (lambda x d))))) (define __eq__ (lambda (self o) (define o-ref (aif it (ref o '__getitem__) it (lambda (x) (pylist-ref o x)))) (try (lambda () (for ((k v : o)) () (if (not (equal? v (o-ref k))) (break #f)) #:final #t)) (#:except KeyError => (lambda x #f))))) (define __ne__ (lambda (self o) (not ((ref self '__eq__) o))))) (define-python-class MutableMapping (Mapping) ;; Abstracts (define __setitem__ (lambda x (error "not implemented"))) (define __delitem__ (lambda x (error "not implemented"))) ;; Mixins (define pop (lambda* (self k #:optional (d None)) (try (lambda () (define v (pylist-ref self k)) ((ref self '__delitem__) k) v) (#:except KeyError => (lambda x d))))) (define popitem (lambda (self) (for ((k v : self)) () (break k v) #:final (raise KeyError)))) (define clear (lambda (self) (define l (for ((k v : self)) ((l '())) (cons k l) #:final l)) (define rem (ref self '__delitem__)) (let lp ((l l)) (if (pair? l) (begin (rem (car l)) (lp (cdr l))))))) (define update (lam (self (* e) (** f)) (define add (ref self '__setitem__)) (let lp ((e e)) (if (pair? e) (begin (for ((k v : (car e))) () (add k v)) (lp (cdr e))))) (for ((k v : f)) () (add k v)))) (define setdefault (lambda* (self k #:optional (d None)) (try (lambda () ((ref self '__getitem__) k)) (#:except KeyError => (lambda x ((ref self '__setitem__) k d) d)))))) (define-python-class MappingView (Sized) ;; Mixins (define __init__ (lambda (self m) (set self '_mapping m))) (define __len__ (lambda (self) (len (ref self '_mapping))))) (define-python-class ItemsView (MappingView Set) ;; Mixins (define __contains__ (lambda (self x) (let ((m (ref self '_mapping)) (k (car x)) (v (cdr x))) (and (in k m) (equal? v (pylist-ref self k)))))) (define __iter__ (lambda (self) ((ref (ref self '_mapping) 'items))))) (define-python-class KeysView (MappingView Set) ;; Mixins (define __contains__ (lambda (self k) (let ((m (ref self '_mapping))) (in k m)))) (define __iter__ (lambda (self) ((ref (ref self '_mapping) 'keys))))) (define-python-class ValuesView (MappingView) ;; Mixins (define __contains__ (lambda (self x) (let ((m (ref self '_mapping))) (for ((k v : m)) () (if (equal? v x) (break #t)) #:final #f)))) (define __iter__ (lambda (self) ((ref (ref self '_mapping) 'values)))))