chain-module-begin.scrbl (2775B)
1 #lang scribble/manual 2 @require[@for-label[chain-module-begin 3 racket/base]] 4 5 @title{Chaining module languages} 6 @author[@author+email["Suzanne Soy" "racket@suzanne.soy"]] 7 8 @defmodule[chain-module-begin] 9 10 This package is experimental. Later versions may break backward-compatibility. 11 12 @defform[(chain-module-begin lang . body)]{ 13 This macro is intended to be used as the result of a @racket[#%module-begin] 14 macro. It chain-calls the @racket[#%module-begin] of @racket[lang]. This makes 15 it possible for a @racket[#%module-begin] to perform some changes on its body, 16 and then chain-call the @racket[#%module-begin] of a user-specified language. 17 18 As an example here is the definition for a no-op language, which simply takes a 19 (possibly improper) list of languages to chain, and calls the next one: 20 21 @racketblock[ 22 (module the-meta-lang racket/base 23 (provide (rename-out [new-#%module-begin #%module-begin])) 24 25 (require chain-module-begin 26 (for-syntax racket/base 27 syntax/parse)) 28 29 (define-syntax (new-#%module-begin stx) 30 (syntax-parse stx 31 [(_ {~or next-lang:id (next-lang:id . chain₊)} . body) 32 (define maybe-chain₊ (if (attribute chain₊) 33 `(,#'chain₊) 34 '())) 35 (define new-form `(,#'chain-module-begin ,#'next-lang ,@maybe-chain₊ 36 . ,(transform-body #'body))) 37 (datum->syntax stx new-form stx stx)])) 38 39 (define-for-syntax (transform-body body) 40 (code:comment "identity transformation:") 41 body))] 42 43 This language could then be used as follows: 44 45 @racketblock[ 46 (module b the-meta-lang typed/racket 47 (define x : Number 123))] 48 49 Given two other meta-language built in the same way and provided by 50 @racketid[meta-two] and @racketid[meta-three], it would be possible 51 to chain the three languages as follows: 52 53 @racketblock[ 54 (module b the-lang (meta-two meta-three . typed/racket) 55 (define x : Number 123))] 56 57 The @racket[chain-module-begin] macro produces the following syntax: 58 59 @racketblock[(#%plain-module-begin 60 (require lang) 61 (continue . internal-args))] 62 63 where @racket[(continue . _internal-args)] fully expands 64 @racket[(#%module-begin . body)], where @racket[#%module-begin] is the one 65 provided by @racket[lang], and produces the following syntax: 66 67 @racketblock[(begin . _expanded-body)] 68 69 An extra scope is added to the whole @racket[(begin . _expanded-body)] form, 70 so that a @racket[#%require] form within the @racket[_expanded-body] may 71 shadow bindings provided by @racket[lang], just as @racket[require] forms 72 normally have the possibility to shadow bindings provided by the @(hash-lang) 73 language.}