[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Chicken-hackers] [PATCH] Simplify module registration a little by remov
[Chicken-hackers] [PATCH] Simplify module registration a little by removing special handling for primitives
Sun, 20 Jul 2014 17:05:39 +0200
I was digging into #1131 again today. So far, I haven't had much luck
trying to untangle the way modules and macros interact, but I did
manage to find a possible way to simplify the way primitives are
handled by the module system!
First, here's a little background on how things currently work as I
When a "primitive" module (like chicken, scheme, extras, etc) is
registered, it marks all its identifiers as being primitive by creating
an alias which is prefixed with "#%". This alias doesn't really *do*
anything, except serve as a sort of anchor to ensure that the name won't
be looked up in the current module. Instead, whenever a primitive
alias is encountered, lookup is short-cut and the alias is replaced by
the core primitive. This hack is required because the primitives are
not defined inside proper modules (which would cause them to be defined
as, "scheme#foo") but as globals. This is wired into the module
system by pseudo-modules (the aforementioned "primitive modules").
For example, the "scheme" pseudo-module defines +. When the module
is registered, it will mark the symbol #%+ as ##core#primitive with
value +. The module's export list contains "+", which maps to "#%+".
Then, when a module which uses the scheme module is being defined,
all references to + are rewritten to #%+. When the module is
resolved, all #%+ are rewritten back to +. So, in the compiled output
where modules don't exist anymore, you only see references to the global
variable "+", which usually holds the procedure implemented by the
Contrast this with the "numbers" egg. This module defines +, which is
automatically rewritten to numbers#+ because numbers is a proper module.
Its export list maps "+" to "numbers#+". When another module is defined
which imports numbers, all its references to + are rewritten to
numbers#+. This _stays_ like that when the module is resolved and in
the compiled output: the numbers implementation library will define the
global variable "numbers#+" which holds the bignum-aware plus procedure.
Now, when a module like r7rs re-exports a primitive procedure like, say,
"error", its generated import library will map error to #%error.
Then, ##sys#register-compiled-module will detect that this is an aliased
reference to the primitive "error", and cause the module's meta
expressions to register the alias like that (so that when this module
is imported by another, it will know about these aliases). However,
the r7rs module's import library itself will already load the primitive
"scheme" module as well, which will already take care of registering
the alias. So I think the primitive detection code can be removed.
This is what the attached patch does; it is a worthwhile simplification
of ##sys#register-compiled-module, I think. I'm just not 100% sure
whether this analysis is correct because this module stuff still
confuses me. Any feedback would be appreciated!
This differentiation between primitive and non-primitive values is a
little unfortunate, and I eventually hope to get rid of that, but
that's trickier than you might expect: we want to continue supporting
R5RS code and any program which doesn't make use of modules at all.
And there, you can do things like (set! + "foo") to overwrite the
implementation. The simplest way I can think of to do this with the
current code base is to change library.scm to actually _define_ a global
variable called #%+, and to make that the primitive. Any reference
to + in toplevel code gets rewritten to #%+, and the module system can
do the same through the mechanism we already have. Anyway, that's for
another day but I wanted to put it out there for y'all to consider.
Description: Text document
- [Chicken-hackers] [PATCH] Simplify module registration a little by removing special handling for primitives,
Peter Bex <=