2.1Patterns

This section covers Redex’s pattern language, used in many
of Redex’s forms.

Note that pattern matching is caching (including caching the results
of side-conditions). This means that once a pattern has matched a
given term, Redex assumes that it will always match that term.

This is the grammar for the Redex pattern language. Non-terminal
references are wrapped with angle brackets; otherwise identifiers
in the grammar are terminals.

pattern

=

any

|

_

|

number

|

natural

|

integer

|

real

|

string

|

boolean

|

variable

|

(variable-except<id>...)

|

(variable-prefix<id>)

|

variable-not-otherwise-mentioned

|

hole

|

symbol

|

(name<id><pattern>)

|

(in-hole<pattern><pattern>)

|

(hide-hole<pattern>)

|

(side-condition<pattern>guard)

|

(cross<id>)

|

(<pattern-sequence>...)

|

<racket-constant>

pattern-sequence

=

<pattern>

|

...;literal ellipsis

|

..._id

The anypattern matches any sexpression.
This pattern may also be suffixed with an underscore and another
identifier, in which case they bind the full name (as if it
were an implicit namepattern) and match the portion
before the underscore.

The _pattern matches any sexpression,
but does not bind _ as a name, nor can it be suffixed to bind a name.

The numberpattern matches any number.
This pattern may also be suffixed with an underscore and another
identifier, in which case they bind the full name (as if it
were an implicit namepattern) and match the portion
before the underscore.

The naturalpattern matches any exact
non-negative integer.
This pattern may also be suffixed with an underscore and another
identifier, in which case they bind the full name (as if it
were an implicit namepattern) and match the portion
before the underscore.

The integerpattern matches any exact integer.
This pattern may also be suffixed with an underscore and another
identifier, in which case they bind the full name (as if it
were an implicit namepattern) and match the portion
before the underscore.

The realpattern matches any real number.
This pattern may also be suffixed with an underscore and another
identifier, in which case they bind the full name (as if it
were an implicit namepattern) and match the portion
before the underscore.

The stringpattern matches any string.
This pattern may also be suffixed with an underscore and another
identifier, in which case they bind the full name (as if it
were an implicit namepattern) and match the portion
before the underscore.

