Author: Manuel Jacob Branch: kill-multimethod Changeset: r69439:0d2003298f8b Date: 2014-02-25 18:34 +0100 http://bitbucket.org/pypy/pypy/changeset/0d2003298f8b/
Log: Remove multimethods sections from documentation. diff --git a/pypy/doc/objspace.rst b/pypy/doc/objspace.rst --- a/pypy/doc/objspace.rst +++ b/pypy/doc/objspace.rst @@ -384,105 +384,6 @@ .. _`Standard Interpreter Optimizations`: interpreter-optimizations.html -Multimethods ------------- - -The Standard Object Space allows multiple object implementations per -Python type - this is based on multimethods_. For a description of the -multimethod variant that we implemented and which features it supports, -see the comment at the start of `pypy/objspace/std/multimethod.py`_. However, multimethods -alone are not enough for the Standard Object Space: the complete picture -spans several levels in order to emulate the exact Python semantics. - -Consider the example of the ``space.getitem(w_a, w_b)`` operation, -corresponding to the application-level syntax ``a[b]``. The Standard -Object Space contains a corresponding ``getitem`` multimethod and a -family of functions that implement the multimethod for various -combination of argument classes - more precisely, for various -combinations of the *interpreter-level* classes of the arguments. Here -are some examples of functions implementing the ``getitem`` -multimethod: - -* ``getitem__Tuple_ANY``: called when the first argument is a - W_TupleObject, this function converts its second argument to an - integer and performs tuple indexing. - -* ``getitem__Tuple_Slice``: called when the first argument is a - W_TupleObject and the second argument is a W_SliceObject. This - version takes precedence over the previous one if the indexing is - done with a slice object, and performs tuple slicing instead. - -* ``getitem__String_Slice``: called when the first argument is a - W_StringObject and the second argument is a slice object. - -Note how the multimethod dispatch logic helps writing new object -implementations without having to insert hooks into existing code. Note -first how we could have defined a regular method-based API that new -object implementations must provide, and call these methods from the -space operations. The problem with this approach is that some Python -operators are naturally binary or N-ary. Consider for example the -addition operation: for the basic string implementation it is a simple -concatenation-by-copy, but it can have a rather more subtle -implementation for strings done as ropes. It is also likely that -concatenating a basic string with a rope string could have its own -dedicated implementation - and yet another implementation for a rope -string with a basic string. With multimethods, we can have an -orthogonally-defined implementation for each combination. - -The multimethods mechanism also supports delegate functions, which are -converters between two object implementations. The dispatch logic knows -how to insert calls to delegates if it encounters combinations of -interp-level classes which is not directly implemented. For example, we -have no specific implementation for the concatenation of a basic string -and a StringSlice object; when the user adds two such strings, then the -StringSlice object is converted to a basic string (that is, a -temporarily copy is built), and the concatenation is performed on the -resulting pair of basic strings. This is similar to the C++ method -overloading resolution mechanism (but occurs at runtime). - -.. _multimethods: http://en.wikipedia.org/wiki/Multimethods - - -Multimethod slicing -------------------- - -The complete picture is more complicated because the Python object model -is based on *descriptors*: the types ``int``, ``str``, etc. must have -methods ``__add__``, ``__mul__``, etc. that take two arguments including -the ``self``. These methods must perform the operation or return -``NotImplemented`` if the second argument is not of a type that it -doesn't know how to handle. - -The Standard Object Space creates these methods by *slicing* the -multimethod tables. Each method is automatically generated from a -subset of the registered implementations of the corresponding -multimethod. This slicing is performed on the first argument, in order -to keep only the implementations whose first argument's -interpreter-level class matches the declared Python-level type. - -For example, in a baseline PyPy, ``int.__add__`` is just calling the -function ``add__Int_Int``, which is the only registered implementation -for ``add`` whose first argument is an implementation of the ``int`` -Python type. On the other hand, if we enable integers implemented as -tagged pointers, then there is another matching implementation: -``add__SmallInt_SmallInt``. In this case, the Python-level method -``int.__add__`` is implemented by trying to dispatch between these two -functions based on the interp-level type of the two arguments. - -Similarly, the reverse methods (``__radd__`` and others) are obtained by -slicing the multimethod tables to keep only the functions whose *second* -argument has the correct Python-level type. - -Slicing is actually a good way to reproduce the details of the object -model as seen in CPython: slicing is attempted for every Python types -for every multimethod, but the ``__xyz__`` Python methods are only put -into the Python type when the resulting slices are not empty. This is -how our ``int`` type has no ``__getitem__`` method, for example. -Additionally, slicing ensures that ``5 .__add__(6L)`` correctly returns -``NotImplemented`` (because this particular slice does not include -``add__Long_Long`` and there is no ``add__Int_Long``), which leads to -``6L.__radd__(5)`` being called, as in CPython. - .. _`Flow Object Space`: The Flow Object Space _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
