(define-module (language python list)
#:use-module (oop pf-objects)
#:use-module (oop goops)
#:use-module (language python exceptions)
#:use-module (language python yield)
#:use-module (language python for)
#:use-module (language python try)
#:use-module (language python exceptions)
#:export (to-list pylist-ref pylist-set! pylist-append!))
(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
(define-method (to-list x)
(if (vector? x)
(vector->list x)
x))
(define-method (to-list (x
))
((ref x '__tolist__ (lambda () (error "missing __tolist__ in object")))))
(define-method (to-list (x ))
(define l '())
(catch StopIteration
(lambda ()
(let lp ()
(set! l (cons (next x) l))
(lp)))
(lambda x
(reverse l))))
(define-class () vec n)
(define-method (to-pylist (l ))
(let* ((n (length l))
(vec (make-vector (* 2 n)))
(o (make )))
(let lp ((l l) (i 0))
(if (pair? l)
(begin
(vector-set! vec i (car l))
(lp (cdr l) (+ i 1)))))
(slot-set! o 'n n)
(slot-set! o 'vec vec)
o))
;;; REF
(define-method (pylist-ref (o ) n)
(if (< n (slot-ref o 'n))
(vector-ref (slot-ref o 'vec) n)
(raise IndexError)))
(define-method (pylist-ref (o ) n)
(list-ref o n))
(define-method (pylist-ref (o ) n)
(vector-ref o n))
(define-method (pylist-ref (o ) n)
((ref o '__listref__) n))
;;; SET
(define-method (pylist-set! (o ) n val)
(if (< n (slot-ref o 'n))
(vector-set! (slot-ref o 'vec) n val)
(raise IndexError)))
(define-method (pylist-set! (o ) n val)
(list-set! o n val))
(define-method (pylist-set! (o ) n val)
(vector-set! o n val))
(define-method (pylist-set! (o ) n val)
((ref o '__listset__) n val))
;;APPEND
(define-method (pylist-append! (o ) val)
(let* ((n (slot-ref o 'n))
(vec (slot-ref o 'vec))
(N (vector-length vec)))
(if (< n N)
(begin
(vector-set! vec n val)
(slot-set! o 'n (+ n 1)))
(let* ((N (* 2 N))
(vec2 (make-vector N)))
(let lp ((i 0))
(if (< i n)
(begin
(vector-set! vec2 i (vector-ref vec i))
(lp (+ i 1)))))
(vector-set! vec2 n val)
(slot-set! o 'vec vec2)))
(slot-set! o 'n (+ n 1))
(values)))
(define-method (pylist-append! o n)
(raise 'NotSupportedOP '__append__))
(define-method (pylist-append! (o ) n . l)
(aif it (ref o '__append__)
(it n)
(aif it (ref o 'append)
(apply it n l)
(error "no append"))))
(define-method (to-list (x ))
(let ((vec (slot-ref x 'vec))
(n (slot-ref x 'n)))
(let lp ((i 0))
(if (< i n)
(cons (vector-ref vec i) (lp (+ i 1)))
'()))))
(define-method (write (o ) . l)
(define port (if (null? l) #t (car l)))
(let* ((l (to-list o)))
(if (null? l)
(format port "[]")
(format port "[~a~{, ~a~}]" (car l) (cdr l)))))
(define-method (display (o ) . l)
(define port (if (null? l) #t (car l)))
(let* ((l (to-list o)))
(if (null? l)
(format port "[]")
(format port "[~a~{, ~a~}]" (car l) (cdr l)))))