{"size": 5221, "ext": "scrbl", "max_stars_repo_path": "redex-doc/redex/scribblings/ref/typesetting-and-macros.scrbl", "max_stars_repo_name": "LiberalArtist/redex", "max_stars_repo_stars_event_min_datetime": "2018-07-29T04:13:52.000Z", "max_stars_repo_stars_event_max_datetime": "2022-02-14T16:11:17.000Z", "max_issues_repo_path": "redex-doc/redex/scribblings/ref/typesetting-and-macros.scrbl", "max_issues_repo_name": "LiberalArtist/redex", "max_issues_repo_issues_event_min_datetime": "2017-08-25T20:26:37.000Z", "max_issues_repo_issues_event_max_datetime": "2022-02-26T17:48:40.000Z", "max_forks_repo_path": "redex-doc/redex/scribblings/ref/typesetting-and-macros.scrbl", "max_forks_repo_name": "LiberalArtist/redex", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 10, "max_issues_count": 15, "max_forks_count": null, "avg_line_length": 38.3897058824, "max_line_length": 80, "alphanum_fraction": 0.4439762498}
#lang scribble/base

@(require scribble/manual
          scribble/bnf
          scribble/struct
          scribble/example
          scribble/racket
          (for-syntax racket/base)
          (for-label racket/base
                     (except-in racket/gui make-color)
                     racket/pretty
                     racket/contract
                     mrlib/graph
                     (except-in 2htdp/image make-pen text)
                     (only-in pict pict? text dc-for-text-size text-style/c
                              vc-append)
                     redex))

@(define redex-macros-eval (make-base-eval '(require redex/reduction-semantics
                                                     redex/pict
                                                     (for-syntax racket/base))))

@title{Macros and Typesetting}

When you have a macro that abstracts over variations in 
Redex programs, then typesetting is unlikely to work
without some help from your macros.

To see the issue, consider this macro abstraction over
a Redex grammar:
@examples[#:label #f #:eval redex-macros-eval
          (define-syntax-rule
            (def-my-lang L prim ...)
            (define-language L
              (e ::=
                 (λ (x) e)
                 (e e)
                 prim ...
                 x)
              (x ::= variable-not-otherwise-mentioned)))

          (def-my-lang L + - *)
          (eval:error (render-language L))]
Redex thinks that the grammar is going ``backwards'' because 
of the way macro expansion synthesizes source locations.
In particular, in the result of the macro expansion, the
third production for @racket[_e] appears to come later
in the file than the fourth production and this confuses
Redex, making it unable to typeset this language.

One simple, not-very-general work-around is to just avoid 
typesetting the parts that come from the macro arguments. For
example if you move the primitives into their own non-terminal
and then just avoid typesetting that, Redex can cope:

@examples[#:label #f #:no-prompt #:eval redex-macros-eval
          (define-syntax-rule
            (def-my-lang/separate-prims L prim ...)
            (define-language L
              (e ::=
                 (λ (x) e)
                 (e e)
                 prims
                 x)
              (prims ::= prim ...)
              (x ::= variable-not-otherwise-mentioned)))]

@examples[#:label #f #:eval redex-macros-eval
                  #:no-prompt
          (def-my-lang/separate-prims L + - *)]
@examples[#:label #f #:eval redex-macros-eval
          (render-language L #:nts '(e x))]

You can also, however, exploit Racket's macro system to rewrite the
source locations in a way that tells Redex where the macro-introduced
parts of the language are supposed to be, and then typesetting
will work normally. For example, here is one way to do this with
the original language:

@(require redex/reduction-semantics (for-syntax racket/base))
@examples[#:eval redex-macros-eval #:label #f #:no-prompt
          (define-syntax (def-my-lang stx)
            (syntax-case stx ()
              [(_ L a ...)
               (let ()
                 (define template
                   #'(define-language L
                       (e (λ (x) e)
                          (e e)
                          HERE
                          x)
                       (x variable-not-otherwise-mentioned)))
                 (car
                  (let loop ([stx template])
                    (syntax-case stx (HERE)
                      [HERE
                       (let loop ([as (syntax->list #'(a ...))]
                                  [pos (syntax-position stx)]
                                  [col (syntax-column stx)])
                         (cond
                           [(null? as) '()]
                           [else 
                            (define a (car as))
                            (define span 
                              (string-length
                               (symbol->string (syntax-e a))))
                            (define srcloc
                              (vector (syntax-source stx)
                                      (syntax-line stx)
                                      col
                                      pos
                                      span))
                            (cons
                             (datum->syntax a 
                                            (syntax-e a)
                                            srcloc
                                            a)
                             (loop (cdr as)
                                   (+ pos span 1)
                                   (+ col span 1)))]))]
                      [(a ...)
                       (list
                        (datum->syntax
                         stx
                         (apply append (map loop (syntax->list #'(a ...))))
                         stx
                         stx))]
                      [a
                       (list stx)]))))]))]

@examples[#:label #f #:eval redex-macros-eval
          (def-my-lang L + - *)]
@examples[#:label #f #:eval redex-macros-eval
          (render-language L)]

