1.1 --- a/encoders.py Sat Feb 18 18:52:04 2017 +0100
1.2 +++ b/encoders.py Sat Feb 18 20:13:47 2017 +0100
1.3 @@ -215,7 +215,7 @@
1.4 )
1.5
1.6 context_ops = (
1.7 - "<context>", "<set_context>",
1.8 + "<context>", "<set_context>", "<test_context>",
1.9 )
1.10
1.11 reference_acting_ops = attribute_ops + checked_ops + typename_ops
2.1 --- a/optimiser.py Sat Feb 18 18:52:04 2017 +0100
2.2 +++ b/optimiser.py Sat Feb 18 20:13:47 2017 +0100
2.3 @@ -533,6 +533,8 @@
2.4 if context_test == "test":
2.5 if final_method in ("static", "static-invoke"):
2.6 emit(("__load_static_test", context_var, origin))
2.7 + elif final_method == "access-invoke":
2.8 + emit(("<test_context>", context_var, accessor))
2.9 else:
2.10 emit(("__test_context", context_var, accessor))
2.11
3.1 --- a/templates/ops.c Sat Feb 18 18:52:04 2017 +0100
3.2 +++ b/templates/ops.c Sat Feb 18 20:13:47 2017 +0100
3.3 @@ -198,14 +198,16 @@
3.4
3.5 /* Context-related operations. */
3.6
3.7 -__attr __test_context(__ref context, __attr attr)
3.8 +int __test_context_update(__ref context, __attr attr)
3.9 {
3.10 + /* Return whether the context should be updated for the attribute. */
3.11 +
3.12 __ref attrcontext = __CONTEXT_AS_VALUE(attr).value;
3.13
3.14 /* Preserve any existing null or instance context. */
3.15
3.16 if ((attrcontext == 0) || __is_instance(attrcontext))
3.17 - return attr;
3.18 + return 0;
3.19
3.20 /* Test any instance context against the context employed by the
3.21 attribute. */
3.22 @@ -213,7 +215,7 @@
3.23 if (__is_instance(context))
3.24 {
3.25 if (__test_common_instance(context, __TYPEPOS(attrcontext), __TYPECODE(attrcontext)))
3.26 - return __update_context(context, attr);
3.27 + return 1;
3.28 else
3.29 __raise_type_error();
3.30 }
3.31 @@ -221,11 +223,21 @@
3.32 /* Test for access to a type class attribute using a type instance. */
3.33
3.34 if (__test_specific_type(attrcontext, &__TYPE_CLASS_TYPE) && __is_type_instance(context))
3.35 - return __update_context(context, attr);
3.36 + return 1;
3.37
3.38 /* Otherwise, preserve the attribute as retrieved. */
3.39
3.40 - return attr;
3.41 + return 0;
3.42 +}
3.43 +
3.44 +__attr __test_context(__ref context, __attr attr)
3.45 +{
3.46 + /* Update the context or return the unchanged attribute. */
3.47 +
3.48 + if (__test_context_update(context, attr))
3.49 + return __update_context(context, attr);
3.50 + else
3.51 + return attr;
3.52 }
3.53
3.54 __attr __update_context(__ref context, __attr attr)
4.1 --- a/templates/ops.h Sat Feb 18 18:52:04 2017 +0100
4.2 +++ b/templates/ops.h Sat Feb 18 20:13:47 2017 +0100
4.3 @@ -70,9 +70,13 @@
4.4
4.5 /* Context-related operations. */
4.6
4.7 +int __test_context_update(__ref context, __attr attr);
4.8 __attr __test_context(__ref context, __attr attr);
4.9 __attr __update_context(__ref context, __attr attr);
4.10
4.11 +#define __test_context_set(__TARGET, __CONTEXT, __ATTR) \
4.12 + (__test_context_update(__CONTEXT, __ATTR) ? (__set_context(__TARGET, (__attr) {.value=__CONTEXT}), __ATTR) : __ATTR)
4.13 +
4.14 #define __get_context(__TARGET) (__tmp_contexts[__TARGET])
4.15 #define __set_context(__TARGET, __ATTR) (__tmp_contexts[__TARGET] = (__ATTR).value)
4.16 #define __set_private_context(__ATTR) (__tmp_private_context = (__ATTR).value)
5.1 --- a/translator.py Sat Feb 18 18:52:04 2017 +0100
5.2 +++ b/translator.py Sat Feb 18 20:13:47 2017 +0100
5.3 @@ -789,6 +789,7 @@
5.4 # Mappings to be replaced by those given below.
5.5
5.6 "<context>" : "__tmp_contexts",
5.7 + "<test_context>" : "__tmp_contexts",
5.8 "<set_context>" : "__tmp_contexts",
5.9 "<set_private_context>" : "__tmp_private_context",
5.10 "<set_accessor>" : "__tmp_value",
5.11 @@ -797,6 +798,7 @@
5.12
5.13 self.op_subs = {
5.14 "<context>" : "__get_context",
5.15 + "<test_context>" : "__test_context_set",
5.16 "<set_context>" : "__set_context",
5.17 "<set_private_context>" : "__set_private_context",
5.18 "<set_accessor>" : "__set_accessor",