Feature Request: read-handler parameter for custom reader extensibility

8 views
Skip to first unread message

Michał Pociecha-Łoś

unread,
Mar 10, 2026, 2:51:51 PM (4 days ago) Mar 10
to chez-scheme
Hi everyone,

I’ve found Chez Scheme to be an excellent foundation for implementing custom languages. Parameters like `library-extensions` and `current-expand` already provide great hooks for customising the load and expansion phases.

To complete this extensibility suite, I am proposing the addition of a `read-handler` parameter. This would allow users to provide a custom read function, bridging the gap between raw source files and the expander.

I’ve implemented a small patch in `s/read.ss` (around line 1670) to demonstrate the integration:

  (define do-read
    (lambda (who ip sfd a? fp)
      (when (port-closed? ip)
        ($oops who "not permitted on closed port ~s" ip))
      (let ([fp (or fp
                    (and ($port-flags-set? ip (constant port-flag-char-positions))
                         (port-has-port-position? ip)
                         (port-position ip)))])
        ((read-handler) ip sfd a? fp))))
  (set-who! default-read-handler
    (lambda (ip sfd a? fp)
      (let ([rcb (make-rcb ip sfd (and a? sfd fp #t) who)] [tb ""] [bfp fp] [it #f])
        (call-with-token rd-top-level))))
  (set! read-handler
    (make-parameter default-read-handler)))

Do you think this hook fits the design philosophy of Chez Scheme, and would you be open to a formal Pull Request for it?

Best regards,
Michał

Michał Pociecha-Łoś

unread,
Mar 10, 2026, 8:41:50 PM (4 days ago) Mar 10
to chez-scheme
Alternatively, to allow intercepting reading from source files only, Chez Scheme could provide `make-read-handler`.

  (set-who! default-make-read-handler
    (lambda (ip sfd fp)
      (lambda ()
        (let-values ([(x new-fp) (do-read who ip sfd #t fp)])
          (set! fp new-fp)
          x))))
  (set! make-read-handler
    (make-parameter default-make-read-handler))
  (set! $make-read
    (lambda (ip sfd fp)
      (define who 'read)
      (unless (and (input-port? ip) (textual-port? ip))
        ($oops who "~s is not a textual input port" ip))
      (unless (or (not sfd) (source-file-descriptor? sfd))
        ($oops who "~s is not a source-file descriptor" sfd))
      ((make-read-handler) ip sfd fp)))

Michał

Reply all
Reply to author
Forward
0 new messages