Search code examples
schemeread-eval-print-loop

Scheme REPL in Scheme don't render prompt when user press enter


I've written Scheme REPL that works in all implementations I've tested, but have problem when when someone press enter and don't type anything.

(define void (if #f #f))

(cond-expand
  (lips)
  (kawa)
  (gambit)
  (guile (define (flush-output-port) void))
  (gauche (define (flush-output-port) (flush (current-output-port)))))

(let ((repl (lambda ()
              (let ((env (interaction-environment)))
                (let iter ()
                  (display "scheme> ")
                  (flush-output-port)
                  (let ((input (read)))
                     (if (eof-object? input)
                         (newline)
                         (let ((result (eval input env)))
                           (if (not (eq? result void))
                               (begin
                                 (display result)
                                 (newline)))
                           (iter)))))))))
  (repl))

How to fix my REPL so it works as expected when someone type enter, it should also work when user tried to exit the REPL by using CTRL+D. Right now it don't print prompt when you enter empty input.

NOTE: I was told that my void may don't work in every implementation, but even SRFI use this (I've learned about this in Sketchy Scheme book).


Solution

  • I was able to fix my REPL:

    (let ((repl (lambda ()
                  (let ((env (interaction-environment)))
                    (let iter ()
                      (display "scheme> ")
                      (flush-output-port)
                      (if (char=? (peek-char) #\newline)
                          (begin
                             (read-char)
                             (iter)))
                      (let ((input (read)))
                         (if (eof-object? input)
                             (newline)
                             (let ((result (eval input env)))
                               (if (not (eq? result void))
                                   (begin
                                     (display result)
                                     (newline)))
                                (if (and (char-ready?) (char=? (peek-char) #\newline))
                                    (read-char))
                                (iter)))))))))
      (repl))