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)))))