From: Matthew Flatt <>
Subject: [plt-scheme] 299.102
Date: Mon, 11 Apr 2005 13:02:01 -0600

The exp-tagged code in CVS for MzScheme and MrEd is now version 299.102.

This version is mainly about reader extension:

 * MzScheme’s reader now supports

      #reader <datum>

   in the input stream, at least when enabled via the parameter
   `read-accepts-reader’. The <datum> identifies a module that
   provides `read’ and `read-syntax’ functions to be applied to the
   port where `#reader’ is encountered.

   For example, if the module at the end of this message is put in
   MzLib, then you would write a MzScheme module as

       #reader(lib "")
       (define x 10)
       (provide x)

   because the reader reads until EOF, and puts the read values into a
   `module’ form using the port’s name to name the module. (This is
   just an example. I didn’t add "" to MzLib.)

   Of course, `#reader’ can be used in the middle of an S-expression,
   as well as at the beginning of an expression.

   The `read-accepts-reader’ parameter is #f by default, so that usig
   `read’ for data doesn’t implicitly allow code to be loaded. The REPL
   and the default load handler set the parameter to #t while reading

   A new `current-reader-guard’ parameter holds a procedure to filter
   module paths, so the set of paths allowed after `#reader’ can be
   limited. The default guard is the identity function.

 * MzScheme’s reader can now be parameterized by a readtable. It’s
   essentially the same as a Common LISP readtable, although the
   interface is slightly different because (1) readtables are
   immutable, (2) they deal with both `read’ and `read-syntax’, and (3)
   the default readtable entries are not reified, but they can be
   applied indirectly through `read[-syntax]/recursive’.

   See the docs for details.

If you write code that depends on a readtable parameterization, use
`#reader’ to install the readtable. Don’t expect people to load file A
(which installs a readtable) before loading file B (which depends on
the readtable), because PLT tools would not work on B. On other words,
`#reader’ serves as a declarative specification for reader extension
that all tools can use.

A `#reader’-based syntax doesn’t have to be a variant of S-expressions,
and it doesn’t have to be built in terms of MzScheme’s `read’. But
`#reader’ and readtables work well together.

I know that many are interested in parameterizing the printer as well
as the reader. I expect to work on printing, too, but I haven’t yet
gotten that far.

Other changes:

 * When `read-square-brackets-as-parens’ is set to #f, a square bracket
   is treated as invalid input instead of the start of a symbol.
   Similarly, when `read-curly-braces-as-parens’ is #f, a square
   bracket is illegal. The old behavior is available through a

 * Added `module-provide-protected?’. (See earlier discussion, where I
   suggested `identifier-exported?’. It turns out that
   `module-provide-protected?’ is more general and easier to define.)

 * A struct type inspector can be #f, which makes the struct type
   transparent to all inspectors.



(module mz mzscheme

  (define (mz-read-one read-syntax src port offsets)
    `(module ,(let ([n (object-name port)])
		 [(path? n)
		  (let-values ([(base name dir?) (split-path n)])
                     (path->string (path-replace-suffix name #""))))]
		 [(symbol? n) n]
		 [else ’unknown]))
       ,@(let loop ()
	   (let ([v (read-syntax src port offsets)])
	     (if (eof-object? v)
		 (cons v (loop)))))))

  (define (mz-read port)
    (mz-read-one (lambda (src port offsets) (read port)) #f port #f))

  (define (mz-read-syntax src port offsets)
    (mz-read-one read-syntax src port offsets))

  (provide (rename mz-read read)
	   (rename mz-read-syntax read-syntax)))