1#lang scribble/doc
2@(require scribble/manual scribble/eval scribble/racket
3          "guide-utils.rkt" "modfile.rkt"
4          (for-syntax racket/base)
5          (for-label setup/dirs
6                     syntax/strip-context
7                     syntax-color/default-lexer))
8
9@(define-syntax ! (make-element-id-transformer (lambda (v) #'@tt{|})))
10@(define-syntax !- (make-element-id-transformer (lambda (v) #'@tt{|-})))
11
12
13@title[#:tag "hash-languages" #:style 'toc]{Defining new @hash-lang[] Languages}
14
15When loading a module as a source program that starts
16
17@racketmod[
18@#,racket[_language]
19]
20
21the @racket[_language] determines the way that the rest of the module
22is parsed at the @tech{reader} level. The @tech{reader}-level parse
23must produce a @racket[module] form as a @tech{syntax object}. As
24always, the second sub-form after @racket[module] specifies the
25@tech{module language} that controls the meaning of the module's body
26forms. Thus, a @racket[_language] specified after @hash-lang[]
27controls both the @tech{reader}-level and @tech{expander}-level
28parsing of a module.
29
30@local-table-of-contents[]
31
32@; ----------------------------------------
33@section[#:tag "hash-lang syntax"]{Designating a @hash-lang[] Language}
34
35The syntax of a @racket[_language] intentionally overlaps with the
36syntax of a module path as used in @racket[require] or as a
37@tech{module language}, so that names like @racketmodname[racket],
38@racketmodname[racket/base], @racketmodname[slideshow], or
39@racketmodname[scribble/manual] can be used both as @hash-lang[]
40languages and as module paths.
41
42At the same time, the syntax of @racket[_language] is far more
43restricted than a module path, because only @litchar{a}-@litchar{z},
44@litchar{A}-@litchar{Z}, @litchar{0}-@litchar{9},
45@litchar{/} (not at the start or end),
46@litchar{_}, @litchar{-}, and @litchar{+} are allowed in a
47@racket[_language] name. These restrictions keep the syntax of
48@hash-lang[] as simple as possible. Keeping the syntax of @hash-lang[]
49simple, in turn, is important because the syntax is inherently
50inflexible and non-extensible; the @hash-lang[] protocol allows a
51@racket[_language] to refine and define syntax in a practically
52unconstrained way, but the @hash-lang[] protocol itself must remain
53fixed so that various different tools can ``boot'' into the extended
54world.
55
56Fortunately, the @hash-lang[] protocol provides a natural way to refer
57to languages in ways other than the rigid @racket[_language] syntax:
58by defining a @racket[_language] that implements its own nested
59protocol. We have already seen one example (in @secref["s-exp"]): the
60@racketmodname[s-exp] @racket[_language] allows a programmer to
61specify a @tech{module language} using the general @tech{module path}
62syntax. Meanwhile, @racketmodname[s-exp] takes care of the
63@tech{reader}-level responsibilities of a @hash-lang[] language.
64
65Unlike @racketmodname[racket], @racketmodname[s-exp] cannot be used as a
66module path with @racket[require]. Although the syntax of
67@racket[_language] for @hash-lang[] overlaps with the syntax of module
68paths, a @racket[_language] is not used directly as a module
69path. Instead, a @racket[_language] obtains a module path by trying two
70locations:  first, it looks for a @racketidfont{reader} submodule of the
71main module for  @racket[_language]. If this is not a valid module path,
72then @racket[_language]  is suffixed with @racketidfont{/lang/reader}.
73(If neither is a valid module path, an error is raised.) The resulting
74module supplies @racketidfont{read} and @racketidfont{read-syntax}
75functions using a protocol that is similar to the one for
76@racketmetafont{#reader}.
77
78@guideother{@secref["hash-reader"] introduces @racketmetafont{#reader}.}
79
80A consequence of the way that a @hash-lang[] @racket[_language] is
81turned into a module path is that the language must be installed in a
82@tech{collection}, similar to the way that @filepath{racket} or
83@filepath{slideshow} are collections that are distributed with Racket.
84Again, however, there's an escape from this restriction: the
85@racketmodname[reader] language lets you specify a @tech{reader}-level
86implementation of a language using a general @tech{module path}.
87
88@; ----------------------------------------
89@section[#:tag "hash-lang reader"]{Using @racket[@#,hash-lang[] @#,racketmodname[reader]]}
90
91The @racketmodname[reader] language for @hash-lang[] is similar to
92@racketmodname[s-exp], in that it acts as a kind of meta-language.
93Whereas @racketmodname[s-exp] lets a programmer specify a @tech{module
94language} at the @tech{expander} layer of parsing,
95@racketmodname[reader] lets a programmer specify a language at the
96@tech{reader} level.
97
98A @racket[@#,hash-lang[] @#,racketmodname[reader]] must be followed by
99a module path, and the specified module must provide two functions:
100@racketidfont{read} and @racketidfont{read-syntax}. The protocol is
101the same as for a @racketmetafont{#reader} implementation, but for
102@hash-lang[], the @racketidfont{read} and @racketidfont{read-syntax}
103functions must produce a @racket[module] form that is based on the
104rest of the input file for the module.
105
106The following @filepath{literal.rkt} module implements a language that
107treats its entire body as literal text and exports the text as a
108@racketidfont{data} string:
109
110@racketmodfile["literal.rkt"]
111
112The @filepath{literal.rkt} language uses @racket[strip-context] on the
113generated @racket[module] expression, because a
114@racketidfont{read-syntax} function should return a syntax object with
115no lexical context. Also, the @filepath{literal.rkt} language creates
116a module named @racketidfont{anything}, which is an arbitrary choice;
117the language is intended to be used in a file, and the longhand module
118name is ignored when it appears in a @racket[require]d file.
119
120The @filepath{literal.rkt} language can be used in a module
121@filepath{tuvalu.rkt}:
122
123@racketmodfile["tuvalu.rkt"]
124
125Importing @filepath{tuvalu.rkt} binds @racketidfont{data} to a
126string version of the module content:
127
128@interaction[
129(require "tuvalu.rkt")
130data
131]
132
133@; ----------------------------------------
134@section[#:tag "syntax/module-reader"]{Using @racket[@#,hash-lang[] @#,racketmodname[s-exp] @#,racketmodname[syntax/module-reader]]}
135
136Parsing a module body is usually not as trivial as in
137@filepath{literal.rkt}. A more typical module parser must iterate to
138parse multiple forms for a module body. A language is also more likely
139to extend Racket syntax---perhaps through a @tech{readtable}---instead
140of replacing Racket syntax completely.
141
142The @racketmodname[syntax/module-reader] @tech{module language}
143abstracts over common parts of a language implementation to simplify
144the creation of new languages. In its most basic form, a language
145implemented with @racketmodname[syntax/module-reader] simply specifies
146the @tech{module language} to be used for the language, in which case
147the @tech{reader} layer of the language is the same as Racket. For
148example, with
149
150@racketmod[
151#:file "raquet-mlang.rkt"
152racket
153(provide (except-out (all-from-out racket) lambda)
154         (rename-out [lambda function]))
155]
156
157and
158
159@racketmod[
160#:file "raquet.rkt"
161s-exp syntax/module-reader
162"raquet-mlang.rkt"
163]
164
165then
166
167@racketmod[
168reader "raquet.rkt"
169(define identity (function (x) x))
170(provide identity)
171]
172
173implements and exports the @racket[identity] function, since
174@filepath{raquet-mlang.rkt} exports @racket[lambda] as
175@racket[function].
176
177The @racketmodname[syntax/module-reader] language accepts many optional
178specifications to adjust other features of the language. For example,
179an alternate @racketidfont{read} and @racketidfont{read-syntax} for
180parsing the language can be specified with @racket[#:read] and
181@racket[#:read-syntax], respectively. The following
182@filepath{dollar-racket.rkt} language uses @filepath{dollar.rkt} (see
183@secref["readtable"]) to build a language that is like
184@racketmodname[racket] but with a @litchar{$} escape to simple infix
185arithmetic:
186
187@racketmodfile["dollar-racket.rkt"]
188
189The @racket[require] form appears at the end of the module,
190because all of the keyword-tagged optional specifications for
191@racketmodname[syntax/module-reader] must appear before any helper
192imports or definitions.
193
194The following module uses @filepath{dollar-racket.rkt} to implement a
195@racket[cost] function using a @litchar{$} escape:
196
197@racketmodfile["store.rkt"]
198
199@; ----------------------------------------
200@section[#:tag "language-collection"]{Installing a Language}
201
202So far, we have used the @racketmodname[reader] meta-language to
203access languages like @filepath{literal.rkt} and
204@filepath{dollar-racket.rkt}. If you want to use something like
205@racket[@#,hash-lang[] literal] directly, then you must move
206@filepath{literal.rkt} into a Racket @tech{collection} named
207@filepath{literal} (see also @secref["link-collection"]).
208Specifically, move @filepath{literal.rkt} to a @racketidfont{reader}
209submodule of @filepath{literal/main.rkt} for any directory name
210@filepath{literal}, like so:
211
212@racketmodfile["literal-main.rkt" "literal/main.rkt"]
213
214Then, install the @filepath{literal}
215directory as a package:
216
217@commandline{cd /path/to/literal ; raco pkg install}
218
219After moving the file and installing the package, you can use
220@racket[literal] directly after @hash-lang[]:
221
222@racketmod[
223@#,racket[literal]
224Technology!
225System!
226Perfect!
227]
228
229@margin-note{See @other-manual['(lib "scribblings/raco/raco.scrbl")]
230for more information on using @exec{raco}.}
231
232You can also make your language available for others to install by
233using the Racket package manager (see @other-doc['(lib
234"pkg/scribblings/pkg.scrbl")]). After you create a @filepath{literal}
235package and register it with the Racket package catalog (see
236@secref["concept:catalog" #:doc '(lib "pkg/scribblings/pkg.scrbl")]),
237others can install it using @exec{raco pkg}:
238
239@commandline{raco pkg install literal}
240
241Once installed, others can invoke the language the same way: by using
242@racket[@#,hash-lang[] literal] at the top of a source file.
243
244If you use a public source repository (e.g., GitHub), you can link
245your package to the source. As you improve the package, others can
246update their version using @exec{raco pkg}:
247
248@commandline{raco pkg update literal}
249
250@margin-note{See @other-doc['(lib "pkg/scribblings/pkg.scrbl")] for more
251information about the Racket package manager.}
252
253@; ----------------------------------------
254@section[#:tag "language-get-info"]{Source-Handling Configuration}
255
256The Racket distribution includes a Scribble language for writing prose
257documents, where Scribble extends the normal Racket to better support
258text. Here is an example Scribble document:
259
260@verbatim[#:indent 2]|{
261#lang scribble/base
262
263@(define (get-name) "Self-Describing Document")
264
265@title[(get-name)]
266
267The title of this document is ``@(get-name).''
268}|
269
270If you put that program in DrRacket's @tech{definitions area} and
271click @onscreen{Run}, then nothing much appears to happen. The
272@racketmodname[scribble/base] language just binds and exports
273@racketidfont{doc} as a description of a document, similar to the way
274that @filepath{literal.rkt} exports a string as @racketidfont{data}.
275
276Simply opening a module with the language
277@racketmodname[scribble/base] in DrRacket, however, causes a
278@onscreen{Scribble HTML} button to appear. Furthermore, DrRacket knows
279how to colorize Scribble syntax by coloring green those parts of the
280document that correspond to literal text. The language name
281@racketmodname[scribble/base] is not hard-wired into
282DrRacket. Instead, the implementation of the
283@racketmodname[scribble/base] language provides button and
284syntax-coloring information in response to a query from DrRacket.
285
286If you have installed the @racket[literal] language as described in
287@secref["language-collection"], then you can adjust
288@filepath{literal/main.rkt} so that DrRacket treats the content
289of a module in the @racket[literal] language as plain text instead of
290(erroneously) as Racket syntax:
291
292@racketmodfile["literal-main-get-info.rkt" "literal/main.rkt"]
293
294This revised @racket[literal] implementation provides a
295@racketidfont{get-info} function. The @racketidfont{get-info} function
296is called by @racket[read-language] (which DrRacket calls) with the
297source input stream and location information,
298in case query results should depend on the content of the module after
299the language name (which is not the case for @racket[literal]). The
300result of @racketidfont{get-info} is a function of two arguments. The
301first argument is always a symbol, indicating the kind of information
302that a tool requests from the language; the second argument is the
303default result to be returned if the language does not recognize the
304query or has no information for it.
305
306After DrRacket obtains the result of @racketidfont{get-info} for a
307language, it calls the function with a @racket['color-lexer] query;
308the result should be a function that implements syntax-coloring
309parsing on an input stream. For @racket[literal], the
310@racketmodname[syntax-color/default-lexer] module provides a
311@racket[default-lexer] syntax-coloring parser that is suitable for
312plain text, so @racket[literal] loads and returns that parser in
313response to a @racket['color-lexer] query.
314
315The set of symbols that a programming tool uses for queries
316is entirely between the tool and the languages that choose to
317cooperate with it. For example, in addition to @racket['color-lexer],
318DrRacket uses a @racket['drracket:toolbar-buttons] query to determine
319which buttons should be available in the toolbar to operate on modules
320using the language.
321
322The @racketmodname[syntax/module-reader] language lets you specify
323@racketidfont{get-info} handling through a @racket[#:info] optional
324specification. The protocol for an @racket[#:info] function is
325slightly different from the raw @racketidfont{get-info} protocol; the
326revised protocol allows @racketmodname[syntax/module-reader] the
327possibility of handling future language-information queries
328automatically.
329
330@; ----------------------------------------
331@section[#:tag "module-runtime-config"]{Module-Handling Configuration}
332
333Suppose that the file @filepath{death-list-5.rkt} contains
334
335@racketmodfile["death-list-5.rkt"]
336
337If you @racket[require] @filepath{death-list-5.rkt} directly, then it
338prints the list in the usual Racket result format:
339
340@interaction[
341(require "death-list-5.rkt")
342]
343
344However, if @filepath{death-list-5.rkt} is required by a
345@filepath{kiddo.rkt} that is implemented with @racketmodname[scheme]
346instead of @racketmodname[racket]:
347
348@racketmodfile["kiddo.rkt"]
349
350then, if you run @filepath{kiddo.rkt} file in DrRacket or if you run it
351directly with @exec{racket}, @filepath{kiddo.rkt} causes
352@filepath{death-list-5.rkt} to print its list in traditional Scheme
353format, without the leading quote:
354
355@racketblock[
356@#,racketoutput{("O-Ren Ishii" "Vernita Green" "Budd" "Elle Driver" "Bill")}
357]
358
359The @filepath{kiddo.rkt} example illustrates how the format for
360printing a result value can depend on the main module of a program
361instead of the language that is used to implement it.
362
363More broadly, certain features of a language are only invoked when
364a module written in that language is run directly with @exec{racket}
365(as opposed to being imported into another module). One example is
366result-printing style (as shown above). Another example is REPL
367behavior. These features are part of what's called the
368@deftech{run-time configuration} of a language.
369
370Unlike the syntax-coloring property of a language (as described in
371@secref["language-get-info"]), the run-time configuration is a
372property of a @emph{module} per se as opposed to a property of
373the @emph{source text} representing the module.
374For that reason, the run-time configuration for a
375module needs to be available even if the module is compiled
376to bytecode form and the source is unavailable. Therefore,
377run-time configuration cannot be handled by the
378@racketidfont{get-info} function we're exporting from the language's
379parser module.
380
381Instead, it will be handled by a new
382@racket[configure-runtime] submodule that we'll add inside
383the parsed @racket[module] form. When a module is run directly
384with @exec{racket}, @exec{racket} looks for a
385@racket[configure-runtime] submodule. If it exists, @exec{racket}
386runs it. But if the module is imported into another module,
387the @racket['configure-runtime] submodule is ignored. (And if the
388@racket[configure-runtime] submodule doesn't exist, @exec{racket}
389just evaluates the module as usual.) That means that the
390@racket[configure-runtime] submodule can be used for any special
391setup tasks that need to happen when the module is run directly.
392
393Going back to the @racket[literal] language (see
394@secref["language-get-info"]), we can adjust the language so that
395directly running a @racket[literal] module causes it to print out its
396string, while using a @racket[literal] module in a larger program
397simply provides @racketidfont{data} without printing. To make this
398work, we will need an extra module. (For clarity here, we will implement
399this module as a separate file. But it could equally well be
400a submodule of an existing file.)
401
402@racketblock[
403.... @#,elem{(the main installation or the user's space)}
404!- @#,filepath{literal}
405   !- @#,filepath{main.rkt}            @#,elem{(with reader submodule)}
406   !- @#,filepath{show.rkt}            @#,elem{(new)}
407]
408
409@itemlist[
410
411 @item{The @filepath{literal/show.rkt} module will provide a
412       @racketidfont{show} function to be applied to the string
413       content of a @racket[literal] module, and also provide a
414       @racketidfont{show-enabled} parameter that controls whether
415       @racketidfont{show} actually prints the result.}
416
417 @item{The new @racket[configure-runtime] submodule in
418       @filepath{literal/main.rkt} will set the
419       @racketidfont{show-enabled} parameter to @racket[#t]. The
420       net effect is that @racketidfont{show} will print the strings
421       that it's given, but only when a module using the @racket[literal]
422       language is run directly (because only then will the
423       @racket[configure-runtime] submodule be invoked).}
424
425]
426
427
428These changes are implemented in the following revised
429@filepath{literal/main.rkt}:
430
431@racketmodfile["literal-main-language-info.rkt" "literal/main.rkt"]
432
433Then the @filepath{literal/show.rkt} module must provide
434the @racketidfont{show-enabled} parameter and @racketidfont{show}
435function:
436
437@racketmod[
438#:file "literal/show.rkt"
439racket
440
441(provide show show-enabled)
442
443(define show-enabled (make-parameter #f))
444
445(define (show v)
446  (when (show-enabled)
447    (display v)))
448]
449
450With all of the pieces for @racket[literal] in place, try running the
451following variant of @filepath{tuvalu.rkt} directly and through a
452@racket[require] from another module:
453
454@racketmod[
455#:file "tuvalu.rkt"
456@#,racket[literal]
457Technology!
458System!
459Perfect!
460]
461
462When run directly, we'll see the result printed like so, because
463our @racket[configure-runtime] submodule will have set the
464@racketidfont{show-enabled} parameter to @racket[#t]:
465
466@racketblock[
467@#,racketoutput{Technology!
468@(linebreak)System!
469@(linebreak)Perfect!}
470]
471
472But when imported into another module, printing will be suppressed,
473because the @racket[configure-runtime] submodule will not be invoked,
474and therefore the @racketidfont{show-enabled} parameter will remain
475at its default value of @racket[#f].
476