[PEAK] Self-bootstrapping generic functions
Phillip J. Eby
pje at telecommunity.com
Wed Sep 6 00:31:14 EDT 2006
Another design thought re: PEAK-Rules... One of the trickier bits of
peak.rules.core right now is that there are some special hacks to support
the use of generic functions to implement generic functions. It occured to
me this evening that there is a more "generic" way to deal with the
problem, such that the generic function framework can easily be made
incrementally smarter by adding rules to the functions that implement
generic functions.
Has your head exploded yet? No? Read on. :)
In PEAK-Rules, an Engine object sets the bytecode of a generic function to
some generated code. I've been thinking that when the generated code
becomes invalid (e.g. due to adding a new rule to the function), the engine
would replace it with some code to trigger a rebuild operation. The
problem is that if the rebuild operation needs to *call* the function
that's being rebuilt, it won't work right because the data structures may
be in mid-modification. In other words, a generic function currently isn't
re-entrant while it's modifying itself. :)
So, it finally occurred to me that there's a relatively simple way to fix
this. When an Engine sets the bytecode of the function to be the "rebuild"
code instead of the "execute" code, it should *save* the existing "execute"
code. The "rebuild" code would acquire a re-entrant lock (for safe
threading) and check to see if a rebuild is currently in progress for that
generic function. If it is, it should release the lock and invoke the
*old* "execute" code, rather than trying to rebuild again.
The net result is that any generic function that needs to be called during
its own rebuild or regeneration (by whatever convoluted path) will simply
use its last valid definition to do so. And, that "last valid definition"
can include a default implementation written as a non-generic function,
which is fairly key to bootstrapping the core itself. That is, I can write
a few functions that contain isinstance() tests or simple delegation to
object attributes, and that should be sufficient to get the most
fundamental operations working in skeletal form (e.g. just enough to do
type-only dispatching).
There does seem to be one minor flaw in this process which is that if you
add say, 5 new rules to a generic function, and you want rule 3 to be
available when rule 5 is being processed. In this model, you would have to
*invoke* the function somewhere between adding rule 3 and adding rule 5, in
order to ensure that it's available. But this could perhaps be worked
around by offering some way to force rebuilding without invocation. It's a
little kludgy, but it would only be needed in areas of extreme meta-ness
anyway. :) And in any case, it beats the heck out of the current
hardwired kludge to check whether you're rebuilding the one generic
function that's currently needed to rebuild or execute generic functions. :)
More information about the PEAK
mailing list