[R6RS] modules

R. Kent Dybvig dyb
Thu Aug 26 20:33:07 EDT 2004


> Is it overly conservative to use the set of names that appear
> on the right hand side of a rule but do not appear on the left
> hand side? 

I don't know how to define "overly conservative".  A conservative analysis
isn't harmful until one gets burned by it.  There's no way to know how
bad it will be, and the programmer may not even know when it happens.

> It certainly is neither complex nor expensive.

Typically, the rhs is pretty simple and finding potential implicit
exports is neither complex nor expensive.  The problem is when the
rhs includes data, which, by virtue of graph syntax or constructed
code passed to eval, may be arbitrarily large and/or contain cycles.
Even with syntax rules, it is not generally possible to determine what is
going to be quoted without fully expanding the code against its inputs.
Take the following example:

  (syntax-rules ()
    [(_ x) (foo (quote <arbitrary and possibly cyclic data>) x)])

<arbitrary and possibly cyclic data> appears to be quoted, but if foo is a
keyword, we can't be sure without expanding foo, an expansion complicated,
perhaps impossibly so, by the fact that we don't know the actual text of
its first subform---even if foo is also defined via syntax-rules.  So,
in general, we have to assume that <arbitrary and possibly cyclic data>
is not quoted and scan it for potential implicit exports.

So scanning for implicit exports is indeed complex and potentially
expensive, even for syntax-rules.

Maybe we could ignore the potential expense, since the vast majority of
cases will likely be inexpensive, but I don't look forward to hearing
from the irate programmer who sticks a quoted pointer to a 6GB database
in a piece of code passed to eval, discovers that the compiler doesn't
terminate in a reasonable amount of time, and has no clue why.  In fact,
I'd be pretty upset if r6rs forced my compiler into this circumstance.

> ... As
> a programmer I would definitely prefer that to having to list
> the implicit exports by hand.

I have not found listing implicit exports to be onerous, especially since
I get an error, not incorrect results, if I forget to list one, albeit
only after the module is put to use rather than when it is compiled.

> This is about enabling optimizations, isn't it?  I really don't
> want to require people who don't care about the efficiency gains
> to have to take the trouble to list the implicit exports.  Make
> it optional.  Those that care can do the work and those that don't
> can ignore the issue.  In the absence of a declaration the
> implementator can put as much or as little effort as they like
> into constructing the list of potential exports.

It's not only about enabling optimizations, but also about enabling
static analyses in general.  In Chez Scheme, for example, it's about
enabling better compile-time error checking for things like incorrect
argument counts.  And it's also about security, since in the absense of
a recorded set of implicit exports, macros like the one below may yield
to macro parameters like caser unintended permission to reference and
maybe assign a module's local variables.

  (syntax-rules ()
    [(_ caser)
     (caser
       [(#\a) (helper1 ---)]
       [(#\b) (helper2 ---)]
       ---)])

Perhaps we can come up with an intuitive set of rules for when the system
will try to determine implicit exports automatically and how hard it
will work before it gives up, then require the programmer to specify
implicit exports in other situations.  Perhaps we can further allow the
programmer to specify implicit exports in all cases, with a warning
about the possible efficiency, diagnostic, and security consequences
of leaving the analysis to the expander.  But I think it's simpler and
better just to require that implicit exports always be listed.

Kent


More information about the R6RS mailing list