[gambit-list] Readtables in Files

Seth Burleigh seth at tewebs.com
Tue Jan 12 10:36:51 EST 2010


If anyones interested.

 

 

 

When loading a source, the function
##read-all-as-a-begin-expr-from-psettings is called which reads the whole
file using the reader as if it started with a  'begin' form. 

 

Unlike some common lisp parsers, it does not read a toplevel and then
macroexpand it. But you can evaluate a form during reading using the #.
macro form (well, you 

have to enable this. see below).

Unfortunately, ##read-all-as-a-being-expr-from-port (another function in the
chain of calls)  makes a copy of the ##current-readtable (the default
readtable) 

and then passes it around to other reader macros. So we cant just modify
that.  

 

 

In _io.scm

 

(define-prim (##read-all-as-a-begin-expr-from-port

              port

              readtable

              wrap

              unwrap

              start-syntax

              close-port?)

  (##with-exception-catcher

   (lambda (exc)

     (if close-port?

       (##close-input-port port))

     (macro-raise exc))

   (lambda ()

     (let ((rt

            (##readtable-copy-shallow readtable)))

       (macro-readtable-start-syntax-set! rt start-syntax)

       (let* ((re

               (##make-readenv port rt wrap unwrap 'script))

              (head

               (##cons (wrap re '##begin)

                       '())) ;; tail will be replaced with expressions read

              (expr

               (wrap re head))

              (first

               (##read-datum-or-eof re))

              (script-line

               (and (##eq? first (##script-marker))

                    (##read-line port #\newline #f ##max-fixnum)))

              (language-and-tail

               (##extract-language-and-tail script-line)))

         (if language-and-tail

           (let ((language (##car language-and-tail)))

             (##readtable-setup-for-language! rt language)))

         (let* ((rest

                 (if (##eof-object? first)

                   '()

                   (##read-all re ##read-datum-or-eof)))

                (port-name

                 (##port-name port)))

           (if close-port?

             (##close-input-port port))

           (cond ((##eof-object? first)

                  (##vector #f expr port-name))

                 ((##eq? first (##script-marker))

                  (##set-cdr! head rest)

                  (##vector script-line expr port-name))

                 (else

                  (##set-cdr! head (##cons first rest))

                  (##vector #f expr port-name)))))))))

 

----------------------------------------------------------------------

So. Solutions to being able to redefine the reader table while the file is
being read. 

(1) Redefine ##read-all-as-a-begin-expr-from-psettings to not make a copy of
the readtable. Probably  not a good idea.

 

(2) Create a special reader syntax which imports the current
readtable/environment as a paramter into the special reader when one
loads/compiles a file. 

I like this one. So instead of doing #.(begin (func-1) (func-2)) you
redefine #. to behave the same way except (current-file-readtable) now
references the actual 

readtable/environment being used.

Note that you can change the current-readtable parameter value as shown
below and thus change the reader macro when loading non scripts (regular
.scm files). I think what

happens if the file is declared to be a script is that first the default
readtable is passed in but is then copied and then modified to fit the
appropriate language.

If it is a regular scheme file, i don't think the default readtable is
modified, but i haven't looked into this.

 

 

 (parameterize

  ((current-readtable 

    (let ((readtab 

        (readtable-keywords-allowed?-set (readtable-eval-allowed?-set
(current-readtable) #t) #f)))

      (##readtable-char-class-set! readtab  ;;changing  reader macro as a
demonstration. look at _io.scm for more examples

       #\; #\t (lambda (re c)

            (display c) (display "GOOFY!")

            (error "IM NOT a comment!")))

      readtab)))

  (load "tar.scm")

 ;....save the current-readtable which has been modified

)

 

tar.scm:

;'yodel

 

Output:

 ;GOOFY!*** ERROR IN ##load -- IM NOT a comment!

 

OK, but what if we want to change the readtable in the actual file instead
of before loading it?

 

Well, now all we have to figure out is, given a environment object and
readtable, how do we go about 'injecting' a parameter into the environment?

 

Well, in _io.scm, heres the definition of the read-sharp-dot macro. And
thats about far as I went. I imagine youde have to find out how to pass a
environment to the #eval.

 

 

(define (##read-sharp-dot re next start-pos)

  (if (not (macro-readtable-eval-allowed? (macro-readenv-readtable re)))

    (begin

      (##raise-datum-parsing-exception 'invalid-token re)

      (##read-datum-or-label-or-none-or-dot re)) ;; skip error

    (begin

      (macro-read-next-char-or-eof re) ;; skip char after #\#

      (let* ((expr

              (##read-expr-from-port

               (macro-readenv-port re)))

             (val

              (##eval expr)))

        (macro-readenv-filepos-set! re start-pos) ;; set pos to start of
datum

        (macro-readenv-wrap re val)))))

 

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20100112/996eaf9f/attachment.htm>


More information about the Gambit-list mailing list