[racket] top-level-rename
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.