[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