[plt-scheme] 299.102
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 "mz.ss")
(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 "mz.ss" 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
code.
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
readtable.
* 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.
Matthew
----------------------------------------
(module mz mzscheme
(define (mz-read-one read-syntax src port offsets)
`(module ,(let ([n (object-name port)])
(cond
[(path? n)
(let-values ([(base name dir?) (split-path n)])
(string->symbol
(path->string (path-replace-suffix name #""))))]
[(symbol? n) n]
[else 'unknown]))
mzscheme
,@(let loop ()
(let ([v (read-syntax src port offsets)])
(if (eof-object? v)
null
(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)))