racket/collects/stepper/internal-docs.txt
Eli Barzilay daa18fcba0 typos
svn: r66
2005-06-08 00:28:39 +00:00

243 lines
9.8 KiB
Plaintext

This file summarizes certain aspects of the operation of the stepper.
The Stepper's use of syntax-property:
In order to make macro-unwinding possible, the stepper adds
syntax-properties to elaborated code which then informs the
reconstruction process about how certain macros were originally
formed.
In fact, the truth is slightly more complicated, because there are
two rounds of macro-expansion for a program written in a teaching
language. First, the program is expanded according to the
macro definitions contained in the "lang" collection. Then, the
code is expanded according to the macro definitions built into
mzscheme. So, for instance, a beginner 'cond' expands into a
mzscheme 'cond' which expands into a nested series of 'if's.
Correspondingly, the stepper's addition of syntax properties is broken
into two parts; those added for the beginner macros, and those added
for the mzscheme macros. However, since it is harder to alter the
macro expansion which occurs in mzscheme, the latter set are added not
during the actual macro expansion in mzscheme but as part of a pass
over the code that occurs in the annotator between expansion and the
main annotation. This procedure is called 'top-level-rewrite'.
Therefore, the stepper's syntax-property additions occur in two
textual locations: collects/lang/private/teach.ss, and
collects/stepper/private/annotate.ss (with a few stray ones
in collects/lang/private/teachhelp.ss).
Also, in order to be visible to the reconstructor, these properties
must be explicitly transferred from the annotated source code syntax
to the reconstructed syntax. This is accomplished by the 'attach-info'
procedure in reconstruct.ss. Note that in the process, these properties
are given names that have "user-" prepended to them. This now seems
like a strange decision.
Finally, the astute reader may wonder why I need to add things like
'comes-from-or, since the expression that results from the expansion
of 'or' has a corresponding 'or' element in its 'origin field. The
reason is that this element appears only on the outermost expression
in the expansion, and during runtime reconstruction, this outermost
expression may be gone.
Here are the syntax properties added, the values they may be
associated with, their meanings, whether they're transferred
by attach-info, and where they're used:
stepper-skip-completely :
[ #t ] : this code should not be annotated at all. In general, this
means it therefore be invisible to the reconstructor. (Not
transferred.) Actually, the code is wrapped with a dummy mark,
just to make sure that other marks get properly obliterated.
Note that skipping an expression can turn a sensible expression into
a nonsensical one. This is where the 'expressions are lists of
subexpressions' abstraction and the 'expressions are one of A...Z'
abstraction part ways.
Uses:
- applied to the check of the test-variable in the expansion of the
'or' macro.
- applied to the expansion of the primitives defined with
'define-primitive'.
- applied to the 'make-generative-lambda' inserted by teach.ss
stepper-hint :
this is the most generally applied syntax property. In general, it
informs the reconstructor what macro this source expression came
from.
See notes below about 'being careful with stepper-hint'.
(Transferred.)
[ 'comes-from-cond ] : similarly, this expression came from a use
of 'cond'. This tag is applied to all the if's, but not to the else
clause.
[ 'comes-from-let* ] : expression was expanded from let*
[ 'comes-from-local ] : expression was expanded from local
[ 'from-xml-box ] : expression was expanded from an xml box
[ 'from-scheme-box ] : expression was expanded from a scheme box
(inside an xml box)
[ 'from-splice-box ] : expression was expanded from a scheme splice
box (inside an xml box)
[ 'comes-from-recur ] : expression was expanded from a 'recur'
stepper-define-type:
this is attached to the right-hand sides of defines to indicate what
kind of define they came from.
[ 'shortened-proc-define ] : this lambda arose from the expansion
of (define (id arg ...) body). N.B.: anything tagged with this
property must also have a 'stepper-proc-define-name
property.
[ 'lambda-define ] : this lambda arose from the expansion of
(define id (lambda (
(Transferred.)
Question 1: why the right-hand side? Why not on the define itself?
A: because for certain kinds of define (namely those in a local),
the define itself evaporates into an internal define which is then
expanded in a mzscheme-native expansion into a letrec.
Question 2: won't the right-hand side change, losing the mark?
A: yes it will, but not for definitions of lambdas. Since there
are three cases we need to distinguish, and two of them are
definitions of lambdas, we can distinguish the third case
by its lack of a stepper-define-type mark.
Question 3: what if, through reduction, a different expression
than the original one shows up ... which _does_ have one of the
two stepper-define-type marks?
A: to prevent this, there's another syntax-property,
'stepper-proc-define-name, which indicates the identifier to which
this procedure was originally bound. In the absence of set!,
this solves the problem.
stepper-xml-hint : indicates whether this expression came from an
xml-box. The protocol is as follows:
[ 'from-xml-box ] : attached to the outer application that wraps
the result of expanding an xml-box
[ 'from-scheme-box ] : attached to the (begin ...) that wraps
the result of expanding a scheme-box
[ 'from-splice-box ] : attached to the (qq-append ...) that wraps
the result of expanding a splice-box
(Transferred.)
stepper-xml-value-hint : like the stepper-xml-hint, used to indicate
values that are the result of evaluating xml boxes. The reason
this cannot be the same as the stepper-xml-hint property is that
the stepper-xml-hint property is one of the "attached" ones which
follows the source syntax around. This means that instances of this
property used to signal values that are the result of xml-box
evaluation get stomped by the stepper-xml-hint values attached to the
source.
[ 'from-xml-box ] : this value is the result of evaluating an xml
box.
stepper-proc-define-name : stores the name to which a procedure
defined with the (define (fn arg ...) body) was bound.
(Transferred.)
stepper-orig-name: attached to an uninterned symbol used by
the expansion of define so that the stepper can compare the
name attached to a lambda to the name of a definition.
(Not transferred.)
stepper-prim-name:
this is attached to the expansion of primitives introduced with the
'define-primitive' form. Its value indicates what name to give to
the source term at reconstruction time.
stepper-binding-type :
this is actually unrelated to macro expansion. It differentiates
between the various kinds of lexical bindings. (Not transferred.)
[ 'macro-bound ] : this variable's binding was inserted by a macro
[ 'let-bound ] : this variable's binding was in a let/*/rec
[ 'lambda-bound ] : this variable's binding was in a lambda
stepper-and/or-clauses-consumed :
indicates the number of clauses to the left of the one associated
with a given 'if' in the expansion of an 'and' or 'or'.
This allows the stepper to reconstruct a partially evaluated
'and' or 'or' with the right number of 'true's or 'false's
in front.
(Transferred.)
stepper-skipto :
this instructs the annotator to look inside the current expression
along a given path for the expression to be annotated. In
particular, the value bound to stepper-skipto must be a list whose
elements are car, cdr, or syntax-e. (Not transferred)
Some uses:
- applied to the 'check-undefined' check added on local-bound variables.
- applied to the spurious 'let' that's wrapped around a local.
Where it's used: the stepper-skipto label is used by the 2nd-pass
macro-labeler and the annotator. Both are in annotate.ss. In addition
to skipping inward, a stepper hint
stepper-else :
[ #t ] : Initially applied to the 'true' that the cond macro
replaces a beginner's 'else' with, it is later transferred
to the 'if' wrapping that 'true'. This is because there is no
place to annotated the cond that is passed to mzscheme's
expander which will result in an annotation on the 'if.'
Note that it cannot be applied simply to the 'true' itself,
because then, when you reduce to the then, the mark on the
test (that is, the (#%datum . true)) is gone.
(Transferred.)
stepper-define-struct-hint :
this expression came from a define-struct. The value associated with
this label is the syntax-object representing the define-struct itself.
stepper-test-suite-hint :
this expression was the expression being tested in a test-suite-tool
test. this hint indicates to the annotator that the expression should
be annotated, even though it's not in one of the expected top-level
shapes.
STEPPER-HINT COLLISIONS
The major concern with the stepper-hint is that two of them may
collide. My claim that this never happens is founded on the following
reasoning, KNOWN NOT TO BE RIGOROUS.
0) Tags are attached only to expressions that are produced fresh as
the result of a macro expansion. (For instance, the 'if' that is
the result of the expansion of 'and'.)
1) except in the circumstances listed below, the expressions with tags
attached to them are not themselves macro invocations.
Q.E.D.
exceptions:
1) the beginner cond expands into the mzscheme cond, which is
then annotated by the top-level-rewrite. In this case, the expansion
of the beginner cond does not add any stepper-hint properties, so no
collision can occur.
2) the intermediate let* expands into the beginner let; both add a
stepper-hint. To resolve this, the expansion of let allows an existing
stepper-hint to stand.