The booleanpattern matches #true and #false
(which are the same as #t and #f, respectively).
This pattern may also be suffixed with an underscore and another
identifier, in which case they bind the full name (as if it
were an implicit namepattern) and match the portion
before the underscore.

The variablepattern matches any symbol.
This pattern may also be suffixed with an underscore and another
identifier, in which case they bind the full name (as if it
were an implicit namepattern) and match the portion
before the underscore.

The variable-exceptpattern matches any symbol except those
listed in its argument. This is useful for ensuring that
keywords in the language are not accidentally captured by
variables.

The variable-prefixpattern matches any symbol
that begins with the given prefix.

The variable-not-otherwise-mentionedpattern matches any
symbol except those that are used as literals elsewhere in
the language.

The symbolpattern stands for a literal symbol that must
match exactly, unless it is the name of a non-terminal in a
relevant language or contains an underscore.

If it is a non-terminal, it matches any of the right-hand
sides of that non-terminal. If the non-terminal appears
twice in a single pattern, then the match is constrained
to expressions that are the same, unless the pattern is part
of a grammar, in which case there is no constraint.

If the symbol is a non-terminal followed by an underscore,
for example e_1, it is implicitly the same as a name pattern
that matches only the non-terminal, (name e_1 e) for the
example. Accordingly, repeated uses of the same name are
constrained to match the same expression.

If the symbol is a non-terminal followed by _!_, for example
e_!_1, it is also treated as a pattern, but repeated uses of
the same pattern are constrained to be different. For
example, this pattern:

(e_!_1e_!_1e_!_1)

matches lists of three es, but where all three of them are
distinct.

If the _!_ is used under the ellipsis then the ellipsis is effectively
ignored. That is, a pattern like this:

The (side-conditionpattern guard)pattern
matches what the embedded pattern matches, and then the guard
expression is evaluated. If it returns #f, the pattern fails
to match, and if it returns anything else, the pattern matches. Any
occurrences of name in the pattern (including those implicitly
there via _ patterns) are bound using term-let in the
guard.

The (cross symbol)pattern is used for the compatible
closure functions. If the language contains a non-terminal with the
same name as symbol, the pattern(crosssymbol) matches the
context that corresponds to the compatible closure of that
non-terminal.

The (pattern-sequence ...)pattern matches a sexpression
list, where each pattern-sequence element matches an element
of the list. In addition, if a list pattern contains an
ellipsis, the ellipsis is not treated as a literal, instead
it matches any number of duplicates of the pattern that
came before the ellipses (including 0). Furthermore, each
(name symbol pattern) in the duplicated pattern binds a
list of matches to symbol, instead of a single match. (A
nested duplicated pattern creates a list of list matches,
etc.) Ellipses may be placed anywhere inside the row of
patterns, except in the first position or immediately after
another ellipses.

three different ways. One where the first a in the pattern
matches nothing, and the second matches both of the
occurrences of a, one where each named pattern matches a
single a and one where the first matches both and the
second matches nothing.

If the ellipses is named (i.e., has an underscore and a name
following it, like a variable may), the pattern matcher
records the length of the list and ensures that any other
occurrences of the same named ellipses must have the same
length.

If redex-match receives three arguments, it
matches the pattern (in the language) against its third
argument. If it matches, this returns a list of match
structures describing the matches (see match? and
match-bindings). If it fails, it returns
#f.

If redex-match receives only two arguments, it
builds a procedure for efficiently testing if expressions
match the pattern, using the language lang. The
procedures accepts a single expression and if the expression
matches, it returns a list of match structures describing the
matches. If the match fails, the procedure returns #f.

Instances of this struct are returned by redex-match.
Each bind associates a name with an s-expression from the
language, or a list of such s-expressions, if the (name ...)
clause is followed by an ellipsis. Nested ellipses produce
nested lists.

When this parameter is #t (the default), Redex caches the results of
pattern matching and metafunction evaluation. There is a separate cache for
each pattern and metafunction; when one fills (see set-cache-size!),
Redex evicts all of the entries in that cache.

Caching should be disabled when matching a pattern that depends on values
other than the in-scope pattern variables or evaluating a metafunction
that reads or writes mutable external state.

Ambiguous patterns can slow down
Redex’s pattern matching implementation significantly. To help debug
such performance issues, set the check-redundancy
parameter to #t. This causes Redex to, at runtime,
report any redundant matches that it encounters.

2.2Terms

Object language expressions in Redex are written using
term. It is similar to Racket’s quote (in
many cases it is identical) in that it constructs lists as
the visible representation of terms.

The grammar of terms is (note that an ellipsis
stands for repetition unless otherwise indicated):

It behaves similarly to quasiquote, except for a few special
forms that are recognized (listed below) and that names bound by
term-let are implicitly substituted with the values that
those names were bound to, expanding ellipses as in-place sublists (in
the same manner as syntax-case patterns).

The optional #:lang keyword must supply an identifier bound
by define-language, and adds a check that any symbol containing
an underscore in term could have been bound by a pattern in the
language referenced by lang-id. In practice, this means that the
underscore must be preceded by a non-terminal in that language or a
built-in pattern such as number. This form of term
is used internally by default, so this check is applied to terms
that are constructed by Redex forms such as reduction-relation
and define-metafunction.

It is an error for a term variable to appear in an
expression with an ellipsis-depth different from the depth
with which it was bound by term-let. It is also an error
for two term-let-bound identifiers bound to lists of
different lengths to appear together inside an ellipsis.

Matches each given id pattern to the value yielded by
evaluating the corresponding expression and binds each variable in
the id pattern to the appropriate value (described
below). These bindings are then accessible to the term
syntactic form.

Note that each ellipsis should be the literal symbol consisting of
three dots (and the ... elsewhere indicates repetition as usual). If
tl-pat is an identifier, it matches any value and binds it to
the identifier, for use inside term. If it is a list, it
matches only if the value being matched is a list value and only if
every subpattern recursively matches the corresponding list
element. There may be a single ellipsis in any list pattern; if one is
present, the pattern before the ellipses may match multiple adjacent
elements in the list value (possibly none).

This produces a procedure that accepts term (or quoted)
expressions and checks them against each pattern. The
function returns a list of the values of the expression
where the pattern matches. If one of the patterns matches
multiple times, the expression is evaluated multiple times,
once with the bindings in the pattern for each match.

When evaluating a term-match expression, the patterns are
compiled in an effort to speed up matching. Using the procedural
result multiple times to avoid compiling the patterns multiple times.

This produces a procedure that accepts term (or quoted)
expressions and checks them against each pattern. The
function returns the expression behind the first successful
match. If that pattern produces multiple matches, an error
is signaled. If no patterns match, an error is signaled.

Raises an exception recognized by exn:fail:redex? if
no clauses match or if one of the clauses matches multiple ways.

When evaluating a term-match/single expression, the patterns
are compiled in an effort to speed up matching. Using the procedural
result multiple times to avoid compiling the patterns multiple times.

The first argument to this function is an sexpression to
plug into. The second argument is the sexpression to replace
in the first argument. It returns the replaced term. This is
also used when a term sub-expression contains in-hole.

2.3Languages

This form defines the grammar of a language. It allows the
definition of recursive patterns, much like a BNF, but for
regular-tree grammars. It goes beyond their expressive
power, however, because repeated namepatterns and
side-conditions can restrict matches in a context-sensitive
way.

A non-terminal-def comprises one or more non-terminal names
(considered aliases) followed by one or more productions.

For example, the following defines lc-lang as the
grammar of the λ-calculus:

extends lc-lang with two new alternatives (+ and number)
for the v non-terminal, carries forward the e
and c non-terminals, and replaces the x non-terminal
with a new one (which happens to be equivalent to the one that would
have been inherited).

The four-period ellipses indicates that the new language’s
non-terminal has all of the alternatives from the original
language’s non-terminal, as well as any new ones. If a
non-terminal occurs in both the base language and the
extension, the extension’s non-terminal replaces the
originals. If a non-terminal only occurs in either the base
language, then it is carried forward into the
extension. And, of course, extend-language lets you add new
non-terminals to the language.

If a language is has a group of multiple non-terminals
defined together, extending any one of those non-terminals
extends all of them.

If a language has a prefix, then all of the non-terminals
from that language have the corresponding prefix in
the union language. The prefix helps avoid unintended collisions
between the constituent language’s non-terminals.

Defines a reduction relation case-wise, one case for each of the
reduction-case clauses.

The optional domain clause provides a contract for the
relation, in the form of a pattern that defines the relation’s
domain and codomain.

The arrow-name in each reduction-case clause is either
base-arrow-name (default -->) or an arrow name
defined by shortcuts (described below). In either case,
the pattern refers to language and binds variables in
the corresponding term. Following the pattern and term
can be the name of the reduction rule and declarations of fresh
variables and side-conditions.

Fresh variable clauses generate variables that do not
occur in the term being reduced. If the fresh-clause is a
variable, that variable is used both as a binding in the
term and as the prefix for the freshly generated
variable. (The variable does not have to be
a non-terminal in the language of the reduction relation.)

The second form of fresh-clauses generates
a sequence of variables. In that case, the ellipses
are literal ellipses; that is, you must actually write
ellipses in your rule. The variable var1 is like the
variable in first case of a fresh-clause; namely it is
used to determine the prefix of the generated variables and
it is bound in the right-hand side of the reduction rule,
but unlike the single-variable fresh clause, it is bound to
a sequence of variables. The variable var2 is used to
determine the number of variables generated and var2 must be
bound by the left-hand side of the rule.

The expressions within side-condition clauses
and side-condition/hidden clauses are collected with and and
used as guards on the case being matched. The argument to each
side-condition should be a Racket expression, and the pattern
variables in the pattern are bound in that expression. A
side-condition/hidden clause is the same as
a side-condition clause, except that the condition is not
rendered when typesetting via redex/pict.

Each where clause acts as a side condition requiring a
successful pattern match, and it can bind pattern variables in the
side-conditions (and where clauses) that follow and in the
metafunction result. The bindings are the same as bindings in a
term-let expression. A where/hidden clause is the
same as a where clause, but the clause is not
rendered when typesetting via redex/pict.

Each judgment-holds clause acts like a where clause, where
the left-hand side pattern incorporates each of the patterns used in the
judgment form’s output positions.

Each shortcut clause defines arrow names in terms of
base-arrow-name and earlier shortcut definitions.
The left- and right-hand sides of a shortcut definition
are identifiers, not patterns and terms. These identifiers
need not correspond to non-terminals in language.

This form extends the reduction relation in its first
argument with the rules specified in more. They should
have the same shape as the rules (including the with
clause) in an ordinary reduction-relation.

If the original reduction-relation has a rule with the same
name as one of the rules specified in the extension, the old
rule is removed.

In addition to adding the rules specified to the existing
relation, this form also reinterprets the rules in the
original reduction, using the new language.

This accepts a reduction, a language, a pattern representing
a context (i.e., that can be used as the first argument to
in-hole; often just a non-terminal) in the language and
returns the closure of the reduction in that context.

Accepts a reduction relation and a
term. Starting from t, it follows every reduction
path and returns all of the terms that do not reduce further.
If there are infinite reduction
sequences that do not repeat, this function will not
terminate (it does terminate if the only infinite reduction paths are cyclic).

If the cache-all? argument is #t, then apply-reduction-relation*
keeps a cache of all visited terms when traversing the graph and does not revisit
any of them. This cache can, in some cases, use a lot of memory, so it is off by
default and the cycle checking happens by keeping track only of the current path
it is traversing through the reduction graph.

The stop-when argument controls the stopping criterion. Specifically, it is
called with each term that apply-reduction-relation* encounters. If it
ever returns a true value (anything except #f), then apply-reduction-relation*
considers the term to be irreducible (and so returns it and does not try to
reduce it further).

The define-metafunction form builds a function on
sexpressions according to the pattern and right-hand-side
expressions. The first argument indicates the language used
to resolve non-terminals in the pattern expressions. Each of
the rhs-expressions is implicitly wrapped in term.

The contract, if present, is matched against every input to
the metafunction and, if the match fails, an exception is raised.
If present, the term inside the maybe-pre-condition is evaluated
after a successful match to the input pattern in the contract (with
any variables from the input contract bound). If
it returns #f, then the input contract is considered to not
have matched and an error is also raised. When a metafunction
returns, the expression in the maybe-post-condition is
evaluated (if present), with any variables from the input or output
contract bound.

The side-condition, hidden-side-condition,
where, and where/hidden clauses behave as
in the reduction-relation form.

The resulting metafunction raises an exception recognized by exn:fail:redex? if
no clauses match or if one of the clauses matches multiple ways
(and that leads to different results for the different matches).

The side-condition extra is evaluated after a successful match
to the corresponding argument pattern. If it returns #f,
the clause is considered not to have matched, and the next one is tried.
The side-condition/hidden extra behaves the same, but is
not typeset.

The where and where/hidden extra are like
side-condition and side-condition/hidden,
except the match guards the clause.

The judgment-holds clause is like side-condition
and where, except the given judgment must hold for the
clause to be taken.

Note that metafunctions are assumed to always return the same results
for the same inputs, and their results are cached, unless
caching-enabled? is set to #f. Accordingly, if a
metafunction is called with the same inputs twice, then its body is
only evaluated a single time.

As an example, these metafunctions finds the free variables in
an expression in the lc-lang above:

The first argument to define-metafunction is the grammar
(defined above). Following that are three cases, one for
each variation of expressions (e in lc-lang). The free variables of an
application are the free variables of each of the subterms;
the free variables of a variable is just the variable
itself, and the free variables of a λ expression are
the free variables of the body, minus the bound parameters.

Defines a metafunction g as an extension of an existing
metafunction f. The metafunction g behaves as
if f’s clauses were appended to its definition (with
occurrences of f changed to g in the inherited
clauses).

For example, define-metafunction/extension may be used to extend
the free-vars function above to the forms introduced by the language
lc-num-lang.

Defines form-id as a relation on terms via a set of inference rules.
Each rule must be such that its premises can be evaluated left-to-right
without “guessing” values for any of their pattern variables. Redex checks this
property using the mandatory mode-spec declaration, which partitions positions
into inputs I and outputs O. Output positions in conclusions
and input positions in premises must be terms; input positions in conclusions and
output positions in premises must be patterns. When the optional contract-spec
declaration is present, Redex dynamically checks that the terms flowing through
these positions match the provided patterns, raising an exception recognized by
exn:fail:redex if not. The term in the optional invariant-spec is
evaluated after the output positions have been computed and the contract has matched
successfully, with variables from the contract bound; a result of #f is
considered to be a contract violation and an exception is raised.

A rule’s side-condition and side-condition/hidden premises are similar
to those in reduction-relation and define-metafunction, except that
they do not implicitly unquote their right-hand sides. In other words, a premise
of the form (side-conditionterm) is equivalent to the premise
(where#tterm), except it does not typeset with the “#t = ”, as that would.

Judgments with exclusively I mode positions may also be used in terms
in a manner similar to metafunctions, and evaluate to a boolean.

"typing-rules.rkt" —
defines a type system in a way that supports mechanized typesetting.
When a typing judgment form can be given a mode, it can also be encoded as
a metafunction using where clauses as premises, but Redex
cannot typeset that encoding as inference rules.

"sos.rkt" —
defines an SOS-style semantics in a way that supports mechanized typesetting.

"multi-val.rkt" —
defines a judgment form that serves as a multi-valued metafunction.

In its first form, checks whether judgment holds for any assignment of
the pattern variables in judgment-id’s output positions. In its second
form, produces a list of terms by instantiating the supplied term template with
each satisfying assignment of pattern variables.

The term field holds an s-expression based rendering of the
conclusion of the derivation, the name field holds the name
of the clause with term as the conclusion, and
subs contains the sub-derivations.

Similar to define-judgment-form but suitable only when every position
is an input. There is no associated form corresponding to
judgment-holds; querying the result uses the same syntax as
metafunction application.

The contract specification for a relation restricts the patterns that can
be used as input to a relation. For each argument to the relation, there
should be a single pattern, using x or × to separate
the argument contracts.

Controls which metafunctions are currently being traced. If it is
'all, all of them are. Otherwise, the elements of the list
name the metafunctions to trace.

The tracing looks just like the tracing done by the racket/trace
library, except that the first column printed by each traced call indicate
if this call to the metafunction is cached. Specifically, a c is printed
in the first column if the result is just returned from the cache and a
space is printed if the metafunction call is actually performed.

Tests to see if the term e1-expr,
reduces to the terms e2-expr under rel-expr,
using pred-expr to determine equivalence.

If #:pred is specified, it is applied to each reachable term
until one of the terms fails to satisfy the predicate (i.e., the
predicate returns #f). If that happens, then the test fails
and a message is printed with the term that failed to satisfy the
predicate.

This test uses
apply-reduction-relation*, so it does not terminate
when the resulting reduction graph is infinite, although it
does terminate if there are cycles in the (finite) graph.

If #:cycles-ok is not supplied then any cycles detected
are treated as a test failure. If a pred-expr is supplied,
then it is used to compare the expected and actual results. If it
isn’t supplied, then (default-equiv) is used.

Tests to see if the term start-expr reduces according to the reduction
relation rel-expr to a term specified by goal-expr in
steps-expr or fewer steps (default 1,000). The specification
goal-expr may be either a predicate on terms or a term itself.

Extracts the coverage information recorded in c, producing
an association list mapping names (or source locations, in the case of
metafunctions or unnamed reduction-relation cases) to application counts.

from-pattern:
In the first case, randomly makes an expression matching the given pattern
whose size is bounded by size-expr; the second returns a function
that accepts a size bound and returns a random term. Calling this function
(even with the same size bound) may be more efficient than using the first case.

The #:i-th option uses an enumeration of the non-terminals in a language.
If index-expr is supplied, generate-term returns the corresponding
term and if it isn’t, generate-term returns a function from indices
to terms.

The string enumeration produces all single character strings before
going on to strings with multiple characters. For each character it starts
the lowercase Latin characters, then uppercase Latin, and then every remaining
Unicode character. The variable enumeration is the same, except it
produces symbols instead of strings.

In addition, all other pattern types are supported
except for mismatch repeat ..._!_ patterns
and side-condition patterns.

The enumerators do not repeat terms unless the given pattern is ambiguous.
Roughly speaking, the enumerator generates all possible ways that a pattern
might be parsed and since ambiguous patterns have multiple ways they might
be parsed, those multiple parsings turn into repeated elements in the enumeration.

In this case, the elements of the resulting list are the same,
even though they should not be, according to the pattern. Internally,
the enumerator has discovered two different ways to generate ambig
(one where the x comes from the first ellipses and one from the second)
but those two different ways produce the same term and so the enumerator
incorrectly produces (xx).

from-judgment-form: Randomly picks a term that satisfies
the given use of the judgment form.

from-metafunction: The first form randomly picks a term
that satisfies the given invocation of the metafunction, using
techniques similar to how the from-judgment-form case works.
The second form uses a more naive approach; it simply generates terms
that match the patterns of the cases of the metafunction; it does not
consider the results of the metafunctions, nor does it consider
patterns from earlier cases when generating terms based on a particular case.
The third case is like the second, except it returns a function that accepts
the size and keywords arguments that may be more efficient if multiple
random terms are generated.

from-reduction-relation: In the first case, generate-term
randomly picks a rule from the reduction relation and tries to pick a term
that satisfies its domain pattern, returning that. The second case returns
a function that accepts the size and keyword arguments that may be more
efficient if multiple random terms are generated.

The argument size-expr bounds the height of the generated term
(measured as the height of its parse tree).

The optional keyword argument attempt-num-expr
(default 1) provides coarse grained control over the random
decisions made during generation; increasing attempt-num-expr
tends to increase the complexity of the result. For example, the absolute
values of numbers chosen for integer patterns increase with
attempt-num-expr.

The random generation process does not actively consider the constraints
imposed by side-condition or _!_patterns; instead,
it uses a “guess and check” strategy in which it freely generates
candidate terms then tests whether they happen to satisfy the constraints,
repeating as necessary. The optional keyword argument retries-expr
(default 100) bounds the number of times that
generate-term retries the generation of any pattern. If
generate-term is unable to produce a satisfying term after
retries-expr attempts, it raises an exception recognized by
exn:fail:redex:generation-failure?.

Searches for a counterexample to property-expr, interpreted
as a predicate universally quantified over the pattern variables
bound by the pattern(s) in template.
redex-check constructs and tests
a candidate counterexample by choosing a random term t based
on template and then evaluating property-expr
using the match-bindings produced by matching
t against pattern. The form of template controls
how t is generated:

languagepattern:
In this case, redex-check uses an ad hoc strategy for
generating pattern. For the first 10 seconds, it uses
in-order enumeration to pick terms. After that, it
alternates back and forth between in-order enumeration
and the ad hoc random generator. After the 10 minute mark,
it switches over to using just the ad hoc random generator.

languagepattern#:in-order:
In this case, redex-check uses an enumeration
of pattern, checking each t one at a time

languagepattern#:uniform-at-randomp-value:
that to index into an enumeration of pattern.
If the enumeration is finite, redex-check picks a natural number
uniformly at random; if it isn’t, redex-check uses a geometric
distribution with p-value as its probability of zero
to pick the number of bits in the index and then picks a
number uniformly at random with that number of bits.

languagepattern#:enumbound:
This is similar to #:uniform-at-random, except
that Redex always picks a random natural number less than bound
to index into the enumeration

language#:satisfying(metafunction-idpattern...)=pattern:
Generates terms matching the two patterns, such that
if the first is the argument to the metafunction, the
second will be the result.

redex-check generates at most attempts-expr
(default (default-check-attempts))
random terms in its search. The size and complexity of these terms tend to increase
with each failed attempt. The #:attempt-size keyword determines the rate at which
terms grow by supplying a function that bounds term size based on the number of failed
attempts (see generate-term’s size-expr argument). By default, the bound
grows according to the default-attempt-size function.

The optional #:prepare keyword supplies a function that transforms each
generated example before redex-check checks property-expr.
This keyword may be useful when property-expr takes the form
of a conditional, and a term chosen freely from the grammar is unlikely to
satisfy the conditional’s hypothesis. In some such cases, the prepare
keyword can be used to increase the probability that an example satisfies the
hypothesis.

The #:retries keyword behaves identically as in generate-term,
controlling the number of times the generation of any pattern will be
reattempted. It can’t be used together with #:satisfying.

If keep-going?-expr produces any non-#f value,
redex-check will stop only when it hits the limit on the number of attempts
showing all of the errors it finds. This argument is allowed only when
print?-expr is not #f.

When passed a metafunction or reduction relation via the optional #:source
argument, redex-check distributes its attempts across the left-hand sides
of that metafunction/relation by using those patterns, rather than pattern,
as the basis of its generation. It is an error if any left-hand side generates a
term that does not match pattern. #:source cannot be used
with #:satisfying.

Toggles whether or not redex will dynamically adjust the
chance that more recursive clauses of judgment forms or metafunctions
are chosen earlier when attempting to generate terms
with forms that use #:satisfying. It is #t by
default, which causes redex to favor more recursive clauses at
lower depths and less recursive clauses at depths closer to the
limit, in an attempt to generate larger terms. When it is
#f, all clause orderings have equal probability
above the bound.

WARNING: redex-generator is a new, experimental form,
and its API may change.

Returns a thunk that, each time it is called, either generates a random
s-expression based on satisfying or fails to (and returns #f).
The terms returned by a particular thunk are guaranteed to be distinct.

The default value of the #:attempt-size argument to
redex-check and the other randomized testing forms, this
procedure computes an upper bound on the size of the next
test case from the number of previously attempted tests n.
Currently, this procedure computes the base 5 logarithm, but
that behavior may change in future versions.

Recognizes the exceptions raised by generate-term,
redex-check, etc. when those forms are unable to produce
a term matching some pattern.

Debugging PLT Redex Programs

It is easy to write grammars and reduction rules that are
subtly wrong. Typically such mistakes result in examples
that get stuck when viewed in a traces window.

The best way to debug such programs is to find an expression
that looks like it should reduce, but doesn’t, then try to find
out which pattern is failing to match. To do so, use the
redex-match form.

In particular, first check if the term in question matches the
your system’s main non-terminal (typically the expression
or program non-terminal). If it does not match, simplify the term
piece by piece to determine whether the problem is in the
term or the grammar.

If the term does match your system’s main
non-terminal, determine by inspection which reduction rules
should apply. For each such rule, repeat the above term-pattern
debugging procedure, this time using the rule’s left-hand side
pattern instead of the system’s main non-terminal. In addition
to simplifying the term, also consider simplifying the pattern.

If the term matches the left-hand side, but the rule does not
apply, then one of the rule’s side-condition or
where clauses is not satisfied. Using the bindings
reported by redex-match, check each side-condition
expression and each where pattern-match to discover which
clause is preventing the rule’s application.

This function opens a new window and inserts each expression
in expr (if multiple? is #t – if
multiple? is #f, then expr is treated as a single
expression). Then, it reduces the terms until at least
reduction-steps-cutoff (see below) different terms are
found, or no more reductions can occur. It inserts each new
term into the gui. Clicking the reduce button reduces
until reduction-steps-cutoff more terms are found.

The pred function indicates if a term has a particular
property. If it returns #f, the term is displayed with a
pink background. If it returns a string or a color% object,
the term is displayed with a background of that color (using
the-color-database to map the string to a color). If it
returns any other value, the term is displayed normally. If
the pred function accepts two arguments, a term-node
corresponding to the term is passed to the predicate. This
lets the predicate function explore the (names of the)
reductions that led to this term, using term-node-children,
term-node-parents, and term-node-labels.

The pred function may be called more than once per node. In
particular, it is called each time an edge is added to a
node. The latest value returned determines the color.

The pp function is used to specially print expressions. It
must either accept one or four arguments. If it accepts one
argument, it will be passed each term and is expected to
return a string to display the term.

If the pp function takes four arguments, it should render
its first argument into the port (its second argument) with
width at most given by the number (its third argument). The
final argument is the text where the port is connected –
characters written to the port go to the end of the editor.
Use write-special to send snip% objects or
2htdp/image images
(or other things that subscribe to file/convertible
or pict/convert)
directly to the editor.

The colors argument, if provided, specifies a list of
reduction-name/color-list pairs. The traces gui will color arrows
drawn because of the given reduction name with the given color instead
of using the default color.

The cdr of each of the elements of colors is a list
of colors, organized in pairs. The first two colors cover the colors
of the line and the border around the arrow head, the first when the
mouse is over a graph node that is connected to that arrow, and the
second for when the mouse is not over that arrow. Similarly, the next
colors are for the text drawn on the arrow and the last two are for
the color that fills the arrow head. If fewer than six colors are
specified, the specified colors are used and then defaults are
filled in for the remaining colors.

The racket-colors? argument (along with scheme-colors?,
retained for backward compatibility), controls the coloring of
each window. When racket-colors? is #t (and
scheme-colors? is #t too), traces colors the
contents according to DrRacket’s Racket-mode color scheme; otherwise,
traces uses a black color scheme.

The term-filter function is called each time a new node is
about to be inserted into the graph. If the filter returns false, the
node is not inserted into the graph.

The x-spacing and y-spacing arguments control the amount of
space put between the snips in the default layout.

The layout argument is called (with all of the terms) when
new terms are inserted into the window. In general, it is called
after new terms are inserted in response to the user clicking on the
reduce button, and after the initial set of terms is inserted.
See also term-node-set-position!.

If edge-labels? is #t (the default), then edge labels
are drawn; otherwise not.

The edge-label-font argument is used as the font on the edge
labels. If #f is supplied, the dc<%> object’s default
font is used.

The traces library uses an instance of the mrlib/graph
library’s graph-pasteboard<%> interface to layout
the graphs. Sometimes, overriding one of its methods can
help give finer-grained control over the layout, so the
graph-pasteboard-mixin is applied to the class
before it is instantiated. Also note that all of the snips
inserted into the editor by this library have a
get-term-node method which returns the snip’s
term-node.

For a more serious example of traces, please see Amb: A Redex Tutorial,
but for a silly one that demonstrates how the pp argument
lets us use images, we can take the pairing functions discussed in
Matthew Szudzik’s An Elegant Pairing Function presentation:

Returns a list of the names of the reductions that led to
the given node, in the same order as the result of
term-node-parents. If the list contains #f, that means that
the corresponding step does not have a label.

Changes the highlighting of the node; if its second argument
is #f, the coloring is removed, otherwise the color is set
to the specified color% object or the color named by the
string. The color-database<%> is used to convert the string
to a color% object.

2.8Typesetting

The redex/pict library provides functions
designed to typeset grammars, reduction relations, and
metafunctions.

Each grammar, reduction relation, and metafunction can be
saved in a ".ps" file (as encapsulated PostScript),
or can be turned into a pict for viewing in the REPL or
using with Slideshow (see the pict
library).

For producing papers with Scribble, just include the
picts inline in the paper and pass the the --dvipdf
flag generate the ".pdf" file. For producing
papers with LaTeX, create ".ps" files from Redex and use
latex and dvipdf to create ".pdf" files
(using pdflatex with ".pdf" files will
work but the results will not look as good onscreen).

Renders the term term. If file is #f or not present,
render-term produces a pict; if file is a path, it saves
Encapsulated PostScript in the provided filename, unless the filename
ends with ".pdf", in which case it saves PDF.

The term argument must be a literal; it is not an
evaluated position. For example, this:

The first argument is expected to be a compiled-language? and
the second argument is expected to be a term (without the
term wrapper). The formatting in the term argument
is used to determine how the resulting pict will look.

This function is primarily designed to be used with
Slideshow or with other tools that combine picts
together.

Like render-term, except that the term argument is evaluated,
and expected to return a term. Then, pretty-write is used
to determine where the line breaks go, using the width argument
as a maximum width (via pretty-print-columns).

Renders a language. If file is #f,
it produces a pict; if file is a path, it saves
Encapsulated PostScript in the provided filename, unless the filename
ends with ".pdf", in which case it saves PDF.
See
render-language-nts for information on the
nts argument.

Renders a reduction relation. If file is #f,
it produces a pict; if file is a path, it saves
Encapsulated PostScript in the provided filename, unless the filename
ends with ".pdf", in which case it saves PDF.
See rule-pict-style for information on the
style argument.