1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-01 12:20:26 +02:00

Re-use string output port within read

* module/ice-9/read.scm (read): Just have one string output port during
  the read.
This commit is contained in:
Andy Wingo 2021-02-17 11:55:53 +01:00
parent a194d04d11
commit b6df67fe06

View file

@ -134,6 +134,14 @@
(define (peek) (lookahead-char port)) (define (peek) (lookahead-char port))
(define filename (port-filename port)) (define filename (port-filename port))
(define (get-pos) (cons (port-line port) (port-column port))) (define (get-pos) (cons (port-line port) (port-column port)))
(define accumulator (open-output-string))
(define-syntax-rule (accumulate proc)
(begin
(proc (lambda (ch) (put-char accumulator ch)))
(let ((str (get-output-string accumulator)))
(seek accumulator 0 SEEK_SET)
(truncate-file accumulator 0)
str)))
(define (annotate line column datum) (define (annotate line column datum)
;; FIXME: Return a syntax object instead, so we can avoid the ;; FIXME: Return a syntax object instead, so we can avoid the
@ -161,16 +169,13 @@
(else (read-semicolon-comment))))) (else (read-semicolon-comment)))))
(define-syntax-rule (take-until first pred) (define-syntax-rule (take-until first pred)
(let ((acc (open-output-string))) (accumulate
(put-char acc first) (lambda (put)
(put first)
(let lp () (let lp ()
(let ((ch (peek))) (let ((ch (peek)))
(cond (unless (or (eof-object? ch) (pred ch))
((or (eof-object? ch) (put ch)
(pred ch))
(get-output-string acc))
(else
(put-char acc ch)
(next) (next)
(lp))))))) (lp)))))))
(define-syntax-rule (take-while first pred) (define-syntax-rule (take-while first pred)
@ -288,14 +293,14 @@
(input-error "invalid character in escape sequence: ~S" ch))))))) (input-error "invalid character in escape sequence: ~S" ch)))))))
(define (read-string rdelim) (define (read-string rdelim)
(let ((acc (open-output-string))) (accumulate
(lambda (put)
(let lp () (let lp ()
(let ((ch (next))) (let ((ch (next)))
(unless (eqv? ch rdelim)
(cond (cond
((eof-object? ch) ((eof-object? ch)
(input-error "unexpected end of input while reading string")) (input-error "unexpected end of input while reading string"))
((eqv? ch rdelim)
(get-output-string acc))
((eqv? ch #\\) ((eqv? ch #\\)
(let ((ch (next))) (let ((ch (next)))
(when (eof-object? ch) (when (eof-object? ch)
@ -314,32 +319,32 @@
;; Accept "\(" for use at the beginning of ;; Accept "\(" for use at the beginning of
;; lines in multiline strings to avoid ;; lines in multiline strings to avoid
;; confusing emacs lisp modes. ;; confusing emacs lisp modes.
((#\| #\\ #\() (put-char acc ch)) ((#\| #\\ #\() (put ch))
((#\0) (put-char acc #\nul)) ((#\0) (put #\nul))
((#\f) (put-char acc #\ff)) ((#\f) (put #\ff))
((#\n) (put-char acc #\newline)) ((#\n) (put #\newline))
((#\r) (put-char acc #\return)) ((#\r) (put #\return))
((#\t) (put-char acc #\tab)) ((#\t) (put #\tab))
((#\a) (put-char acc #\alarm)) ((#\a) (put #\alarm))
((#\v) (put-char acc #\vtab)) ((#\v) (put #\vtab))
((#\b) (put-char acc #\backspace)) ((#\b) (put #\backspace))
((#\x) ((#\x)
(let ((ch (if (or (r6rs-escapes?) (eqv? rdelim #\|)) (let ((ch (if (or (r6rs-escapes?) (eqv? rdelim #\|))
(read-r6rs-hex-escape) (read-r6rs-hex-escape)
(read-fixed-hex-escape 2)))) (read-fixed-hex-escape 2))))
(put-char acc ch))) (put ch)))
((#\u) ((#\u)
(put-char acc (read-fixed-hex-escape 4))) (put (read-fixed-hex-escape 4)))
((#\U) ((#\U)
(put-char acc (read-fixed-hex-escape 8))) (put (read-fixed-hex-escape 8)))
(else (else
(unless (eqv? ch rdelim) (unless (eqv? ch rdelim)
(input-error "invalid character in escape sequence: ~S" ch)) (input-error "invalid character in escape sequence: ~S" ch))
(put-char acc ch))) (put ch)))
(lp))) (lp)))
(else (else
(put-char acc ch) (put ch)
(lp))))))) (lp)))))))))
(define (read-character) (define (read-character)
(let ((ch (next))) (let ((ch (next)))