update #lang tutorial to use reader submodule (#1409)

This commit is contained in:
Matthew Butterick 2016-08-19 05:33:36 -07:00 committed by Matthew Flatt
parent 0b21818100
commit 9f7a0af3e5
5 changed files with 113 additions and 81 deletions

View File

@ -66,8 +66,11 @@ Unlike @racketmodname[racket], @racketmodname[s-exp] cannot be used as a
module path with @racket[require]. Although the syntax of module path with @racket[require]. Although the syntax of
@racket[_language] for @hash-lang[] overlaps with the syntax of module @racket[_language] for @hash-lang[] overlaps with the syntax of module
paths, a @racket[_language] is not used directly as a module paths, a @racket[_language] is not used directly as a module
path. Instead, a @racket[_language] is suffixed with path. Instead, a @racket[_language] obtains a module path by trying two
@racketidfont{/lang/reader} to obtain a module path, and the resulting locations: first, it looks for a @racketidfont{reader} submodule of the
main module for @racket[_language]. If this is not a valid module path,
then @racket[_language] is suffixed with @racketidfont{/lang/reader}.
(If neither is a valid module path, an error is raised.) The resulting
module supplies @racketidfont{read} and @racketidfont{read-syntax} module supplies @racketidfont{read} and @racketidfont{read-syntax}
functions using a protocol that is similar to the one for functions using a protocol that is similar to the one for
@racketmetafont{#reader}. @racketmetafont{#reader}.
@ -202,10 +205,16 @@ access languages like @filepath{literal.rkt} and
@racket[@#,hash-lang[] literal] directly, then you must move @racket[@#,hash-lang[] literal] directly, then you must move
@filepath{literal.rkt} into a Racket @tech{collection} named @filepath{literal.rkt} into a Racket @tech{collection} named
@filepath{literal} (see also @secref["link-collection"]). @filepath{literal} (see also @secref["link-collection"]).
Specifically, move @filepath{literal.rkt} to Specifically, move @filepath{literal.rkt} to a @racketidfont{reader}
@filepath{literal/lang/reader.rkt} for any directory name submodule of @filepath{literal/main.rkt} for any directory name
@filepath{literal}. Then, install the @filepath{literal} @filepath{literal}, like so:
directory as a package.
@racketmodfile["literal-main.rkt" "literal/main.rkt"]
Then, install the @filepath{literal}
directory as a package:
@commandline{cd /path/to/literal ; raco pkg install}
After moving the file and installing the package, you can use After moving the file and installing the package, you can use
@racket[literal] directly after @hash-lang[]: @racket[literal] directly after @hash-lang[]:
@ -278,38 +287,11 @@ For security reasons, only languages that have been specifically
installed by a user can respond to language-information queries. If installed by a user can respond to language-information queries. If
you have installed the @racket[literal] language as described in you have installed the @racket[literal] language as described in
@secref["language-collection"], then you can adjust @secref["language-collection"], then you can adjust
@filepath{literal/lang/reader.rkt} so that DrRacket treats the content @filepath{literal/main.rkt} so that DrRacket treats the content
of a module in the @racket[literal] language as plain text instead of of a module in the @racket[literal] language as plain text instead of
(erroneously) as Racket syntax: (erroneously) as Racket syntax:
@racketmod[ @racketmodfile["literal-main-get-info.rkt" "literal/main.rkt"]
#:file "literal/lang/reader.rkt"
racket
(require syntax/strip-context)
(provide (rename-out [literal-read read]
[literal-read-syntax read-syntax])
get-info)
(define (literal-read in)
(syntax->datum
(literal-read-syntax #f in)))
(define (literal-read-syntax src in)
(with-syntax ([str (port->string in)])
(strip-context
#'(module anything racket
(provide data)
(define data (quote str))))))
(define (get-info in mod line col pos)
(lambda (key default)
(case key
[(color-lexer)
(dynamic-require 'syntax-color/default-lexer
'default-lexer)]
[else default])))
]
This revised @racket[literal] implementation provides a This revised @racket[literal] implementation provides a
@racketidfont{get-info} function. The @racketidfont{get-info} function @racketidfont{get-info} function. The @racketidfont{get-info} function
@ -396,14 +378,14 @@ Going back to the @racket[literal] language (see
directly running a @racket[literal] module causes it to print out its directly running a @racket[literal] module causes it to print out its
string, while using a @racket[literal] module in a larger program string, while using a @racket[literal] module in a larger program
simply provides @racketidfont{data} without printing. To make this simply provides @racketidfont{data} without printing. To make this
work, we will need three extra module files: work, we will need three modules. (For clarity here, we will implement
these modules as separate files. But they could equally well be
submodules of a single file.)
@racketblock[ @racketblock[
.... @#,elem{(the main installation or the user's space)} .... @#,elem{(the main installation or the user's space)}
!- @#,filepath{collects}
!- @#,filepath{literal} !- @#,filepath{literal}
!- @#,filepath{lang} !- @#,filepath{main.rkt} @#,elem{(with reader submodule)}
! !- @#,filepath{reader.rkt}
!- @#,filepath{language-info.rkt} @#,elem{(new)} !- @#,filepath{language-info.rkt} @#,elem{(new)}
!- @#,filepath{runtime-config.rkt} @#,elem{(new)} !- @#,filepath{runtime-config.rkt} @#,elem{(new)}
!- @#,filepath{show.rkt} @#,elem{(new)} !- @#,filepath{show.rkt} @#,elem{(new)}
@ -415,7 +397,8 @@ work, we will need three extra module files:
reflective information about the language of modules written in reflective information about the language of modules written in
the @racket[literal] language. The name of this module is not the @racket[literal] language. The name of this module is not
special; it will be connected to the @racket[literal] language special; it will be connected to the @racket[literal] language
through a change to @filepath{literal/lang/reader.rkt}.} through a change to the @racketidfont{reader} submodule of
@filepath{literal/main.rkt}.}
@item{The @filepath{literal/runtime-config.rkt} module will be @item{The @filepath{literal/runtime-config.rkt} module will be
identified by @filepath{literal/language-info.rkt} as the identified by @filepath{literal/language-info.rkt} as the
@ -445,7 +428,7 @@ different modules for these different tasks, we avoid loading code at
times when it is not needed. times when it is not needed.
The three new files are connected to the @racket[literal] language by The three new files are connected to the @racket[literal] language by
changes to @filepath{literal/lang/reader.rkt}: changes to the @racketidfont{reader} submodule of @filepath{literal/main.rkt}:
@itemlist[ @itemlist[
@ -473,41 +456,9 @@ changes to @filepath{literal/lang/reader.rkt}:
] ]
These changes are implemented in the following revised These changes are implemented in the following revised
@filepath{literal/lang/reader.rkt}: @filepath{literal/main.rkt}:
@racketmod[ @racketmodfile["literal-main-language-info.rkt" "literal/main.rkt"]
#:file "literal/lang/reader.rkt"
racket
(require syntax/strip-context)
(provide (rename-out [literal-read read]
[literal-read-syntax read-syntax])
get-info)
(define (literal-read in)
(syntax->datum
(literal-read-syntax #f in)))
(define (literal-read-syntax src in)
(with-syntax ([str (port->string in)])
(syntax-property
(strip-context
#'(module anything racket
(require literal/show)
(provide data)
(define data (quote str))
(show data)))
'module-language
'#(literal/language-info get-language-info #f))))
(define (get-info in mod line col pos)
(lambda (key default)
(case key
[(color-lexer)
(dynamic-require 'syntax-color/default-lexer
'default-lexer)]
[else default])))
]
When a @racket[module] form with a @racket['module-language] property When a @racket[module] form with a @racket['module-language] property
is compiled, the property value is preserved with the compiled module, is compiled, the property value is preserved with the compiled module,

View File

@ -0,0 +1,27 @@
#lang racket
(module reader racket
(require syntax/strip-context)
(provide (rename-out [literal-read read]
[literal-read-syntax read-syntax])
get-info)
(define (literal-read in)
(syntax->datum
(literal-read-syntax #f in)))
(define (literal-read-syntax src in)
(with-syntax ([str (port->string in)])
(strip-context
#'(module anything racket
(provide data)
(define data 'str)))))
(define (get-info in mod line col pos)
(lambda (key default)
(case key
[(color-lexer)
(dynamic-require 'syntax-color/default-lexer
'default-lexer)]
[else default]))))

View File

@ -0,0 +1,32 @@
#lang racket
(module reader racket
(require syntax/strip-context)
(provide (rename-out [literal-read read]
[literal-read-syntax read-syntax])
get-info)
(define (literal-read in)
(syntax->datum
(literal-read-syntax #f in)))
(define (literal-read-syntax src in)
(with-syntax ([str (port->string in)])
(syntax-property
(strip-context
#'(module anything racket
(require literal/show)
(provide data)
(define data 'str)
(show data)))
'module-language
'#(literal/language-info get-language-info #f))))
(define (get-info in mod line col pos)
(lambda (key default)
(case key
[(color-lexer)
(dynamic-require 'syntax-color/default-lexer
'default-lexer)]
[else default]))))

View File

@ -0,0 +1,18 @@
#lang racket
(module reader racket
(require syntax/strip-context)
(provide (rename-out [literal-read read]
[literal-read-syntax read-syntax]))
(define (literal-read in)
(syntax->datum
(literal-read-syntax #f in)))
(define (literal-read-syntax src in)
(with-syntax ([str (port->string in)])
(strip-context
#'(module anything racket
(provide data)
(define data 'str))))))

View File

@ -10,7 +10,7 @@
(define-syntax (racketmodfile stx) (define-syntax (racketmodfile stx)
(syntax-case stx () (syntax-case stx ()
[(_ file) [(_ file displayed-name)
(let ([f (path->complete-path (syntax-e #'file) (let ([f (path->complete-path (syntax-e #'file)
(or (current-load-relative-directory) (or (current-load-relative-directory)
(current-directory)))]) (current-directory)))])
@ -27,4 +27,8 @@
null null
(cons (replace-context #'file v) (cons (replace-context #'file v)
(loop)))))))]) (loop)))))))])
#'(racketmod #:file file content ...)))])) #'(racketmod #:file displayed-name content ...)))]
[(_ file)
#'(racketmodfile file file)]))