[racket] Passing info from reader level
At Sat, 15 Dec 2012 13:12:50 -0800, Rajah Mahsohn Omega wrote:
> So from what I'm gathering the only way to share data with the reader and
> expander layer is to add the reader as a submodue in the main.rkt file.
No, I don't think that works. It might work under some circumstances,
but I think you should imagine that a program is read and compiled on a
different machine where it is run, and so you can't directly share
state between the reader and run-time code. (Ideally, Racket would
enforce that separation, but it currently doesn't.)
Instead, I meant instead that the reader needs to produce module that
has a submodule.
> So
> I've done that and it works but now I have a new problem, provide doesn't
> seem to be providing anything. Here is an example main.rkt file that
> provides meta-count.
The module that your reader produces uses the language `racket' (as
specified after the `syntax/module-reader' language), which doesn't
export `meta-count'.
More generally, I think you will need to use `#:wrapper2' so that you
get control over the whole `module' form to add a nested `module' form
to hold metadata. Here's an example, based on your code.
------------------------------------------------------------
"meta-count.rkt"
------------------------------------------------------------
#lang racket
(module* reader syntax/module-reader
racket
#:wrapper2 wrapper2
(require syntax/readerr)
(define meta-count 0)
(define (wrapper2 in f)
(define mod
(parameterize ([current-readtable (make-meta-readtable)])
(f in)))
(define new-mod
(syntax-case mod ()
[(_mod _name _lang (_mb body ...))
(quasisyntax/loc (if (syntax? mod) mod #'here)
(_mod _name _lang
(_mb (module meta-count racket/base #,meta-count)
body ...)))]))
(if (syntax? mod)
new-mod
(syntax->datum new-mod)))
(define (make-meta-readtable)
(make-readtable (current-readtable)
#\^ 'terminating-macro read-meta))
(define read-meta
(case-lambda
[(ch in)
(rread (object-name in) in)]
[(ch in src line col pos)
(rread src in)]))
(define (rread src in)
(define-values (line col pos) (port-next-location in))
(let ([meta (regexp-match #rx"[^ (['`#]+" in)])
(if meta
(begin
(set! meta-count (add1 meta-count))
(make-special-comment meta))
(raise-read-error "expected a metadata name" src line col pos 1)))))
------------------------------------------------------------
"m.rkt":
------------------------------------------------------------
#lang reader (submod "meta-count.rkt" reader)
^meta (+ ^meta1 1 2)
------------------------------------------------------------
Comamnd line, looking at the expanded form of "m.rkt":
------------------------------------------------------------
% raco expand m.rkt
(module m racket
(#%module-begin
(module meta-count racket/base
(#%module-begin (#%app call-with-values (lambda () '2) print-values)))
(#%app call-with-values (lambda () (#%app + '1 '2)) print-values)))
------------------------------------------------------------
REPL:
------------------------------------------------------------
> (require "m.rkt")
3
> (require (submod "m.rkt" meta-count))
2