descriptor support for __get__ and __set__

Descriptor support for `__get__` and `__set__` in the `getattr`, `getclsattr`, and `callattr` paths.

- The `getattr` path follows the protocol described at https://docs.python.org/2/howto/descriptor.html. There are two cases: the object is an instance and the instance is a class.
  - For instances, It looks up attribute in the object's dictionary and the attribute from the class using `typeLookup`. In the latter, it looks for the `__get__` method, but if the attribute exists in _both_ it also checks that `__set__` exists.
  - For classes, it's simpler; it just looks if `__get__` exists in the looked-up item.
- The `getclsattr` path is sort of a mix - it looks up the attribute just in the class but will call `__get__` with the object rather than `None`.
- For `callattr`, the code for looking up the value seemed completely wrong (e.g., it was doing custom lookups through `__getattr__` before looking up the class object) so I scrapped that part. I figured this should basically share all logic with `getattr` or `getclsattr` as appropriate - except that it shouldn't wrap functions in instancemethods. So I refactored `getattr_internal` out into `getattr_internal_general` which takes an additional flag which species that it should not wrap functions, and `callattr` just calls that. (So `callattr` still does binding if necessary.) Similarly, I factored `clsattr_internal` into `clsattr_internal_general`.

One thing of note is that it currently doesn't rewrite the path where `callattr` calls `__get__`, since that involves _two_ function calls: one to `__get__` and another to the function that `__get__` returns. Of course, this path is basically just a getattr and a call, each of which could be written by itself, so this clearly isn't a fundamental limitation.

I got rid of `_handleClsAttr` which already had special-case descriptor logic for functions and member descriptors. Those cases are still handled specially though, just in getattr and getclsattr with the other descriptor logic.

Finally, for `setattr`, I check if `__set__` exists and if so call that.
Because the way it's set up now, it wouldn't work because there would be
guards in between the two `runtimeCall`s; we need to be done guarding
before we make the first call.

So we need to set it up so that any guards after `__get__`'s `runtimeCall`
jump to a place that knows that `__get__` has already been called, or
something.


On Thu, Aug 14, 2014 at 4:14 PM, Kevin Modzelewski <notifications@github.com
> wrote:

> In test/tests/descriptors_callattr_cls_ics.py:
>
> > @@ -0,0 +1,77 @@
> > +# expected: statfail
>
> I guess I don't why a single callattr should be more difficult to rewrite
> than a sequence of getattr then runtimeCall -- that's how it's defined,
> except that it can directly handle certain common cases (functions) and
> bypass the descriptor behavior.
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/dropbox/pyston/pull/123/files#r16272799>.
>