[racket] top-level-rename

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Aug 11 01:44:16 EDT 2014

At Sun, 10 Aug 2014 17:01:01 +0200, Jens Axel Søgaard wrote:
> 2014-08-08 7:07 GMT+02:00 Matthew Flatt <mflatt at cs.utah.edu>:
> > At Wed, 6 Aug 2014 22:03:17 +0200, Jens Axel Søgaard wrote:
> >> The program below produce bytecodes for the program that returns a
> >> syntax-object representing 42.
> >>
> >> The syntax-object looks like this:
> >>
> >>     (#s((stx zo 0)
> >>            #s((wrapped zo 0)
> >>               42
> >>               (#s((top-level-rename wrap 0 zo 0) #f)
> >>                #s((top-level-rename wrap 0 zo 0) #f)
> >>                #s((top-level-rename wrap 0 zo 0) #t)
> >>                #s((phase-shift wrap 0 zo 0) 0 #f #f #f))
> >>               clean))))
> >>
> >> Two questions:
> >>    1) Why three top-level-renames and not just one?
> >>
> >>    2) What is the meaning of the boolean flag?
> >
> > The boolean apparently indicates whether the rename is for phase 0. It
> > should instead be the phase of the rename, where using a boolean for
> > the phase is probably a leftover from an original implementation where
> > imports were either phase 0 or phase 1.
> >
> > The three renames are from phases 0, 1, and #f.
> 
> Got it.
> 
> The next part of the syntax object is:

Answers below, but first a big caution: While these details have been
the same for a while, I hope and expect the representation of syntax
objects to change in the coming months. I have been threatening to
rewrite the macro expander (yes, in Racket) for a while, but things are
lining up so that I can actually start trying soon.


>      #s((phase-shift wrap 0 zo 0) 0 #f #f #f))
> 
> The form of a phase-shift is
>     (phase-shift amt src dest cancel-id)
> where
>   amt is #f or an integer,
>   src and dest are module-path-index?
>   cancel-id is #f or an integer
> 
> The documentation on phase-shift is rather brief.
> 
> 1) Is it correct that a shift of #f means that only bindings at phase level 0
>     are shifted to the label phase level?

I'm afraid I could only look for the answer in the same place in the
implementation where you must have found the "phase shift to #f shifts
only phase-0 bindings" comment. So, yes.


> 2) Even though src and dest are documented to be module-path-indices
>     the example show that #f is a valid value too.
>     Is it safe to assume that the combination #f #f means toplevel and
> "self-module" ?
>     Or do #f  mean "use the same value as before" ?

I believe it means "use the same value as before".


> 3) The example shows a phase-shift of 0. At first I didn't get what
> the purpose of this.
>     Then I found a comment in add_renames_unless_module :
> 
>     /* this "phase shift" just attaches the namespace's module registry: */
>     form = scheme_stx_phase_shift(form, NULL, NULL, NULL,
> 
> genv->module_registry->exports, NULL, NULL);
> 
>     and this comment in scheme_stx_phase_shift :
> 
>     /* Shifts the phase on a syntax object in a module. A 0 shift might be
>     used just to re-direct relative module paths. new_midx might be
>     NULL to shift without redirection. And so on. */
> 
>     Is this is the explanation behind the zero phase shift?

Yes, that sounds right.


> 4) What is the cancel-id? used for ?

It's for yet another job of "phase shift" entries: to indicate the
boundaries between information for a submodule context and information
for the enclosing module's context.

Roughly, a cancel ID causes a later module context to be ignored for
the purposes of determining an identifier's context. The value of the
cancel-ID field is matched against an identity field of each
module-rename record.

You could see get_old_module_env() for more, but I have trouble
understanding and trusting this piece myself. I think it's a hack that
has worked just well enough... except for Typed Racket, where submodule
expansion doesn't work right, probably due to this part.



Posted on the users mailing list.