[pypy-dev] "Unwrap" Concidered Harmful

Armin Rigo arigo at tunes.org
Tue Sep 2 15:54:56 CEST 2003


Hello Rocco,

On Sat, Aug 23, 2003 at 09:00:58PM -0400, Rocco Moretti wrote:
> Maybe I overstate the subject line, but there are serious limitations
> on the .unwrap() concept.

Yes, I agree with your analysis. I actually think that we are using unwrap() 
for different purposes at different places, and we should clearly mark these 
differences...

> all information about value. So there is no way we can say that
> s.unwrap(s.wrap(x)) == x.

I am now coming closer to the idea that wrap() should be redefined as well, 
because it is used not only on simple types but also on "internal interpreter 
structures", like code objects plus others more internals than that.

I now tend to think about wrap(x) as 'I want you, object space, to build 
something that acts as reference to my object x'. The unwrap() operation would 
then only be defined on objects that have been wrapped, and the object space 
should somehow guarantee that "unwrap(wrap(x)) is x".

Now this is not exactly the way wrap() and unwrap() are used in the current
code base. We also use wrap(x) when x is a simple immutable object, to build 
simple blackboxed objects (ints, strs...). And we also use unwrap(x) when we 
expect 'x' to be such an object, to get a plain int or str out of a blackbox.

Moreover, in the light of the current refactoring on branch 'builtinrefactor',
I think it would make sense to say that the object spaces (all of them,
whatever their semantics are) have to support a particular kind of
interpreter-controlled semantics on complex objects created by wrap(). In
other words, the interpreter would control what occurs when object space
operations involve such an object. So, for example, space.getattr() on a
wrapped code object would force the object space to call back the interpreter,
which would perform the necessary attribute-reading operation. (I think it is
reasonable to say that the object space should not be responsible for that
because it is essentially an interpreter-controlled object. The same would go
for, say, wrapped frames, tracebacks, whatever, possibly module objects too. 
There is no need to code logic for these in each and every object space, as we
are now doing in std and ann).

In summary we'd have two usages for wrap()/unwrap() -- let's try to figure out
some better names:

 * wrap(x) -> create a blackboxed reference for the interpreter object x
 * unwrap(w_x,ExpectedType) -> inverse of the previous operation
 * newint(i), newstr(s)... -> create simple object space objects
 * unwrap(w_x,int), unwrap(w_x,str) -> inverse of the previous operation

In this idea, unwrap() would be a bit like PyArg_ParseTuple in that it would
check what type of interpreter-level object it is supposed to return, possibly
raising a TypeError.

Still this doesn't directly address the whole issue of application-level
helpers. I tend to think now that we should be very careful before using
app-level helpers. All the troubles we had with the argument-parsing one were
solved when Holger finally convinced me to just try to write the damn thing
directly at interpreter-level, which I did without too much trouble after all. 
I'd currently advice to reserve app-level helpers to tasks that could really
be thought of as part of a user program. For example I think it is ok to keep
at app-level the logic that decodes what a 'raise' statement really meant,
e.g. 'raise X, Y' -> 'raise X(Y)', because this is the kind of thing that a
user could write in a small general-purpose function of his program if it
wasn't built in the interpreter.


A bientôt,

Armin.



More information about the Pypy-dev mailing list