a little more progress on the documentation port

svn: r11077
This commit is contained in:
Robby Findler 2008-08-05 03:57:51 +00:00
parent b9fb8b5155
commit f6037ca1c6

View File

@ -4,6 +4,8 @@
scribble/eval scribble/eval
(for-syntax scheme/base) (for-syntax scheme/base)
(for-label scheme/base (for-label scheme/base
scheme/gui
scheme/pretty
scheme/contract scheme/contract
redex)) redex))
@ -20,6 +22,12 @@
(identifier? #'arg) (identifier? #'arg)
#`(tech #,(symbol->string (syntax-e #'arg)))])) #`(tech #,(symbol->string (syntax-e #'arg)))]))
@(define-syntax (ttpattern stx)
(syntax-case stx ()
[(_ args ...)
#'((tech (tt "pattern")) args ...)]
[x (identifier? #'x) #'(tech (tt "pattern"))]))
@(define-syntax (pattern stx) @(define-syntax (pattern stx)
(syntax-case stx () (syntax-case stx ()
[(_ args ...) [(_ args ...)
@ -138,6 +146,7 @@ This section describes the all of the exports of
@schememodname[redex/reduction-semantics], each of which is @schememodname[redex/reduction-semantics], each of which is
also exported by @schememodname[redex]. also exported by @schememodname[redex].
@subsection{Patterns}
The @tt{reduction-semantics.ss} library defines a @deftech{pattern} The @tt{reduction-semantics.ss} library defines a @deftech{pattern}
language, used in various ways: language, used in various ways:
@ -211,7 +220,7 @@ the language.
} }
@item{The @defpattech[hole] @pattern matches anything when inside a matching @item{The @defpattech[hole] @pattern matches anything when inside a matching
the first argument to an @pattech[in-hole] pattern. Otherwise, the first argument to an @pattech[in-hole] @|pattern|. Otherwise,
it matches only the hole. it matches only the hole.
} }
@ -229,16 +238,16 @@ example. Accordingly, repeated uses of the same name are
constrainted to match the same expression. constrainted to match the same expression.
If the symbol is a non-terminal followed by @tt{_!_}, for example If the symbol is a non-terminal followed by @tt{_!_}, for example
@tt{e_!_1}, it is also treated as a pattern, but repeated uses of @tt{e_!_1}, it is also treated as a @|pattern|, but repeated uses of
the same @pattern are constrained to be different. For the same @pattern are constrained to be different. For
example, this pattern: example, this @|pattern|:
@schemeblock[(e_!_1 e_!_1 e_!_1)] @schemeblock[(e_!_1 e_!_1 e_!_1)]
matches lists of three @tt{e}s, but where all three of them are matches lists of three @tt{e}s, but where all three of them are
distinct. distinct.
Unlike a @tt{_} pattern, the @tt{_!_} patterns do not bind names. Unlike a @tt{_} @|pattern|, the @tt{_!_} @|pattern|s do not bind names.
If @tt{_} names and @tt{_!_} are mixed, they are treated as If @tt{_} names and @tt{_!_} are mixed, they are treated as
separate. That is, this @pattern @tt{(e_1 e_!_1)} matches just the separate. That is, this @pattern @tt{(e_1 e_!_1)} matches just the
@ -248,27 +257,27 @@ variables.
If the symbol otherwise has an underscore, it is an error. If the symbol otherwise has an underscore, it is an error.
} }
@item{The @pattern @tt{(@defpattech[name] symbol @pattern)} @item{The @pattern @tt{(@defpattech[name] symbol @ttpattern)}
matches @tt{@pattern} and binds using it to the name @tt{symbol}. matches @tt{@pattern} and binds using it to the name @tt{symbol}.
} }
@item{The @tt{(@defpattech[in-hole] @pattern @pattern)} @pattern @item{The @tt{(@defpattech[in-hole] @ttpattern @ttpattern)} @pattern
matches the first pattern. This match must include exactly one match matches the first @|pattern|. This match must include exactly one match
against the second pattern. If there are zero matches or more against the second @|pattern|. If there are zero matches or more
than one match, an exception is raised. than one match, an exception is raised.
When matching the first argument of in-hole, the `hole' @pattern When matching the first argument of in-hole, the `hole' @pattern
matches any sexpression. Then, the sexpression that matched the hole matches any sexpression. Then, the sexpression that matched the hole
@pattern is used to match against the second pattern. @pattern is used to match against the second @|pattern|.
} }
@item{The @tt{(@defpattech[hide-hole] @pattern)} @pattern matches what @item{The @tt{(@defpattech[hide-hole] @ttpattern)} @pattern matches what
the embedded @pattern matches but if the @pattern matcher is the embedded @pattern matches but if the @pattern matcher is
looking for a decomposition, it ignores any holes found in looking for a decomposition, it ignores any holes found in
that pattern. that @|pattern|.
} }
@item{The @tt{(@defpattech[side-condition] @pattern guard)} @pattern matches @item{The @tt{(@defpattech[side-condition] @ttpattern guard)} @pattern matches
what the embedded @pattern matches, and then the guard expression is what the embedded @pattern matches, and then the guard expression is
evaluated. If it returns @scheme[#f], the @pattern fails to match, and if it evaluated. If it returns @scheme[#f], the @pattern fails to match, and if it
returns anything else, the @pattern matches. In addition, any returns anything else, the @pattern matches. In addition, any
@ -290,14 +299,14 @@ of the list. In addition, if a list @pattern contains an
ellipsis, the ellipsis is not treated as a literal, instead ellipsis, the ellipsis is not treated as a literal, instead
it matches any number of duplications of the @pattern that it matches any number of duplications of the @pattern that
came before the ellipses (including 0). Furthermore, each came before the ellipses (including 0). Furthermore, each
@tt{(@pattech[name] symbol @pattern)} in the duplicated @pattern binds a @tt{(@pattech[name] symbol @ttpattern)} in the duplicated @pattern binds a
list of matches to @tt{symbol}, instead of a single match. (A list of matches to @tt{symbol}, instead of a single match. (A
nested duplicated @pattern creates a list of list matches, nested duplicated @pattern creates a list of list matches,
etc.) Ellipses may be placed anywhere inside the row of etc.) Ellipses may be placed anywhere inside the row of
patterns, except in the first position or immediately after @|pattern|s, except in the first position or immediately after
another ellipses. another ellipses.
Multiple ellipses are allowed. For example, this pattern: Multiple ellipses are allowed. For example, this @|pattern|:
@schemeblock[((name x a) ... (name y a) ...)] @schemeblock[((name x a) ... (name y a) ...)]
@ -317,7 +326,7 @@ records the length of the list and ensures that any other
occurrences of the same named ellipses must have the same occurrences of the same named ellipses must have the same
length. length.
As an example, this pattern: As an example, this @|pattern|:
@schemeblock[((name x a) ..._1 (name y a) ..._1)] @schemeblock[((name x a) ..._1 (name y a) ..._1)]
@ -326,14 +335,14 @@ only matches this sexpression:
@schemeblock[(term (a a))] @schemeblock[(term (a a))]
one way, with each named @pattern matching a single a. Unlike one way, with each named @pattern matching a single a. Unlike
the above, the two patterns with mismatched lengths is ruled the above, the two @|pattern|s with mismatched lengths is ruled
out, due to the underscores following the ellipses. out, due to the underscores following the ellipses.
Also, like underscore patterns above, if an underscore Also, like underscore @|pattern|s above, if an underscore
@pattern begins with @tt{..._!_}, then the lengths must be @pattern begins with @tt{..._!_}, then the lengths must be
different. different.
Thus, with the pattern: Thus, with the @|pattern|:
@schemeblock[((name x a) ..._!_1 (name y a) ..._!_1)] @schemeblock[((name x a) ..._!_1 (name y a) ..._!_1)]
@ -349,15 +358,190 @@ bound to @scheme['()].
} }
} }
@defform*[[(redex-match lang pattern any)
(redex-match lang pattern)]]{
If @scheme[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. If it fails, it returns
@scheme[#f].
If @scheme[redex-match] receives only two arguments, it
builds a procedure for efficiently testing if expressions
match the pattern, using the language @scheme[lang]. The
procedures accepts a single expression and if the expresion
matches, it returns a list of match structures describing the
matches. If the match fails, the procedure returns @scheme[#f].
}
@defproc[(match? [val any/c]) boolean?]{
Determines if a value is a @tt{match} structure.
}
@defproc[(match-bindings [m match?]) (listof bind?)]{
This returns a bindings structure (see below) that
binds the pattern variables in this match.
}
@defstruct[bind ([name symbol?] [exp any?])]{
Instances of this struct are returned by @scheme[redex-match].
Each @scheme[bind] associates a name with an s-expression from the
language, or a list of such s-expressions, if the @tt{(@pattech[name] ...)}
clause is followed by an ellipsis. Nested ellipses produce
nested lists.
}
@defform[(term s-expr)]{
This form is used for construction of new s-expressions in
the right-hand sides of reductions. 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).
For example,
@schemeblock[
(term-let ([body '(+ x 1)]
[(expr ...) '(+ - (values * /))]
[((id ...) ...) '((a) (b) (c d))])
(term (let-values ([(id ...) expr] ...) body)))
]
evaluates to
@schemeblock[
'(let-values ([(a) +]
[(b) -]
[(c d) (values * /)])
(+ x 1))
]
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.
The special forms recognized by term are:
@itemize{
@item{@scheme[(in-hole a b)]
This is the dual to the @pattern `in-hole' -- it accepts
a context and an expression and uses `plug' to combine
them.
}@item{@scheme[(in-named-hole name a b)]
Like in-hole, but substitutes into a hole with a particular name.
}@item{@scheme[hole]
This produces a hole.
}@item{@scheme[(hole name)]
This produces a hole with the name `name'. To produce an unnamed
hole, use #f as the name.
}}}
@defform/subs[(term-let ([tl-pat expr] ...) body)
([tl-pat identifier (tl-pat-ele ...)]
[tl-pat-ele tl-pat (code:line tl-pat ellipses)])]{
Matches each given id pattern to the value yielded by
evaluating the corresponding expr and binds each variable in
the id pattern to the appropriate value (described
below). These bindings are then accessible to the `term'
syntactic form.
Identifier-patterns are terms in the following grammar:
where ellipses is the literal symbol consisting of three
dots (and the ... 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).
}
@defform[(term-match language [#, @|ttpattern| expression] ...)]{
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.
}
@defform[(term-match/single language [#, @|ttpattern| expression] ...)]{
This produces a procedure that accepts term (or quoted)
expressions and checks them against each pattern. The
function returns the expression behind the first sucessful
match. If that pattern produces multiple matches, an error
is signaled. If no patterns match, an error is signaled.
}
@defproc[(plug [context any?] [expression any?]) any]{
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 @scheme[term] sub-expression contains @pattech[in-hole].
}
@defproc[(variable-not-in [t any?] [var symbol?]) symbol?]{
This helper function accepts an sexpression and a
variable. It returns a variable not in the sexpression with
a prefix the same as the second argument.
}
@defproc[(variables-not-in [t any?] [vars (listof symbol?)]) (listof symbol?)]{
This function, like variable-not-in, makes variables that do
no occur in its first argument, but it returns a list of
such variables, one for each variable in its second
argument.
Does not expect the input symbols to be distinct, but does
produce variables that are always distinct.
}
@defproc[(set-cache-size! [size (or/c false/c positive-integer?)]) void?]{
Changes the cache size; a #f disables the cache
entirely. The default size is 350.
The cache is per-pattern (ie, each pattern has a cache of
size at most 350 (by default)) and is a simple table that
maps expressions to how they matched the pattern. When the
cache gets full, it is thrown away and a new cache is
started.
}
@subsection{Languages}
@defform/subs[(define-language lang-name @defform/subs[(define-language lang-name
(non-terminal-spec #, @pattern ...) (non-terminal-spec #, @|ttpattern| ...)
...) ...)
([non-terminal-spec symbol (symbol ...)])]{ ([non-terminal-spec symbol (symbol ...)])]{
This form defines the grammar of a language. It allows the This form defines the grammar of a language. It allows the
definition of recursive patterns, much like a BNF, but for definition of recursive @|pattern|s, much like a BNF, but for
regular-tree grammars. It goes beyond their expressive regular-tree grammars. It goes beyond their expressive
power, however, because repeated `name' patterns and power, however, because repeated `name' @|pattern|s and
side-conditions can restrict matches in a context-sensitive side-conditions can restrict matches in a context-sensitive
way. way.
@ -385,7 +569,7 @@ variables, @scheme[c] for the evaluation contexts and @scheme[v] for values.
} }
@defform[(define-extended-language language language @defform[(define-extended-language language language
(non-terminal pattern ...) (non-terminal #, @|ttpattern| ...)
...)]{ ...)]{
This form extends a language with some new, replaced, or This form extends a language with some new, replaced, or
@ -434,107 +618,11 @@ Returns #t if its argument was produced by `language', #f
otherwise. otherwise.
} }
@defform/subs[(term-let ([tl-pat expr] ...) body) @subsection{Reduction Relations}
([tl-pat identifier (tl-pat-ele ...)]
[tl-pat-ele tl-pat (code:line tl-pat ellipses)])]{
Matches each given id pattern to the value yielded by
evaluating the corresponding expr and binds each variable in
the id pattern to the appropriate value (described
below). These bindings are then accessible to the `term'
syntactic form.
Identifier-patterns are terms in the following grammar:
where ellipses is the literal symbol consisting of three
dots (and the ... 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).
}
@defform[(term s-expr)]{
This form is used for construction of new s-expressions in
the right-hand sides of reductions. 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).
For example,
@schemeblock[
(term-let ([body '(+ x 1)]
[(expr ...) '(+ - (values * /))]
[((id ...) ...) '((a) (b) (c d))])
(term (let-values ([(id ...) expr] ...) body)))
]
evaluates to
@schemeblock[
'(let-values ([(a) +]
[(b) -]
[(c d) (values * /)])
(+ x 1))
]
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.
The special forms recognized by term are:
@itemize{
@item{@scheme[(in-hole a b)]
This is the dual to the pattern `in-hole' -- it accepts
a context and an expression and uses `plug' to combine
them.
}@item{@scheme[(in-named-hole name a b)]
Like in-hole, but substitutes into a hole with a particular name.
}@item{@scheme[hole]
This produces a hole.
}@item{@scheme[(hole name)]
This produces a hole with the name `name'. To produce an unnamed
hole, use #f as the name.
}}}
@defform[(term-match language [pattern expression] ...)]{
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.
}
@defform[(term-match/single language [pattern expression] ...)]{
This produces a procedure that accepts term (or quoted)
expressions and checks them against each pattern. The
function returns the expression behind the first sucessful
match. If that pattern produces multiple matches, an error
is signaled. If no patterns match, an error is signaled.
}
@defform/subs[#:literals (--> fresh side-condition where) @defform/subs[#:literals (--> fresh side-condition where)
(reduction-relation language reduction-case ...) (reduction-relation language reduction-case ...)
((reduction-case (--> pattern exp extras ...)) ((reduction-case (--> #, @|ttpattern| exp extras ...))
(extras name (extras name
(fresh <fresh-clause> ...) (fresh <fresh-clause> ...)
(side-condition <guard> ...) (side-condition <guard> ...)
@ -689,6 +777,47 @@ returns the closure of the reduction in that context.
@scheme[#f] otherwise. @scheme[#f] otherwise.
} }
@defproc[(apply-reduction-relation [r reduction-relation?] [t any?]) (listof any?)]{
This accepts reduction relation, a term, and returns a
list of terms that the term reduces to.
}
@defproc[(apply-reduction-relation/tag-with-names
[r reduction-relation?]
[t any/c])
(listof (list/c (union false/c string?) any/c))]{
Like @scheme[apply-reduction-relation], but the result indicates the
names of the reductions that were used.
}
@defproc[(apply-reduction-relation*
[r reduction-relation?]
[t any?])
(listof (listof any?))]{
apply-reduction-relation* accepts a list of reductions and a
term. It returns the results of following every reduction
path from the term. If there are infinite reduction
sequences starting at the term, this function will not
terminate.
}
@defidform[-->]{ Recognized specially within
@scheme[reduction-relation]. A @scheme[-->] form is an
error elsewhere. }
@defidform[fresh]{ Recognized specially within
@scheme[reduction-relation]. A @scheme[-->] form is an
error elsewhere. }
@defidform[with]{ Recognized specially within
@scheme[reduction-relation]. A @scheme[with] form is an
error elsewhere. }
@subsection{Metafunctions}
@defform/subs[#:literals (: ->) @defform/subs[#:literals (: ->)
(define-metafunction language-exp (define-metafunction language-exp
contract contract
@ -779,17 +908,7 @@ legtimate inputs according to @scheme[metafunction-name]'s contract,
and @scheme[#f] otherwise. and @scheme[#f] otherwise.
} }
@defidform[-->]{ Recognized specially within @subsection{Testing}
@scheme[reduction-relation]. A @scheme[-->] form is an
error elsewhere. }
@defidform[fresh]{ Recognized specially within
@scheme[reduction-relation]. A @scheme[-->] form is an
error elsewhere. }
@defidform[with]{ Recognized specially within
@scheme[reduction-relation]. A @scheme[with] form is an
error elsewhere. }
@defform[(test-equal e1 e2)]{ @defform[(test-equal e1 e2)]{
@ -812,109 +931,6 @@ counters so that next time this function is called, it
prints the test results for the next round of tests. prints the test results for the next round of tests.
} }
@defproc[(plug [context any?] [expression any?]) any]{
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 @scheme[term] sub-expression contains @pattech[in-hole].
}
@defproc[(apply-reduction-relation [r reduction-relation?] [t any?]) (listof any?)]{
This accepts reduction relation, a term, and returns a
list of terms that the term reduces to.
}
@defproc[(apply-reduction-relation/tag-with-names
[r reduction-relation?]
[t any/c])
(listof (list/c (union false/c string?) any/c))]{
Like @scheme[apply-reduction-relation], but the result indicates the
names of the reductions that were used.
}
@defproc[(apply-reduction-relation*
[r reduction-relation?]
[t any?])
(listof (listof any?))]{
apply-reduction-relation* accepts a list of reductions and a
term. It returns the results of following every reduction
path from the term. If there are infinite reduction
sequences starting at the term, this function will not
terminate.
}
@defform*[[(redex-match lang pattern any)
(redex-match lang pattern)]]{
If @scheme[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. If it fails, it returns
@scheme[#f].
If @scheme[redex-match] receives only two arguments, it
builds a procedure for efficiently testing if expressions
match the pattern, using the language @scheme[lang]. The
procedures accepts a single expression and if the expresion
matches, it returns a list of match structures describing the
matches. If the match fails, the procedure returns @scheme[#f].
}
@defproc[(match? [val any/c]) boolean?]{
Determines if a value is a @tt{match} structure.
}
@defproc[(match-bindings [m match?]) (listof bind?)]{
This returns a bindings structure (see below) that
binds the pattern variables in this match.
}
@defproc[(variable-not-in [t any?] [var symbol?]) symbol?]{
This helper function accepts an sexpression and a
variable. It returns a variable not in the sexpression with
a prefix the same as the second argument.
}
@defproc[(variables-not-in [t any?] [vars (listof symbol?)]) (listof symbol?)]{
This function, like variable-not-in, makes variables that do
no occur in its first argument, but it returns a list of
such variables, one for each variable in its second
argument.
Does not expect the input symbols to be distinct, but does
produce variables that are always distinct.
}
@defstruct[bind ([name symbol?] [exp any?])]{
Instances of this struct are returned by @scheme[redex-match].
Each @scheme[bind] associates a name with an s-expression from the
language, or a list of such s-expressions, if the @tt{(@pattech[name] ...)}
clause is followed by an ellipsis. Nested ellipses produce
nested lists.
}
@defproc[(set-cache-size! [size (or/c false/c positive-integer?)]) void?]{
Changes the cache size; a #f disables the cache
entirely. The default size is 350.
The cache is per-pattern (ie, each pattern has a cache of
size at most 350 (by default)) and is a simple table that
maps expressions to how they matched the pattern. When the
cache gets full, it is thrown away and a new cache is
started.
}
@deftech{Debugging PLT Redex Programs} @deftech{Debugging PLT Redex Programs}
It is easy to write grammars and reduction rules that are It is easy to write grammars and reduction rules that are
@ -941,78 +957,38 @@ simplifying the expression).
@section{GUI} @section{GUI}
@defmodule[redex/gui]
The _gui.ss_ library provides the following functions: This section describes the GUI tools that Redex provides for
exploring reduction sequences.
> (stepper reductions expr [pp]) :: @defproc[(traces [reductions reduction-relation?]
(opt-> (compiled-lang? [expr (or/c any/c (listof any/c))]
reduction-relation? [#:multiple? multiple? boolean? #f]
any/c) [#:pred pred
((or/c (any -> string) (or/c (sexp -> any) (sexp term-node? any))
(any output-port number (is-a?/c text%) -> void))) (lambda (x) #t)]
void?) [#:pp pp
(or/c (any -> string)
This function opens a stepper window for exploring the (any output-port number (is-a?/c text%) -> void))
behavior of its third argument in the reduction system default-pretty-printer]
described by its first two arguments. [#:colors colors (listof (list string string)) '()])
void?]{
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.
The default pp, provided as default-pretty-printer, uses
MzLib's pretty-print function. See threads.ss in the
examples directory for an example use of the one-argument
form of this argument and ho-contracts.ss in the examples
directory for an example use of its four-argument form.
> (stepper/seed reductions seed [pp]) ::
(opt-> (compiled-lang?
reduction-relation?
(cons/c any/c (listof any/c)))
((or/c (any -> string)
(any output-port number (is-a?/c text%) -> void)))
void?)
Like `stepper', this function opens a stepper window, but it
seeds it with the reduction-sequence supplied in `terms'.
> (traces reductions expr
#:pred [pred (lambda (x) #t)]
#:pp [pp default-pretty-printer]
#:colors [colors '()]
#:multiple? [multiple? #f])
lang : language
reductions : (listof reduction)
expr : (or/c (listof sexp) sexp)
multiple : boolean --- controls interpretation of expr
pred : (or/c (sexp -> any)
(sexp term-node? any))
pp : (or/c (any -> string)
(any output-port number (is-a?/c text%) -> void))
colors : (listof (list string string))
This function opens a new window and inserts each expression This function opens a new window and inserts each expression
in expr (if multiple is #t -- if multiple is #f, then expr in expr (if @scheme[multiple?] is #t -- if
is treated as a single expression). Then, it reduces the @scheme[multiple?] is #f, then expr is treated as a single
terms until either reduction-steps-cutoff (see below) expression). Then, it reduces the terms until at least
different terms are found, or no more reductions can @scheme[reduction-steps-cutoff] (see below) different terms are
occur. It inserts each new term into the gui. Clicking the found, or no more reductions can occur. It inserts each new
`reduce' button reduces until reduction-steps-cutoff more term into the gui. Clicking the @onscreen{reduce} button reduces
terms are found. until reduction-steps-cutoff more terms are found.
The pred function indicates if a term has a particular The pred function indicates if a term has a particular
property. If it returns #f, the term is displayed with a property. If it returns @scheme[#f], the term is displayed with a
pink background. If it returns a string or a color% object, pink background. If it returns a string or a @scheme[color%] object,
the term is displayed with a background of that color (using the term is displayed with a background of that color (using
the-color-database<%> to map the string to a color). If it @scheme[the-color-database] to map the string to a color). If it
returns any other value, the term is displayed normally. If returns any other value, the term is displayed normally. If
the pred function accepts two arguments, a term-node the pred function accepts two arguments, a term-node
corresponding to the term is passed to the predicate. This corresponding to the term is passed to the predicate. This
@ -1020,22 +996,61 @@ lets the predicate function explore the (names of the)
reductions that led to this term, using term-node-children, reductions that led to this term, using term-node-children,
term-node-parents, and term-node-labels. term-node-parents, and term-node-labels.
The pred function may be called more than once per node. In The @scheme[pred] function may be called more than once per node. In
particular, it is called each time an edge is added to a particular, it is called each time an edge is added to a
node. The latest value returned determines the color. node. The latest value returned determines the color.
The pp argument is the same as to the stepper functions The @scheme[pp] function is used to specially print expressions. It
(above). 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.
The colors argument, if provided, specifies a list of If the @scheme[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.
The default value of @scheme[pp], provided as
@scheme[default-pretty-printer], uses MzLib's
@scheme[pretty-print] function.
The @scheme[colors] argument, if provided, specifies a list of
reduction-name/color-string pairs. The traces gui will color reduction-name/color-string pairs. The traces gui will color
arrows drawn because of the given reduction name with the arrows drawn because of the given reduction name with the
given color instead of using the default color. given color instead of using the default color.
You can save the contents of the window as a postscript file You can save the contents of the window as a postscript file
from the menus. from the menus.
}
> term-node-children :: (-> term-node (listof term-node)) @defproc[(stepper [reductions reduction-relation?]
[t any/c]
[pp (or/c (any -> string)
(any output-port number (is-a?/c text%) -> void))
default-pretty-printer])
void?]{
This function opens a stepper window for exploring the
behavior of its third argument in the reduction system
described by its first two arguments.
The @scheme[pp] argument is the same as to the
@scheme[traces] functions (above).
}
@defproc[(stepper/seed [reductions reduction-relation?]
[seed (cons/c any/c (listof any/c))]
[pp (or/c (any -> string)
(any output-port number (is-a?/c text%) -> void))
default-pretty-printer])
void?]{
Like @scheme[stepper], this function opens a stepper window, but it
seeds it with the reduction-sequence supplied in @scheme[seed].
}
@defproc[(term-node-children [tn term-node?]) (listof term-node?)]{
Returns a list of the children (ie, terms that this term Returns a list of the children (ie, terms that this term
reduces to) of the given node. reduces to) of the given node.
@ -1043,8 +1058,9 @@ reduces to) of the given node.
Note that this function does not return all terms that this Note that this function does not return all terms that this
term reduces to -- only those that are currently in the term reduces to -- only those that are currently in the
graph. graph.
}
> term-node-parents :: (-> term-node (listof term-node)) @defproc[(term-node-parents [tn term-node?]) (listof term-node?)]{
Returns a list of the parents (ie, terms that reduced to the Returns a list of the parents (ie, terms that reduced to the
current term) of the given node. current term) of the given node.
@ -1052,77 +1068,77 @@ current term) of the given node.
Note that this function does not return all terms that Note that this function does not return all terms that
reduce to this one -- only those that are currently in the reduce to this one -- only those that are currently in the
graph. graph.
}
> term-node-labels :: (-> term-node (listof (union false/c string))) @defproc[(term-node-labels [tn term-node]) (listof (or/c false/c string?))]{
Returns a list of the names of the reductions that led to Returns a list of the names of the reductions that led to
the given node, in the same order as the result of the given node, in the same order as the result of
term-node-parents. If the list contains #f, that means that term-node-parents. If the list contains @scheme[#f], that means that
the corresponding step does not have a label. the corresponding step does not have a label.
}
> term-node-set-color! :: @defproc[(term-node-set-color! [tn term-node?] [color (or/c string? (is-a?/c color%) false/c)]) void?]{
(-> term-node?
(or/c string? (is-a?/c color%) false/c)
void?)
Changes the highlighting of the node; if its second argument Changes the highlighting of the node; if its second argument
is #f, the coloring is removed, otherwise the color is set is @scheme[#f], the coloring is removed, otherwise the color is set
to the specified color% object or the color named by the to the specified @scheme[color%] object or the color named by the
string. The color-database<%> is used to convert the string string. The @scheme[color-database<%>] is used to convert the string
to a color% object. to a @scheme[color%] object.
}
> term-node-set-red! :: (-> term-node boolean void?) @defproc[(term-node-set-red! [tn term-node?] [red? boolean?]) void?]{
Changes the highlighting of the node; if its second argument Changes the highlighting of the node; if its second argument
is #t, the term is colored pink, if it is #f, the term is is @scheme[#t], the term is colored pink, if it is @scheme[#f], the term is
not colored specially. not colored specially.
> term-node-expr :: (-> term-node any) }
@defproc[(term-node-expr [tn term-node?]) any]{
Returns the expression in this node. Returns the expression in this node.
}
> term-node? :: (-> any boolean) @defproc[(term-node? [v any/c]) boolean?]{
Recognizes term nodes. Recognizes term nodes.
}
> (reduction-steps-cutoff) @defparam[reduction-steps-cutoff cutoff number?]{
> (reduction-steps-cutoff number)
A parameter that controls how many steps the `traces' function A parameter that controls how many steps the @scheme[traces] function
takes before stopping. takes before stopping.
}
> (initial-font-size) @defparam[initial-font-size size number?]{
> (initial-font-size number)
A parameter that controls the initial font size for the terms shown A parameter that controls the initial font size for the terms shown
in the GUI window. in the GUI window.
}
> (initial-char-width) @defparam[initial-char-width width number?]{
> (initial-char-width number)
A parameter that determines the initial width of the boxes A parameter that determines the initial width of the boxes
where terms are displayed (measured in characters) for both where terms are displayed (measured in characters) for both
the stepper and traces. the stepper and traces.
}
> (dark-pen-color color-or-string) @deftogether[[
> (dark-pen-color) => color-or-string @defparam[dark-pen-color color (or/c string? (is-a?/c color<%>))]{}
@defparam[dark-brush-color color (or/c string? (is-a?/c color<%>))]{}
> (dark-brush-color color-or-string) @defparam[light-pen-color color (or/c string? (is-a?/c color<%>))]{}
> (dark-brush-color) => color-or-string @defparam[light-brush-color color (or/c string? (is-a?/c color<%>))]{}]]{
> (light-pen-color color-or-string)
> (light-pen-color) => color-or-string
> (light-brush-color color-or-string)
> (light-brush-color) => color-or-string
These four parameters control the color of the edges in the graph. These four parameters control the color of the edges in the graph.
}
@section{Typesetting} @section{Typesetting}
The @tt{pict.ss} library provides functions designed to @defmodule[redex/pict]
automatically typeset grammars, reduction relations, and
metafunction written with plt redex. The @schememodname[redex/pict] library provides functions
designed to automatically typeset grammars, reduction
relations, and metafunction written with plt redex.
Each grammar, reduction relation, and metafunction can be Each grammar, reduction relation, and metafunction can be
saved in a .ps file (as encapsulated postscript), or can be saved in a .ps file (as encapsulated postscript), or can be
@ -1139,9 +1155,11 @@ If you are only using the picts to experiment in DrScheme's
REPL, be sure your program is in the GUI library, and REPL, be sure your program is in the GUI library, and
contains this header: contains this header:
#lang scheme/gui @schememod[
(require texpict/mrpict) scheme/gui
(dc-for-text-size (make-object bitmap-dc% (make-object bitmap% 1 1))) (require texpict/mrpict)
(dc-for-text-size (make-object bitmap-dc% (make-object bitmap% 1 1)))
]
Be sure to remove the call to dc-for-text-size before you Be sure to remove the call to dc-for-text-size before you
generate .ps files, otherwise the font spacing will be wrong generate .ps files, otherwise the font spacing will be wrong