On this page:
with-unquote-rewriter
with-atomic-rewriter
with-compound-rewriter
9.1 LW
build-lw
lw-e
lw-line
lw-line-span
lw-column
lw-column-span
lw?
lw
to-lw
render-lw
lw->pict
just-before
just-after

9 Removing the pink background from PLT Redex rendered picts and ps files

When reduction rules, a metafunction, or a grammar contains unquoted Racket code or side-conditions, they are rendered with a pink background as a guide to help find them and provide alternative typesettings for them. In general, a good goal for a PLT Redex program that you intend to typeset is to only include such things when they correspond to standard mathematical operations, and the Racket code is an implementation of those operations.

To replace the pink code, use:

(with-unquote-rewriter proc expression)
It installs proc the current unqoute rewriter and evaluates expression. If that expression computes any picts, the unquote rewriter specified is used to remap them.

The proc should be a function of one argument. It receives a lw struct as an argument and should return another lw that contains a rewritten version of the code.

(with-atomic-rewriter name-symbol
                      string-or-thunk-returning-pict
                      expression)
This extends the current set of atomic-rewriters with one new one that rewrites the value of name-symbol to string-or-pict-returning-thunk (applied, in the case of a thunk), during the evaluation of expression.

name-symbol is expected to evaluate to a symbol. The value of string-or-thunk-returning-pict is used whever the symbol appears in a pattern.

(with-compound-rewriter name-symbol
                        proc
                        expression)
This extends the current set of compound-rewriters with one new one that rewrites the value of name-symbol via proc, during the evaluation of expression.

name-symbol is expected to evaluate to a symbol. The value of proc is called with a (listof lw), and is expected to return a new (listof (or/c lw? string? pict?)), rewritten appropriately.

The list passed to the rewriter corresponds to the lw for the sequence that has name-symbol’s value at its head.

The result list is constrained to have at most 2 adjacent non-lws. That list is then transformed by adding lw structs for each of the non-lws in the list (see the description of lw below for an explanation of logical-space):

9.1 LW

(build-lw e line line-span column column-span)  lw?
  e : 
(or/c string?
      symbol?
      pict?
      (listof (or/c (symbols 'spring) lw?)))
  line : exact-positive-integer?
  line-span : exact-positive-integer?
  column : exact-positive-integer?
  column-span : exact-positive-integer?
(lw-e lw)  
(or/c string?
      symbol?
      pict?
      (listof (or/c (symbols 'spring) lw?)))
  lw : lw?
(lw-line lw)  exact-positive-integer?
  lw : lw?
(lw-line-span lw)  exact-positive-integer?
  lw : lw?
(lw-column lw)  exact-positive-integer?
  lw : lw?
(lw-column-span lw)  exact-positive-integer?
  lw : lw?
(lw? v)  boolean?
  v : any/c
lw
The lw data structure corresponds represents a pattern or a Racket expression that is to be typeset. The functions listed above construct lw structs, select fields out of them, and recognize them. The lw binding can be used with copy-struct.

(to-lw arg)
This form turns its argument into lw structs that contain all of the spacing information just as it would appear when being used to typeset.

Each sub-expression corresponds to its own lw, and the element indicates what kind of subexpression it is. If the element is a list, then the lw corresponds to a parenthesized sequence, and the list contains a lw for the open paren, one lw for each component of the sequence and then a lw for the close parenthesis. In the case of a dotted list, there will also be a lw in the third-to-last position for the dot.

For example, this expression:

  (a)

becomes this lw (assuming the above expression appears as the first thing in the file):

  (build-lw (list (build-lw "(" 0 0 0 1)
                           (build-lw 'a 0 0 1 1)
                           (build-lw ")" 0 0 2 1))
                     0 0 0 3)

If there is some whitespace in the sequence, like this one:

  (a b)

then there is no lw that corresponds to that whitespace; instead there is a logical gap between the lws.

  (build-lw (list (build-lw "(" 0 0 0 1)
                  (build-lw 'a 0 0 1 1)
                  (build-lw 'b 0 0 3 1)
                  (build-lw ")" 0 0 4 1))
            0 0 0 5)

In general, identifiers are represented with symbols and parenthesis are represented with strings and picts can be inserted to render arbitrary pictures.

The line, line-span, column, and column-span correspond to the logical spacing for the redex program, not the actual spacing that will be used when they are rendered. The logical spacing is only used when determining where to place typeset portions of the program. In the absense of any rewriters, these numbers correspond to the line and column numbers in the original program.

The line and column are absolute numbers from the beginning of the file containing the expression. The column number is not necessarily the column of the open parenthesis in a sequence – it is the leftmost column that is occupied by anything in the sequence. The line-span is the number of lines, and the column span is the number of columns on the last line (not the total width).

When there are multiple lines, lines are aligned based on the logical space (ie, the line/column & line-span/column-span) fields of the lws. As an example, if this is the original pattern:

  (all good boys
       deserve fudge)

then the leftmost edges of the words "good" and "deserve" will be lined up underneath each other, but the relative positions of "boys" and "fudge" will be determined by the natural size of the words as they rendered in the appropriate font.

When 'spring appears in the list in the e field of a lw struct, then it absorbs all of the space around it. It is also used by to-lw when constructing the picts for unquoted strings. For example, this expression

  ,x

corresponds to these structs:

  (build-lw (list (build-lw "" 1 0 9 0)
                  'spring
                  (build-lw x 1 0 10 1))
            1 0 9 2)

and the 'spring causes there to be no space between the empty string and the x in the typeset output.

(render-lw language/nts lw)  pict?
  language/nts : (or/c (listof symbol?) compiled-lang?)
  lw : lw?
Produces a pict that corresponds to the lw object argument, using language/nts to determine which of the identifiers in the lw argument are non-terminals.

This function sets dc-for-text-size. See also lw->pict.

(lw->pict language/ntw lw)  pict?
  language/ntw : (or/c (listof symbol?) compiled-lang?)
  lw : lw?
Produces a pict that corresponds to the lw object argument, using language/nts to determine which of the identifiers in the lw argument are non-terminals.

This does not set the dc-for-text-size parameter. See also render-lw.

(just-before stuff lw)  lw?
  stuff : (or/c pict? string? symbol?)
  lw : lw?
(just-after stuff lw)  lw?
  stuff : (or/c pict? string? symbol?)
  lw : lw?
These two helper functions build new lws whose contents are the first argument, and whose line and column are based on the second argument, making the new loc wrapper be either just before or just after that argument. The line-span and column-span of the new lw is always zero.