Commit 983a714a authored by Manuel Jacob's avatar Manuel Jacob

Big cleanup: make things more consistent (headers, whitespace, blank lines)...

Big cleanup: make things more consistent (headers, whitespace, blank lines) and use more useful sphinx features (e.g. for cross-referencing).
parent 9fa57048
=====================================
PyPy: Python in Python Implementation
PyPy: Python in Python Implementation
=====================================
Welcome to PyPy!
......@@ -23,6 +23,7 @@ and send us feedback!
the pypy-dev team <pypy-dev@python.org>
Building
========
......
......@@ -19,6 +19,4 @@ installation
usage
=====
`sample.py`_ explains in details how to use it.
.. _`sample.py`: http://codespeak.net/svn/pypy/dist/ctypes_configure/doc/sample.py
:source:`sample.py <ctypes_configure/doc/sample.py>` explains in details how to use it.
=======================
The ``__pypy__`` module
=======================
The ``__pypy__`` module is the main entry point to special features provided
by PyPy's standard interpreter. Its content depends on `configuration options`_
which may add new functionality and functions whose existence or non-existence
indicates the presence of such features.
by PyPy's standard interpreter. Its content depends on :doc:`configuration options <config/index>`
which may add new functionality and functions whose existence or non-existence
indicates the presence of such features.
.. _`configuration options`: config/index.html
Generally available functionality
=================================
---------------------------------
- ``internal_repr(obj)``: return the interpreter-level representation of an
object.
......@@ -18,28 +16,22 @@ Generally available functionality
It works like a simplified array of characters (actually, depending on the
configuration the ``array`` module internally uses this).
Transparent Proxy Functionality
===============================
-------------------------------
If `transparent proxies`_ are enabled (with :config:`objspace.std.withtproxy`)
If :ref:`transparent proxies <tproxy>` are enabled (with :config:`objspace.std.withtproxy`)
the following functions are put into ``__pypy__``:
- ``tproxy(typ, controller)``: Return something that looks like it is of type
typ. Its behaviour is completely controlled by the controller. See the docs
about `transparent proxies`_ for detail.
about :ref:`transparent proxies <tproxy>` for detail.
- ``get_tproxy_controller(obj)``: If obj is really a transparent proxy, return
its controller. Otherwise return None.
.. _`transparent proxies`: objspace-proxies.html#tproxy
Functionality available on py.py (not after translation)
========================================================
--------------------------------------------------------
- ``isfake(obj)``: returns True if ``obj`` is faked.
- ``interp_pdb()``: start a pdb at interpreter-level.
......@@ -6,6 +6,7 @@ Goals and Architecture Overview
This document gives an overview of the goals and architecture of PyPy.
See :doc:`getting started <getting-started>` for a practical introduction and starting points.
Mission statement
-----------------
......
===============================
The ``clr`` module for PyPy.NET
===============================
......@@ -8,8 +7,7 @@ still missing and its interface might change in next versions, but
it's still useful to experiment a bit with PyPy.NET.
PyPy.NET provides an import hook that lets you to import .NET namespaces
seamlessly as they were normal Python modules. Then,
seamlessly as they were normal Python modules. Then,
PyPY.NET native classes try to behave as much as possible in the
"expected" way both for the developers used to .NET and for the ones
used to Python.
......@@ -34,8 +32,9 @@ they exist in both worlds:
Moreover, all the usual Python features such as bound and unbound
methods are available as well.
Example of usage
================
----------------
Here is an example of interactive session using the ``clr`` module::
......@@ -52,8 +51,9 @@ Here is an example of interactive session using the ``clr`` module::
>>>> print obj.Count
3
Conversion of parameters
========================
------------------------
When calling a .NET method Python objects are converted to .NET
objects. Lots of effort have been taken to make the conversion as
......@@ -68,11 +68,12 @@ some sort of collection.
The opposite .NET to Python conversions happens for the values returned
by the methods. Again, primitive types are converted in a
straightforward way; non-primitive types are wrapped in a Python object,
straightforward way; non-primitive types are wrapped in a Python object,
so that they can be treated as usual.
Overload resolution
===================
-------------------
When calling an overloaded method, PyPy.NET tries to find the best
overload for the given arguments; for example, consider the
......@@ -94,7 +95,7 @@ TypeError exception is raised.
Generic classes
================
----------------
Generic classes are fully supported. To instantiate a generic class, you need
to use the ``[]`` notation::
......@@ -115,7 +116,7 @@ to use the ``[]`` notation::
External assemblies and Windows Forms
=====================================
-------------------------------------
By default, you can only import .NET namespaces that belongs to already loaded
assemblies. To load additional .NET assemblies, you can use
......
This diff is collapsed.
......@@ -195,7 +195,8 @@ latex_use_modindex = False
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None),
'rpython': ('http://rpython.readthedocs.org/en/improve-docs/', None)}
# -- Options for manpage output-------------------------------------------------
......
=============================
PyPy's Configuration Handling
=============================
......@@ -6,16 +5,17 @@ Due to more and more available configuration options it became quite annoying to
hand the necessary options to where they are actually used and even more
annoying to add new options. To circumvent these problems configuration
management was introduced. There all the necessary options are stored in a
configuration object, which is available nearly everywhere in the `RPython
configuration object, which is available nearly everywhere in the `RPython
toolchain`_ and in the standard interpreter so that adding new options becomes
trivial. Options are organized into a tree. Configuration objects can be
created in different ways, there is support for creating an optparse command
line parser automatically.
_`RPython toolchain`: translation.html
.. _RPython toolchain: https://rpython.readthedocs.org/
Main Assumption
===============
---------------
Configuration objects are produced at the entry points and handed down to
where they are actually used. This keeps configuration local but available
......@@ -24,7 +24,7 @@ command line.
API Details
===========
-----------
The handling of options is split into two parts: the description of which
options are available, what their possible values and defaults are and how they
......@@ -40,8 +40,9 @@ The Options are organized in a tree. Every option has a name, as does every
option group. The parts of the full name of the option are separated by dots:
e.g. ``config.translation.thread``.
Description of Options
----------------------
~~~~~~~~~~~~~~~~~~~~~~
All the constructors take a ``name`` and a ``doc`` argument as first arguments
to give the option or option group a name and to document it. Most constructors
......@@ -70,6 +71,7 @@ This class is used to group suboptions.
``children`` is a list of option descriptions (including
``OptionDescription`` instances for nested namespaces).
``ChoiceOption``
++++++++++++++++
......@@ -81,10 +83,11 @@ Represents a choice out of several objects. The option can also have the value
``requires`` is a dictionary mapping values to lists of of two-element
tuples.
``BoolOption``
++++++++++++++
Represents a choice between ``True`` and ``False``.
Represents a choice between ``True`` and ``False``.
``__init__(self, name, doc, default=None, requires=None, suggests=None, cmdline=DEFAULT, negation=True)``
``default`` specifies the default value of the option. ``requires`` is
......@@ -103,7 +106,6 @@ Represents a choice between ``True`` and ``False``.
Represents a choice of an integer.
``__init__(self, name, doc, default=None, cmdline=DEFAULT)``
``FloatOption``
......@@ -112,7 +114,6 @@ Represents a choice of an integer.
Represents a choice of a floating point number.
``__init__(self, name, doc, default=None, cmdline=DEFAULT)``
``StrOption``
......@@ -121,12 +122,10 @@ Represents a choice of a floating point number.
Represents the choice of a string.
``__init__(self, name, doc, default=None, cmdline=DEFAULT)``
Configuration Objects
---------------------
~~~~~~~~~~~~~~~~~~~~~
``Config`` objects hold the chosen values for the options (of the default,
if no choice was made). A ``Config`` object is described by an
......@@ -164,7 +163,7 @@ Description of the (useful) methods on ``Config``:
Production of optparse Parsers
------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To produce an optparse parser use the function ``to_optparse``. It will create
an option parser using callbacks in such a way that the config object used for
......@@ -182,10 +181,9 @@ creating the parser is updated automatically.
The usage of config objects in PyPy
===================================
-----------------------------------
The two large parts of PyPy, the Python interpreter and the `RPython
toolchain`_
The two large parts of PyPy, the Python interpreter and the RPython
toolchain, have two separate sets of options. The translation toolchain options
can be found on the ``config`` attribute of all ``TranslationContext``
instances and are described in :source:`rpython/config/translationoption.py`. The interpreter options
......
Contributors to PyPy
====================
......
This diff is collapsed.
==================
Backends for cppyy
==================
The cppyy module needs a backend to provide the C++ reflection information on
which the Python bindings are build.
The backend is called through a C-API, which can be found in the PyPy sources
in: `pypy/module/cppyy/include/capi.h`_.
in: :source:`pypy/module/cppyy/include/capi.h`.
There are two kinds of API calls: querying about reflection information, which
are used during the creation of Python-side constructs, and making the actual
calls into C++.
The objects passed around are all opaque: cppyy does not make any assumptions
about them, other than that the opaque handles can be copied.
Their definition, however, appears in two places: in the C code (in capi.h),
and on the RPython side (in `capi_types.py`_), so if they are changed, they
and on the RPython side (in :source:`capi_types.py <pypy/module/cppyy/capi/capi_types.py>`), so if they are changed, they
need to be changed on both sides.
.. _`pypy/module/cppyy/include/capi.h`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/include/capi.h
.. _`capi_types.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/capi_types.py
There are two places where selections in the RPython code affect the choice
(and use) of the backend.
The first is in `pypy/module/cppyy/capi/__init__.py`_::
The first is in :source:`pypy/module/cppyy/capi/__init__.py`::
# choose C-API access method:
from pypy.module.cppyy.capi.loadable_capi import *
......@@ -29,19 +25,15 @@ The first is in `pypy/module/cppyy/capi/__init__.py`_::
The default is the loadable C-API.
Comment it and uncomment the builtin C-API line, to use the builtin version.
.. _`pypy/module/cppyy/capi/__init__.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/__init__.py
Next, if the builtin C-API is chosen, the specific backend needs to be set as
well (default is Reflex).
This second choice is in `pypy/module/cppyy/capi/builtin_capi.py`_::
This second choice is in :source:`pypy/module/cppyy/capi/builtin_capi.py`::
import reflex_capi as backend
#import cint_capi as backend
After those choices have been made, built pypy-c as usual.
.. _`pypy/module/cppyy/capi/builtin_capi.py`: https://bitbucket.org/pypy/pypy/src/default/pypy/module/cppyy/capi/builtin_capi.py
When building pypy-c from source, keep the following in mind.
If the loadable_capi is chosen, no further prerequisites are needed.
However, for the build of the builtin_capi to succeed, the ``ROOTSYS``
......
====================================
Differences between PyPy and CPython
====================================
......@@ -19,21 +18,21 @@ List of extension modules that we support:
* Supported as built-in modules (in :source:`pypy/module/`):
__builtin__
`__pypy__`_
:doc:`__pypy__ <__pypy__-module>`
_ast
_codecs
_collections
`_continuation`_
`_ffi`_
:doc:`_continuation <stackless>`
:doc:`_ffi <ctypes-implementation>`
_hashlib
_io
_locale
_lsprof
_md5
`_minimal_curses`_
:doc:`_minimal_curses <config/objspace.usemodules._minimal_curses>`
_multiprocessing
_random
`_rawffi`_
:doc:`_rawffi <ctypes-implementation>`
_sha
_socket
_sre
......@@ -95,13 +94,7 @@ The extension modules (i.e. modules written in C, in the standard CPython)
that are neither mentioned above nor in :source:`lib_pypy/` are not available in PyPy.
(You may have a chance to use them anyway with `cpyext`_.)
.. the nonstandard modules are listed below...
.. _`__pypy__`: __pypy__-module.html
.. _`_continuation`: stackless.html
.. _`_ffi`: ctypes-implementation.html
.. _`_rawffi`: ctypes-implementation.html
.. _`_minimal_curses`: config/objspace.usemodules._minimal_curses.html
.. _`cpyext`: http://morepypy.blogspot.com/2010/04/using-cpython-extension-modules-with.html
.. _cpyext: http://morepypy.blogspot.com/2010/04/using-cpython-extension-modules-with.html
Differences related to garbage collection strategies
......@@ -213,6 +206,7 @@ but ``foo`` on CPython::
>>>> print d1['a']
42
Mutating classes of objects which are already used as dictionary keys
---------------------------------------------------------------------
......@@ -260,6 +254,7 @@ Unless this behavior is clearly present by design and
documented as such (as e.g. for hasattr()), in most cases PyPy
lets the exception propagate instead.
Object Identity of Primitive Values, ``is`` and ``id``
-------------------------------------------------------
......
============================
PyPy's ctypes implementation
============================
Summary
========
--------
Terminology:
......@@ -28,10 +27,11 @@ We reused the ``ctypes`` package version 1.0.2 as-is from CPython. We
implemented ``_ctypes`` which is a C module in CPython mostly in pure
Python based on a lower-level layer extension module ``_rawffi``.
.. _`libffi`: http://sources.redhat.com/libffi/
.. _libffi: http://sources.redhat.com/libffi/
Low-level part: ``_rawffi``
============================
---------------------------
This PyPy extension module (:source:`pypy/module/_rawffi`) exposes a simple interface
to create C objects (arrays and structures) and calling functions
......@@ -44,15 +44,17 @@ We tried to keep this module as small as possible. It is conceivable
that other implementations (e.g. Jython) could use our ctypes
implementation by writing their version of ``_rawffi``.
High-level parts
=================
-----------------
The reused ``ctypes`` package lives in ``lib_pypy/ctypes``. ``_ctypes``
implementing the same interface as ``_ctypes`` in CPython is in
``lib_pypy/_ctypes``.
Discussion and limitations
=============================
-----------------------------
Reimplementing ctypes features was in general possible. PyPy supports
pluggable garbage collectors, some of them are moving collectors, this
......@@ -90,13 +92,15 @@ current implementation:
between its primitive types and user subclasses
of its primitive types
Running application examples
==============================
------------------------------
`pyglet`_ is known to run. We also had some success with pygame-ctypes (which is no longer maintained) and with a snapshot of the experimental pysqlite-ctypes. We will only describe how to run the pyglet examples.
pyglet
-------
~~~~~~
We tried pyglet checking it out from its repository at revision 1984.
......@@ -131,17 +135,17 @@ We did not try the following examples:
- video.py needs avbin
- soundscape needs avbin
.. _`pyglet`: http://pyglet.org/
.. _pyglet: http://pyglet.org/
ctypes configure
=================
-----------------
We also released ``ctypes-configure``, which is an experimental package
trying to approach the portability issues of ctypes-based code.
idea
----
~~~~
One of ctypes problems is that ctypes programs are usually not very
platform-independent. We created ctypes_configure, which invokes c
......@@ -150,11 +154,11 @@ exact sizes of types (for example size_t), ``#defines``, exact outline of
structures etc. It replaces in this regard code generator (h2py).
installation
------------
~~~~~~~~~~~~
``easy_install ctypes_configure``
usage
-----
~~~~~
:source:`ctypes_configure/doc/sample.py` explains in details how to use it.
......@@ -22,7 +22,7 @@ Main tools for achieving this is:
* py.test - automated testing
* Mercurial - version control
* Transparent communication and documentation (mailinglists, IRC, tutorials
etc etc)
etc etc)
Sprint driven development:
......@@ -33,7 +33,7 @@ What is a sprint and why are we sprinting?
Originally the sprint methodology used in the Python community grew from
practices within Zope3 development. The definition of a sprint is "two-day or
three-day focused development session, in which developers pair off together
in a room and focus on building a particular subsystem".
in a room and focus on building a particular subsystem".
Other typical sprint factors:
......@@ -91,7 +91,7 @@ during conferences like PyCon and EuroPython, the team will have an easier
task of recruiting new talents to the team. It also vitalizes the community
and increases the contact between the different Python implementation
projects.
As always with methodologies you have to adapt them to fit your project (and
not the other way around which is much too common). The PyPy team have been
sprinting since early 2003 and have done 22 sprints so far, 19 in Europe, 2
......@@ -100,7 +100,7 @@ team and those are the one we are summarizing here.
How is it done?
+++++++++++++++
~~~~~~~~~~~~~~~
There are several aspects of a sprint. In the PyPy team we focus on:
1. Content (goal)
......@@ -171,7 +171,7 @@ There are several aspects of a sprint. In the PyPy team we focus on:
(or even better: in between so that the memory is fresh) a sprint report is
written by one of the developers and updated to codespeak, this is a kind
of summary of the entire sprint and it tells of the work done and the
people involved.
people involved.
One very important strategy when planning the venue is cost
efficiency. Keeping accommodation and food/travel costs as low as possible
......@@ -181,17 +181,17 @@ There are several aspects of a sprint. In the PyPy team we focus on:
(travel expenses and accommodation) and because most of the funding is so
called matched funding we pay for most of our expenses in our own
organizations and companies anyway.
4. Process - a typical PyPy sprint is 7 days with a break day in the
middle. Usually sprinters show up the day before the sprint starts. The
first day has a start up meeting, with tutorials if there are participants
first day has a start up meeting, with tutorials if there are participants
new to the project or if some new tool or feature have been implemented. A
short presentation of the participants and their background and
expectations is also good to do. Unfortunately there is always time spent
the first day, mostly in the morning when people arrive to get the internet
and server infrastructure up and running. That is why we are, through
documentation_, trying to get participants to set up the tools and
:doc:`documentation <getting-started>`, trying to get participants to set up the tools and
configurations needed before they arrive to the sprint.
Approximate hours being held are 10-17, but people tend to stay longer to
......@@ -224,10 +224,8 @@ There are several aspects of a sprint. In the PyPy team we focus on:
some middle ground - thus increases the importance of feedback.
.. _documentation: getting-started.html
Can I join in?
++++++++++++++
~~~~~~~~~~~~~~
Of course. Just follow the work on pypy-dev and if you specifically are
interested in information about our sprints - subscribe to
......@@ -236,4 +234,3 @@ pypy-sprint@codespeak.net and read the news on codespeak for announcements etc.
If you think we should sprint in your town - send us an email - we are very
interested in using sprints as away of making contact with active developers
(Python/compiler design etc)!
PyPy directory cross-reference
------------------------------
PyPy directory cross-reference
==============================
Here is a fully referenced alphabetical two-level deep
directory overview of PyPy:
Here is a fully referenced alphabetical two-level deep
directory overview of PyPy:
======================================== ============================================
Directory explanation/links
......@@ -21,120 +21,41 @@ Directory explanation/links
:source:`pypy/doc/discussion/` drafts of ideas and documentation
``doc/*/`` other specific documentation topics or tools
:source:`pypy/goal/` our :ref:`main PyPy-translation scripts <translate-pypy>`
live here
:source:`pypy/interpreter/` `bytecode interpreter`_ and related objects
(frames, functions, modules,...)
:source:`pypy/interpreter/` :doc:`bytecode interpreter <interpreter>` and related objects
(frames, functions, modules,...)
:source:`pypy/interpreter/pyparser/` interpreter-level Python source parser
:source:`pypy/interpreter/astcompiler/` interpreter-level bytecode compiler,
via an AST representation
:source:`pypy/module/` contains `mixed modules`_
implementing core modules with
:source:`pypy/module/` contains :ref:`mixed modules <mixed-modules>`
implementing core modules with
both application and interpreter level code.
Not all are finished and working. Use
the ``--withmod-xxx``
or ``--allworkingmodules`` translation
options.
:source:`pypy/objspace/` `object space`_ implementations
:source:`pypy/objspace/` :doc:`object space <objspace>` implementations
:source:`pypy/objspace/std/` the StdObjSpace_ implementing CPython's
:source:`pypy/objspace/std/` the :ref:`StdObjSpace <standard-object-space>` implementing CPython's
objects and types
:source:`pypy/tool/` various utilities and hacks used
from various places
from various places
:source:`pypy/tool/algo/` general-purpose algorithmic and mathematic
tools
:source:`pypy/tool/pytest/` support code for our `testing methods`_
:source:`rpython/annotator/` `type inferencing code`_ for
`RPython`_ programs
:source:`rpython/config/` handles the numerous options for RPython
:source:`rpython/flowspace/` the FlowObjSpace_ implementing
`abstract interpretation`_
:source:`rpython/rlib/` a `"standard library"`_ for RPython_
programs
:source:`rpython/rtyper/` the `RPython Typer`_
:source:`rpython/rtyper/lltypesystem/` the `low-level type system`_ for
C-like backends
:source:`rpython/rtyper/ootypesystem/` the `object-oriented type system`_
for OO backends
:source:`rpython/memory/` the `garbage collector`_ construction
framework
:source:`rpython/translator/` translation_ backends and support code
:source:`rpython/translator/backendopt/` general optimizations that run before a
backend generates code
:source:`rpython/translator/c/` the `GenC backend`_, producing C code
from an
RPython program (generally via the rtyper_)
:source:`rpython/translator/cli/` the `CLI backend`_ for `.NET`_
(Microsoft CLR or Mono_)
:source:`pypy/goal/` our `main PyPy-translation scripts`_
live here
:source:`rpython/translator/jvm/` the Java backend
:source:`rpython/translator/tool/` helper tools for translation
:source:`dotviewer/` `graph viewer`_
:source:`pypy/tool/pytest/` support code for our :ref:`testing methods <testing>`
``*/test/`` many directories have a test subdirectory
containing test
modules (see `Testing in PyPy`_)
containing test
modules (see :ref:`testing`)
``_cache/`` holds cache files from various purposes
======================================== ============================================
.. _`bytecode interpreter`: interpreter.html
.. _`Testing in PyPy`: coding-guide.html#testing-in-pypy
.. _`mixed modules`: coding-guide.html#mixed-modules
.. _`modules`: coding-guide.html#modules
.. _`basil`: http://people.cs.uchicago.edu/~jriehl/BasilTalk.pdf
.. _`object space`: objspace.html
.. _FlowObjSpace: objspace.html#the-flow-object-space
.. _`transparent proxies`: objspace-proxies.html#tproxy
.. _`Differences between PyPy and CPython`: cpython_differences.html
.. _`What PyPy can do for your objects`: objspace-proxies.html
.. _`Continulets and greenlets`: stackless.html
.. _StdObjSpace: objspace.html#the-standard-object-space
.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation
.. _`rpython`: coding-guide.html#rpython
.. _`type inferencing code`: translation.html#the-annotation-pass
.. _`RPython Typer`: translation.html#rpython-typer
.. _`testing methods`: coding-guide.html#testing-in-pypy
.. _`translation`: translation.html
.. _`GenC backend`: translation.html#genc
.. _`CLI backend`: cli-backend.html
.. _`py.py`: getting-started-python.html#the-py.py-interpreter
.. _`translatorshell.py`: getting-started-dev.html#try-out-the-translator
.. _JIT: jit/index.html
.. _`JIT Generation in PyPy`: jit/index.html
.. _`just-in-time compiler generator`: jit/index.html
.. _rtyper: rtyper.html
.. _`low-level type system`: rtyper.html#low-level-type
.. _`object-oriented type system`: rtyper.html#oo-type
.. _`garbage collector`: garbage_collection.html
.. _`main PyPy-translation scripts`: getting-started-python.html#translating-the-pypy-python-interpreter
.. _`.NET`: http://www.microsoft.com/net/
.. _Mono: http://www.mono-project.com/
.. _`"standard library"`: rlib.html
.. _`graph viewer`: getting-started-dev.html#try-out-the-translator
==============================================
Integration of PyPy with host Virtual Machines
==============================================
......@@ -10,8 +9,9 @@ Terminology disclaimer: both PyPy and .NET have the concept of
"wrapped" or "boxed" objects. To avoid confusion I will use "wrapping"
on the PyPy side and "boxing" on the .NET side.
General idea
============
------------
The goal is to find a way to efficiently integrate the PyPy
interpreter with the hosting environment such as .NET. What we would
......@@ -29,8 +29,9 @@ like to do includes but it's not limited to:
One possible solution is the "proxy" approach, in which we manually
(un)wrap/(un)box all the objects when they cross the border.
Example
-------
~~~~~~~
::
......@@ -43,8 +44,9 @@ In this case we need to take the intval field of W_IntObject, box it
to .NET System.Int32, call foo using reflection, then unbox the return
value and reconstruct a new (or reuse an existing one) W_IntObject.
The other approach
------------------
~~~~~~~~~~~~~~~~~~
The general idea to solve handle this problem is to split the
"stateful" and "behavioral" parts of wrapped objects, and use already
......@@ -57,7 +59,7 @@ reconstruct the pair.