srfi-214

Fork of the SRFI-214 reference implementation for CHICKEN

git clone https://git.8pit.net/srfi-214.git

  1(define-record-type Flexvector
  2  (%make-flexvector fv-vector fv-length)
  3  flexvector?
  4  (fv-vector vec set-vec!)
  5  (fv-length flexvector-length set-flexvector-length!))
  6
  7(define (cap fv)
  8  (vector-length (vec fv)))
  9
 10(define (grow! fv)
 11  (define old-vec (vec fv))
 12  (define new-vec (make-vector (quotient (* (vector-length old-vec) 3) 2)))
 13  (vector-copy! new-vec 0 old-vec)
 14  (set-vec! fv new-vec)
 15  new-vec)
 16
 17(define make-flexvector
 18  (case-lambda
 19    ((size)
 20      (assume (>= size 0))
 21      (%make-flexvector (make-vector (max size 4)) size))
 22    ((size fill)
 23      (assume (>= size 0))
 24      (%make-flexvector (make-vector (max size 4) fill) size))))
 25
 26(define (flexvector . xs)
 27  (if (null? xs)
 28    (%make-flexvector (make-vector 4) 0)
 29    (list->flexvector xs)))
 30
 31(define (flexvector-ref fv index)
 32  (assume (flexvector? fv))
 33  (assume (integer? index))
 34  (assume (< -1 index (flexvector-length fv)))
 35  (vector-ref (vec fv) index))
 36
 37(define (flexvector-set! fv index x)
 38  (assume (flexvector? fv))
 39  (assume (integer? index))
 40  (assume (< -1 index (flexvector-length fv)))
 41  (let ((last-value (vector-ref (vec fv) index)))
 42    (vector-set! (vec fv) index x)
 43    last-value))
 44
 45(define flexvector-add!
 46  (case-lambda
 47    ((fv i x)
 48      (assume (flexvector? fv))
 49      (assume (integer? i))
 50      (let* ((len (flexvector-length fv))
 51             (v (if (< len (cap fv)) (vec fv) (grow! fv))))
 52        (assume (<= 0 i len))
 53        (vector-copy! v (+ i 1) v i len)
 54        (vector-set! v i x)
 55        (set-flexvector-length! fv (+ len 1))
 56        fv))
 57    ((fv i . xs)
 58      (flexvector-add-all! fv i xs))))
 59
 60(define flexvector-add-back!
 61  (case-lambda
 62    ((fv x)
 63      (assume (flexvector? fv))
 64      (let* ((len (flexvector-length fv))
 65             (v (if (< len (cap fv)) (vec fv) (grow! fv))))
 66        (vector-set! v len x)
 67        (set-flexvector-length! fv (+ len 1))
 68        fv))
 69    ((fv x . xs)
 70      (flexvector-add-back! fv x)
 71      (apply flexvector-add-back! fv xs))))
 72
 73(define (flexvector-add-all! fv i xs)
 74  (assume (flexvector? fv))
 75  (assume (integer? i))
 76  (assume (list? xs))
 77  (let* ((len (flexvector-length fv))
 78         (xv (list->vector xs))
 79         (xvlen (vector-length xv))
 80         (v (let lp ((v (vec fv)))
 81              (if (< (+ len xvlen) (vector-length v)) v (lp (grow! fv))))))
 82    (assume (<= 0 i len))
 83    (vector-copy! v (+ i xvlen) v i len)
 84    (vector-copy! v i xv 0 xvlen)
 85    (set-flexvector-length! fv (+ len xvlen))
 86    fv))
 87
 88(define (flexvector-remove! fv i)
 89  (assume (flexvector? fv))
 90  (assume (integer? i))
 91  (assume (<= 0 i (- (flexvector-length fv) 1)))
 92  (let ((removed (flexvector-ref fv i)))
 93    (flexvector-remove-range! fv i (+ i 1))
 94    removed))
 95
 96(define (flexvector-remove-range! fv start end)
 97  (assume (flexvector? fv))
 98  (let ((len (flexvector-length fv)))
 99    (when (< start 0) (set! start 0))
100    (when (>= end len) (set! end len))
101    (assume (<= start end))
102    (vector-copy! (vec fv) start (vec fv) end)
103    (let ((new-len (- len (- end start))))
104      ;; Workaround a discrepancy in the implementation of vector-fill!
105      ;; between R7RS and SRFI-133: R7RS doesn't error out on an empty
106      ;; fill for the last vector element while SRFI-133 emits an error.
107      ;;
108      ;; See: http://paste.call-cc.org/paste?id=17238d2150d633b4053fc9dd0ce52ecd7c3b4f85
109      (unless (eqv? start end)
110        (vector-fill! (vec fv) #f new-len len))
111      (set-flexvector-length! fv new-len)))
112  fv)
113
114(define (flexvector-clear! fv)
115  (assume (flexvector? fv))
116  (set-vec! fv (make-vector 4))
117  (set-flexvector-length! fv 0)
118  fv)
119
120(define vector->flexvector
121  (case-lambda
122    ((vec)
123      (assume (vector? vec))
124      (vector->flexvector vec 0 (vector-length vec)))
125    ((vec start)
126      (assume (vector? vec))
127      (vector->flexvector vec start (vector-length vec)))
128    ((vec start end)
129      (assume (vector? vec))
130      (assume (<= 0 start end (vector-length vec)))
131      (let ((len (- end start)))
132        (cond
133          ((< len 4)
134            (let ((new-vec (make-vector 4)))
135              (vector-copy! new-vec 0 vec start end)
136              (%make-flexvector new-vec len)))
137          (else
138            (%make-flexvector (vector-copy vec start end) len)))))))
139
140(define flexvector->vector
141  (case-lambda
142    ((fv)
143      (assume (flexvector? fv))
144      (flexvector->vector fv 0 (flexvector-length fv)))
145    ((fv start)
146      (assume (flexvector? fv))
147      (flexvector->vector fv start (flexvector-length fv)))
148    ((fv start end)
149      (assume (flexvector? fv))
150      (assume (<= 0 start end (flexvector-length fv)))
151      (vector-copy (vec fv) start end))))
152
153(define (list->flexvector xs)
154  (let* ((vec (list->vector xs))
155         (len (vector-length vec)))
156    (cond
157      ((< len 4)
158        (let ((new-vec (make-vector 4)))
159          (vector-copy! new-vec 0 vec)
160          (%make-flexvector new-vec len)))
161      (else
162        (%make-flexvector vec len)))))
163
164(define flexvector-filter/index!
165  (case-lambda
166    ((pred? fv)
167      (assume (flexvector? fv))
168      (let ((v (vec fv)) (len (flexvector-length fv)))
169        (let lp ((i 0) (j 0))
170          (cond
171            ((>= i len)
172              (set-flexvector-length! fv j)
173              fv)
174            ((pred? i (vector-ref v i))
175              (unless (= i j) (vector-set! v j (vector-ref v i)))
176              (lp (+ i 1) (+ j 1)))
177            (else
178              (lp (+ i 1) j))))))
179    ((pred? fv . fvs)
180      (assume (flexvector? fv))
181      (let ((v (vec fv)) (len (flexvector-length fv)))
182        (let lp ((i 0) (j 0))
183          (cond
184            ((>= i len)
185              (set-flexvector-length! fv j)
186              fv)
187            ((apply pred?
188                    i
189                    (vector-ref v i)
190                    (map (lambda (fv) (flexvector-ref fv i)) fvs))
191              (unless (= i j) (vector-set! v j (vector-ref v i)))
192              (lp (+ i 1) (+ j 1)))
193            (else
194              (lp (+ i 1) j))))))))
195
196(define flexvector-copy
197  (case-lambda
198    ((fv)
199      (assume (flexvector? fv))
200      (%make-flexvector (vector-copy (vec fv))
201                        (flexvector-length fv)))
202    ((fv start)
203      (assume (flexvector? fv))
204      (flexvector-copy fv start (flexvector-length fv)))
205    ((fv start end)
206      (assume (flexvector? fv))
207      (assume (<= 0 start end (flexvector-length fv)))
208      (vector->flexvector (vector-copy (vec fv) start end)))))
209
210(define flexvector-copy!
211  (case-lambda
212    ((to at from)
213      (assume (flexvector? from))
214      (flexvector-copy! to at from 0 (flexvector-length from)))
215    ((to at from start)
216      (assume (flexvector? from))
217      (flexvector-copy! to at from start (flexvector-length from)))
218    ((to at from start end)
219      (assume (flexvector? to))
220      (assume (<= 0 at (flexvector-length to)))
221      (assume (<= 0 start end (flexvector-length from)))
222      (let* ((vf (vec from))
223             (lt (+ (flexvector-length to) (- end start)))
224             (vt (let lp ((v (vec to)))
225                   (if (< lt (vector-length v)) v (lp (grow! to))))))
226        (vector-copy! vt at vf start end)
227        (set-flexvector-length! to
228          (max (flexvector-length to) (+ at (- end start))))))))