1.1 --- a/encoders.py Sun Feb 19 18:39:11 2017 +0100
1.2 +++ b/encoders.py Sun Feb 19 19:06:22 2017 +0100
1.3 @@ -215,7 +215,7 @@
1.4 )
1.5
1.6 context_ops = (
1.7 - "<context>", "<set_context>", "<test_context>", "<test_context_static>",
1.8 + "<context>", "<set_context>", "<test_context_revert>", "<test_context_static>",
1.9 )
1.10
1.11 reference_acting_ops = attribute_ops + checked_ops + typename_ops
2.1 --- a/optimiser.py Sun Feb 19 18:39:11 2017 +0100
2.2 +++ b/optimiser.py Sun Feb 19 19:06:22 2017 +0100
2.3 @@ -567,7 +567,7 @@
2.4 # immediately invoked attribute.
2.5
2.6 elif final_method == "access-invoke":
2.7 - emit(("<test_context>", context_var, accessor))
2.8 + emit(("<test_context_revert>", context_var, accessor))
2.9
2.10 # Test the context and update the attribute details if
2.11 # appropriate.
3.1 --- a/templates/ops.c Sun Feb 19 18:39:11 2017 +0100
3.2 +++ b/templates/ops.c Sun Feb 19 19:06:22 2017 +0100
3.3 @@ -214,6 +214,10 @@
3.4
3.5 if (__is_instance(context))
3.6 {
3.7 + /* Obtain the special class attribute position and code identifying the
3.8 + attribute context's class, inspecting the context instance for
3.9 + compatibility. */
3.10 +
3.11 if (__test_common_instance(context, __TYPEPOS(attrcontext), __TYPECODE(attrcontext)))
3.12 return 1;
3.13 else
4.1 --- a/templates/ops.h Sun Feb 19 18:39:11 2017 +0100
4.2 +++ b/templates/ops.h Sun Feb 19 19:06:22 2017 +0100
4.3 @@ -74,12 +74,20 @@
4.4 __attr __test_context(__ref context, __attr attr);
4.5 __attr __update_context(__ref context, __attr attr);
4.6
4.7 -#define __test_context_set(__TARGET, __CONTEXT, __ATTR) \
4.8 - (__test_context_update(__CONTEXT, __ATTR) ? (__set_context(__TARGET, (__attr) {.value=__CONTEXT}), __ATTR) : __ATTR)
4.9 +/* Revert the local context to that employed by the attribute if the supplied
4.10 + context is not appropriate. */
4.11 +
4.12 +#define __test_context_revert(__TARGET, __CONTEXT, __ATTR) \
4.13 + (__test_context_update(__CONTEXT, __ATTR) \
4.14 + ? __ATTR \
4.15 + : (__set_context(__TARGET, __CONTEXT_AS_VALUE(__ATTR)), __ATTR))
4.16 +
4.17 +/* Set the local context to the specified context if appropriate. */
4.18
4.19 #define __test_context_static(__TARGET, __CONTEXT, __REF) \
4.20 - (__test_context_update(__CONTEXT, (__attr) {.value=__REF}) ? \
4.21 - (__set_context(__TARGET, (__attr) {.value=__CONTEXT}), (__attr) {.value=__REF}) : (__attr) {.value=__REF})
4.22 + (__test_context_update(__CONTEXT, (__attr) {.value=__REF}) \
4.23 + ? (__set_context(__TARGET, (__attr) {.value=__CONTEXT}), (__attr) {.value=__REF}) \
4.24 + : (__attr) {.value=__REF})
4.25
4.26 #define __get_context(__TARGET) (__tmp_contexts[__TARGET])
4.27 #define __set_context(__TARGET, __ATTR) (__tmp_contexts[__TARGET] = (__ATTR).value)
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/tests/methods_rebound.py Sun Feb 19 19:06:22 2017 +0100
5.3 @@ -0,0 +1,21 @@
5.4 +class C:
5.5 + def f(self):
5.6 + print self
5.7 + return self.value()
5.8 +
5.9 + def value(self):
5.10 + return 123
5.11 +
5.12 +c = C()
5.13 +
5.14 +class D:
5.15 + f = c.f
5.16 +
5.17 +d = D()
5.18 +
5.19 +print c.f.__name__ # f
5.20 +print c.f() # <__main__.C instance>
5.21 + # 123
5.22 +print d.f.__name__ # wrapper
5.23 +print d.f() # <__main__.C instance>
5.24 + # 123
6.1 --- a/translator.py Sun Feb 19 18:39:11 2017 +0100
6.2 +++ b/translator.py Sun Feb 19 19:06:22 2017 +0100
6.3 @@ -789,7 +789,7 @@
6.4 # Mappings to be replaced by those given below.
6.5
6.6 "<context>" : "__tmp_contexts",
6.7 - "<test_context>" : "__tmp_contexts",
6.8 + "<test_context_revert>" : "__tmp_contexts",
6.9 "<test_context_static>" : "__tmp_contexts",
6.10 "<set_context>" : "__tmp_contexts",
6.11 "<set_private_context>" : "__tmp_private_context",
6.12 @@ -799,7 +799,7 @@
6.13
6.14 self.op_subs = {
6.15 "<context>" : "__get_context",
6.16 - "<test_context>" : "__test_context_set",
6.17 + "<test_context_revert>" : "__test_context_revert",
6.18 "<test_context_static>" : "__test_context_static",
6.19 "<set_context>" : "__set_context",
6.20 "<set_private_context>" : "__set_private_context",