Skip to content

Commit 0fffa79

Browse files
committed
Support uniform numeric array literals
1 parent bfe937e commit 0fffa79

2 files changed

Lines changed: 61 additions & 30 deletions

File tree

ext/uvector/array.scm

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -219,38 +219,68 @@
219219

220220
(define (%read-array-literal port rank type-char ctx)
221221
(define line (port-current-line port))
222-
(define chars '()) ; for error message
223-
(define type-tag
224-
(case type-char
225-
[(#\a #\A) 'a]
226-
[else (error "Uniform numeric array literal isn't supported yet.")]))
222+
(define chars `(,type-char)) ; for error message
223+
(define (save-char!)
224+
(let1 ch (read-char)
225+
(unless (eof-object? ch) (push! chars ch))))
226+
(define (prefix) (list->string (reverse chars)))
227227
(define (err msg content)
228228
(errorf <read-error> :port port :line line
229-
(string-append msg ": #~a~a~a~@[~s~]")
230-
(if (< rank 0) "" rank) type-tag
231-
(list->string (reverse chars)) content))
229+
(string-append msg ": #~a~a~@[~s~]")
230+
(if (< rank 0) "" rank) (prefix) content))
232231
(define (bad-prefix)
233232
;; We read up to the delimiter so that the subsequent read won't be
234233
;; tripped.
235234
(let loop ((ch (peek-char)))
236235
(unless (or (eof-object? ch) (#[\s\(\[\{#\"'`,] ch))
237-
(push! chars (read-char)) (loop (peek-char))))
236+
(save-char!) (loop (peek-char))))
238237
(err "Invalid array literal prefix" #f))
238+
(define (make-type-tag nbits)
239+
(string->symbol (format "~c~d" (char-down-case type-char) nbits)))
240+
(define type-class
241+
(if (#[aA] type-char)
242+
<array>
243+
(case (read-digits #f)
244+
[(8) (case type-char
245+
[(#\s #\S) <s8array>]
246+
[(#\u #\U) <u8array>]
247+
[else (bad-prefix)])]
248+
[(16) (case type-char
249+
[(#\f #\F) <f16array>]
250+
[(#\s #\S) <s16array>]
251+
[(#\u #\U) <u16array>]
252+
[else (bad-prefix)])]
253+
[(32) (case type-char
254+
;;[(#\c #\C) <c32array>]
255+
[(#\f #\F) <f32array>]
256+
[(#\s #\S) <s32array>]
257+
[(#\u #\U) <u32array>]
258+
[else (bad-prefix)])]
259+
[(64) (case type-char
260+
;;[(#\c #\C) <c64array>]
261+
[(#\f #\F) <f64array>]
262+
[(#\s #\S) <s64array>]
263+
[(#\u #\U) <u64array>]
264+
[else (bad-prefix)])]
265+
;; [(128) (case type-char
266+
;; [(#\c #\C) <c128array>]
267+
;; [else (bad-prefix)])]
268+
[else (bad-prefix)])))
239269
(define (read-dimensions r)
240270
(case (peek-char port)
241271
[(#\() (reverse r)]
242-
[(#\@) (push! chars (read-char)) (read-start r)]
243-
[(#\:) (push! chars (read-char)) (read-length 0 r)]
244-
[else (push! chars (read-char)) (bad-prefix)]))
245-
(define (read-digits)
246-
(let loop ((ch (peek-char port))
247-
(ds '()))
272+
[(#\@) (save-char!) (read-start r)]
273+
[(#\:) (save-char!) (read-length 0 r)]
274+
[else (save-char!) (bad-prefix)]))
275+
(define (read-digits allow-sign?)
276+
(let loop ([ch (peek-char port)]
277+
[ds '()])
248278
(cond
249279
[(#[0-9] ch)
250-
(push! chars (read-char))
280+
(save-char!)
251281
(loop (peek-char port) (cons ch ds))]
252-
[(#[+-] ch)
253-
(push! chars (read-char))
282+
[(and allow-sign? (#[+-] ch))
283+
(save-char!)
254284
(if (null? ds)
255285
(loop (peek-char port) (cons ch ds))
256286
(bad-prefix))]
@@ -259,21 +289,21 @@
259289
(bad-prefix)
260290
($ string->number $ list->string $ reverse ds))])))
261291
(define (read-start r)
262-
(let* ([n (read-digits)]
292+
(let* ([n (read-digits #t)]
263293
[ch (peek-char port)])
264294
(case ch
265-
[(#\:) (push! chars (read-char)) (read-length n r)]
266-
[(#\@) (push! chars (read-char)) (read-start `((,n #f) ,@r))]
295+
[(#\:) (save-char!) (read-length n r)]
296+
[(#\@) (save-char!) (read-start `((,n #f) ,@r))]
267297
[(#\() (reverse `((,n #f) ,@r))]
268-
[else (push! chars (read-char)) (bad-prefix)])))
298+
[else (save-char!) (bad-prefix)])))
269299
(define (read-length start r)
270-
(let* ([n (read-digits)]
300+
(let* ([n (read-digits #t)]
271301
[ch (peek-char port)])
272302
(case ch
273-
[(#\:) (push! chars (read-char)) (read-length 0 `((,start ,n) ,@r))]
274-
[(#\@) (push! chars (read-char)) (read-start `((,start ,n) ,@r))]
303+
[(#\:) (save-char!) (read-length 0 `((,start ,n) ,@r))]
304+
[(#\@) (save-char!) (read-start `((,start ,n) ,@r))]
275305
[(#\() (reverse `((,start ,n) ,@r))]
276-
[else (push! chars (read-char)) (bad-prefix)])))
306+
[else (save-char!) (bad-prefix)])))
277307
(define (dim-check suggested content) ;returns #f when bad shape
278308
(let* ([start (if (pair? suggested) (car suggested) 0)]
279309
[actual (length content)]
@@ -325,7 +355,7 @@
325355
(err "Array literal has inconsistent rank" contents))
326356

327357
(list-fill-array!
328-
(make-array-internal <array> (dim->shape dim-list))
358+
(make-array-internal type-class (dim->shape dim-list))
329359
(flatten contents (- (length dim-list) 1) '()))))
330360

331361
;;-------------------------------------------------------------

src/read.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,12 +1638,13 @@ static ScmObj read_num_prefixed(ScmPort *port, ScmChar ch, ScmReadContext *ctx)
16381638
}
16391639
return read_number(port, ch, prefix, ctx);
16401640
}
1641-
case 'a': case 'A':
1642-
/* #digitA - array */
1641+
case 'a': case 'A': case 'c': case 'C': case 'f': case 'F':
1642+
case 's': case 'S': case 'u': case 'U':
1643+
/* #digitA etc. - array */
16431644
if (SCM_EQ(Scm_GetPortReaderLexicalMode(port), SCM_SYM_STRICT_R7)) {
16441645
Scm_ReadError(port, "Array literal isn't allowed in strict R7RS mode.");
16451646
}
1646-
return read_array(port, prefix, 'a', ctx);
1647+
return read_array(port, prefix, ch2, ctx);
16471648
default:
16481649
Scm_ReadError(port, "invalid numeric prefix (#, =, r or R is expected) : #%d%A", prefix, SCM_MAKE_CHAR(ch2));
16491650
return SCM_UNDEFINED;

0 commit comments

Comments
 (0)