From: Mark H Weaver <mhw@netris.org>
To: Andy Wingo <wingo@pobox.com>
Cc: guile-devel <guile-devel@gnu.org>
Subject: Re: summary: lilypond, lambda, and local-eval
Date: Sun, 18 Dec 2011 02:11:41 -0500 [thread overview]
Message-ID: <878vmaicb6.fsf@netris.org> (raw)
In-Reply-To: <87aa6skika.fsf@netris.org> (Mark H. Weaver's message of "Fri, 16 Dec 2011 03:49:09 -0500")
I wrote:
>> Most passes of the compiler will pretend that (the-environment) is
>> replaced by tree-il code corresponding to the following standard scheme
>> code:
>
> I should also mention that perhaps, instead of simply "pretending", it
> might make sense to actually replace (the-environment) with the standard
> scheme code I gave as early as possible, so that later passes will never
> even see `the-environment' tree-il nodes. It need only be late enough
> so that the list of visible lexical variable names is known at that
> point.
So, it turns out that the best place to transform (the-environment) into
standard scheme code is in the macro expander itself. Indeed, only the
macro expander has enough information to generate an optimal list of
"reachable lexicals", i.e. lexical variables that are accessible using
normal symbols (as opposed to syntax objects) [more on this below].
This is great news, because it means that `the-environment' will no
longer require its own tree-il type, and the compiler will only see the
standard scheme code that it expands into.
However, we will need a robust way to either (A) specify, (B) discover,
or (C) predict the order of the captured lexicals in a closure.
Option A would be ideal, because it would allow `local-eval' to easily
and robustly create a new closure that is "compatible" with the
general-dispatcher closure created by (the-environment), using only
standard compiler interfaces. By "compatible", I mean that their
captured lexicals have the same names and are stored in the same order
in the closure, so that code from the new closure can be spliced into
the existing general-dispatcher closure.
Option B would require `local-eval' to use a special interface to the
compiler to compile new code that is compatible with the existing
general-dispatcher closure.
Option C is similar to option B but probably more fragile, because
future changes to the compiler might invalidate the predictions and thus
break `local-eval'. However, this fragility could perhaps be mitigated
by prominent warnings in the comments of the code that determines
closure slot order.
I have yet to decide which option to take. Suggestions welcome.
* * * * *
There's also another issue that has come to my attention. If we must
support arbitrary syntax-objects to be passed to `local-eval', in many
(most?) cases this will greatly increase the number of lexicals that
must be captured, and thus boxed, by (the-environment).
Consider the following example:
(let* ((t 42)
(t (1+ t))
(t (1+ t))
(t (1+ t)))
(or #f (the-environment))))
If syntax-objects are never passed to `local-eval', then only one
lexical variable is reachable from (the-environment), namely the last
`t' in the `let*', and therefore that's the only variable that must be
boxed.
However, if we must support arbitrary syntax-objects, then not only are
all four of the above `t's reachable, but the hidden `t' from the
expansion of the `or' is reachable as well! (or at least I see no way
for the implementation of `the-environment' to prove that the user does
not possess such syntax-objects, given the way psyntax is implemented).
It would be a shame to force all of these shadowed and hidden variables
to be boxed. If we can minimize the number of captured variables, we
can reduce the performance impact of `the-environment'.
So, I'm thinking that (the-environment) should only capture lexical
variables that are reachable using normal symbols. I've already written
code for psyntax that generates this list of reachable lexicals. This
should suffice in the overwhelming majority of cases.
If needed, we could easily support a variant: (the-full-environment) or
(the-environment #:full), that captures _all_ lexicals reachable using
arbitrary syntax-objects.
What do you think?
Mark
next prev parent reply other threads:[~2011-12-18 7:11 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-15 10:21 summary: lilypond, lambda, and local-eval Andy Wingo
2011-12-15 14:46 ` David Kastrup
2011-12-15 16:52 ` Hans Aberg
2011-12-15 17:24 ` David Kastrup
2011-12-15 17:52 ` Hans Aberg
2011-12-16 7:35 ` Mark H Weaver
2011-12-16 8:08 ` Mark H Weaver
2011-12-16 8:49 ` Mark H Weaver
2011-12-16 9:16 ` David Kastrup
2011-12-18 7:11 ` Mark H Weaver [this message]
2011-12-18 11:27 ` Andy Wingo
2011-12-18 15:32 ` Noah Lavine
2011-12-18 16:19 ` David Kastrup
2011-12-18 21:24 ` Noah Lavine
2011-12-19 9:13 ` Mark H Weaver
2012-01-09 14:44 ` David Kastrup
2011-12-16 9:28 ` Andy Wingo
2011-12-16 9:59 ` David Kastrup
2011-12-16 10:33 ` Mark H Weaver
2011-12-16 12:13 ` Hans Aberg
2011-12-16 12:43 ` David Kastrup
2011-12-16 14:57 ` Hans Aberg
2011-12-21 10:32 ` Ian Hulin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=878vmaicb6.fsf@netris.org \
--to=mhw@netris.org \
--cc=guile-devel@gnu.org \
--cc=wingo@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).